root/drivers/misc/habanalabs/hwmon.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hl_build_hwmon_channel_info
  2. hl_read
  3. hl_write
  4. hl_is_visible
  5. hl_get_temperature
  6. hl_get_voltage
  7. hl_get_current
  8. hl_get_fan_speed
  9. hl_get_pwm_info
  10. hl_set_pwm_info
  11. hl_hwmon_init
  12. hl_hwmon_fini

   1 // SPDX-License-Identifier: GPL-2.0
   2 
   3 /*
   4  * Copyright 2016-2019 HabanaLabs, Ltd.
   5  * All Rights Reserved.
   6  */
   7 
   8 #include "habanalabs.h"
   9 
  10 #include <linux/pci.h>
  11 #include <linux/hwmon.h>
  12 
  13 #define SENSORS_PKT_TIMEOUT             1000000 /* 1s */
  14 #define HWMON_NR_SENSOR_TYPES           (hwmon_pwm + 1)
  15 
  16 int hl_build_hwmon_channel_info(struct hl_device *hdev,
  17                                 struct armcp_sensor *sensors_arr)
  18 {
  19         u32 counts[HWMON_NR_SENSOR_TYPES] = {0};
  20         u32 *sensors_by_type[HWMON_NR_SENSOR_TYPES] = {NULL};
  21         u32 sensors_by_type_next_index[HWMON_NR_SENSOR_TYPES] = {0};
  22         struct hwmon_channel_info **channels_info;
  23         u32 num_sensors_for_type, num_active_sensor_types = 0,
  24                         arr_size = 0, *curr_arr;
  25         enum hwmon_sensor_types type;
  26         int rc, i, j;
  27 
  28         for (i = 0 ; i < ARMCP_MAX_SENSORS ; i++) {
  29                 type = le32_to_cpu(sensors_arr[i].type);
  30 
  31                 if ((type == 0) && (sensors_arr[i].flags == 0))
  32                         break;
  33 
  34                 if (type >= HWMON_NR_SENSOR_TYPES) {
  35                         dev_err(hdev->dev,
  36                                 "Got wrong sensor type %d from device\n", type);
  37                         return -EINVAL;
  38                 }
  39 
  40                 counts[type]++;
  41                 arr_size++;
  42         }
  43 
  44         for (i = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++) {
  45                 if (counts[i] == 0)
  46                         continue;
  47 
  48                 num_sensors_for_type = counts[i] + 1;
  49                 curr_arr = kcalloc(num_sensors_for_type, sizeof(*curr_arr),
  50                                 GFP_KERNEL);
  51                 if (!curr_arr) {
  52                         rc = -ENOMEM;
  53                         goto sensors_type_err;
  54                 }
  55 
  56                 num_active_sensor_types++;
  57                 sensors_by_type[i] = curr_arr;
  58         }
  59 
  60         for (i = 0 ; i < arr_size ; i++) {
  61                 type = le32_to_cpu(sensors_arr[i].type);
  62                 curr_arr = sensors_by_type[type];
  63                 curr_arr[sensors_by_type_next_index[type]++] =
  64                                 le32_to_cpu(sensors_arr[i].flags);
  65         }
  66 
  67         channels_info = kcalloc(num_active_sensor_types + 1,
  68                         sizeof(*channels_info), GFP_KERNEL);
  69         if (!channels_info) {
  70                 rc = -ENOMEM;
  71                 goto channels_info_array_err;
  72         }
  73 
  74         for (i = 0 ; i < num_active_sensor_types ; i++) {
  75                 channels_info[i] = kzalloc(sizeof(*channels_info[i]),
  76                                 GFP_KERNEL);
  77                 if (!channels_info[i]) {
  78                         rc = -ENOMEM;
  79                         goto channel_info_err;
  80                 }
  81         }
  82 
  83         for (i = 0, j = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++) {
  84                 if (!sensors_by_type[i])
  85                         continue;
  86 
  87                 channels_info[j]->type = i;
  88                 channels_info[j]->config = sensors_by_type[i];
  89                 j++;
  90         }
  91 
  92         hdev->hl_chip_info->info =
  93                         (const struct hwmon_channel_info **)channels_info;
  94 
  95         return 0;
  96 
  97 channel_info_err:
  98         for (i = 0 ; i < num_active_sensor_types ; i++)
  99                 if (channels_info[i]) {
 100                         kfree(channels_info[i]->config);
 101                         kfree(channels_info[i]);
 102                 }
 103         kfree(channels_info);
 104 channels_info_array_err:
 105 sensors_type_err:
 106         for (i = 0 ; i < HWMON_NR_SENSOR_TYPES ; i++)
 107                 kfree(sensors_by_type[i]);
 108 
 109         return rc;
 110 }
 111 
 112 static int hl_read(struct device *dev, enum hwmon_sensor_types type,
 113                         u32 attr, int channel, long *val)
 114 {
 115         struct hl_device *hdev = dev_get_drvdata(dev);
 116 
 117         if (hl_device_disabled_or_in_reset(hdev))
 118                 return -ENODEV;
 119 
 120         switch (type) {
 121         case hwmon_temp:
 122                 switch (attr) {
 123                 case hwmon_temp_input:
 124                 case hwmon_temp_max:
 125                 case hwmon_temp_crit:
 126                 case hwmon_temp_max_hyst:
 127                 case hwmon_temp_crit_hyst:
 128                         break;
 129                 default:
 130                         return -EINVAL;
 131                 }
 132 
 133                 *val = hl_get_temperature(hdev, channel, attr);
 134                 break;
 135         case hwmon_in:
 136                 switch (attr) {
 137                 case hwmon_in_input:
 138                 case hwmon_in_min:
 139                 case hwmon_in_max:
 140                         break;
 141                 default:
 142                         return -EINVAL;
 143                 }
 144 
 145                 *val = hl_get_voltage(hdev, channel, attr);
 146                 break;
 147         case hwmon_curr:
 148                 switch (attr) {
 149                 case hwmon_curr_input:
 150                 case hwmon_curr_min:
 151                 case hwmon_curr_max:
 152                         break;
 153                 default:
 154                         return -EINVAL;
 155                 }
 156 
 157                 *val = hl_get_current(hdev, channel, attr);
 158                 break;
 159         case hwmon_fan:
 160                 switch (attr) {
 161                 case hwmon_fan_input:
 162                 case hwmon_fan_min:
 163                 case hwmon_fan_max:
 164                         break;
 165                 default:
 166                         return -EINVAL;
 167                 }
 168                 *val = hl_get_fan_speed(hdev, channel, attr);
 169                 break;
 170         case hwmon_pwm:
 171                 switch (attr) {
 172                 case hwmon_pwm_input:
 173                 case hwmon_pwm_enable:
 174                         break;
 175                 default:
 176                         return -EINVAL;
 177                 }
 178                 *val = hl_get_pwm_info(hdev, channel, attr);
 179                 break;
 180         default:
 181                 return -EINVAL;
 182         }
 183         return 0;
 184 }
 185 
 186 static int hl_write(struct device *dev, enum hwmon_sensor_types type,
 187                         u32 attr, int channel, long val)
 188 {
 189         struct hl_device *hdev = dev_get_drvdata(dev);
 190 
 191         if (hl_device_disabled_or_in_reset(hdev))
 192                 return -ENODEV;
 193 
 194         switch (type) {
 195         case hwmon_pwm:
 196                 switch (attr) {
 197                 case hwmon_pwm_input:
 198                 case hwmon_pwm_enable:
 199                         break;
 200                 default:
 201                         return -EINVAL;
 202                 }
 203                 hl_set_pwm_info(hdev, channel, attr, val);
 204                 break;
 205         default:
 206                 return -EINVAL;
 207         }
 208         return 0;
 209 }
 210 
 211 static umode_t hl_is_visible(const void *data, enum hwmon_sensor_types type,
 212                                 u32 attr, int channel)
 213 {
 214         switch (type) {
 215         case hwmon_temp:
 216                 switch (attr) {
 217                 case hwmon_temp_input:
 218                 case hwmon_temp_max:
 219                 case hwmon_temp_max_hyst:
 220                 case hwmon_temp_crit:
 221                 case hwmon_temp_crit_hyst:
 222                         return 0444;
 223                 }
 224                 break;
 225         case hwmon_in:
 226                 switch (attr) {
 227                 case hwmon_in_input:
 228                 case hwmon_in_min:
 229                 case hwmon_in_max:
 230                         return 0444;
 231                 }
 232                 break;
 233         case hwmon_curr:
 234                 switch (attr) {
 235                 case hwmon_curr_input:
 236                 case hwmon_curr_min:
 237                 case hwmon_curr_max:
 238                         return 0444;
 239                 }
 240                 break;
 241         case hwmon_fan:
 242                 switch (attr) {
 243                 case hwmon_fan_input:
 244                 case hwmon_fan_min:
 245                 case hwmon_fan_max:
 246                         return 0444;
 247                 }
 248                 break;
 249         case hwmon_pwm:
 250                 switch (attr) {
 251                 case hwmon_pwm_input:
 252                 case hwmon_pwm_enable:
 253                         return 0644;
 254                 }
 255                 break;
 256         default:
 257                 break;
 258         }
 259         return 0;
 260 }
 261 
 262 static const struct hwmon_ops hl_hwmon_ops = {
 263         .is_visible = hl_is_visible,
 264         .read = hl_read,
 265         .write = hl_write
 266 };
 267 
 268 long hl_get_temperature(struct hl_device *hdev, int sensor_index, u32 attr)
 269 {
 270         struct armcp_packet pkt;
 271         long result;
 272         int rc;
 273 
 274         memset(&pkt, 0, sizeof(pkt));
 275 
 276         pkt.ctl = cpu_to_le32(ARMCP_PACKET_TEMPERATURE_GET <<
 277                                 ARMCP_PKT_CTL_OPCODE_SHIFT);
 278         pkt.sensor_index = __cpu_to_le16(sensor_index);
 279         pkt.type = __cpu_to_le16(attr);
 280 
 281         rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
 282                         SENSORS_PKT_TIMEOUT, &result);
 283 
 284         if (rc) {
 285                 dev_err(hdev->dev,
 286                         "Failed to get temperature from sensor %d, error %d\n",
 287                         sensor_index, rc);
 288                 result = 0;
 289         }
 290 
 291         return result;
 292 }
 293 
 294 long hl_get_voltage(struct hl_device *hdev, int sensor_index, u32 attr)
 295 {
 296         struct armcp_packet pkt;
 297         long result;
 298         int rc;
 299 
 300         memset(&pkt, 0, sizeof(pkt));
 301 
 302         pkt.ctl = cpu_to_le32(ARMCP_PACKET_VOLTAGE_GET <<
 303                                 ARMCP_PKT_CTL_OPCODE_SHIFT);
 304         pkt.sensor_index = __cpu_to_le16(sensor_index);
 305         pkt.type = __cpu_to_le16(attr);
 306 
 307         rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
 308                                         SENSORS_PKT_TIMEOUT, &result);
 309 
 310         if (rc) {
 311                 dev_err(hdev->dev,
 312                         "Failed to get voltage from sensor %d, error %d\n",
 313                         sensor_index, rc);
 314                 result = 0;
 315         }
 316 
 317         return result;
 318 }
 319 
 320 long hl_get_current(struct hl_device *hdev, int sensor_index, u32 attr)
 321 {
 322         struct armcp_packet pkt;
 323         long result;
 324         int rc;
 325 
 326         memset(&pkt, 0, sizeof(pkt));
 327 
 328         pkt.ctl = cpu_to_le32(ARMCP_PACKET_CURRENT_GET <<
 329                                 ARMCP_PKT_CTL_OPCODE_SHIFT);
 330         pkt.sensor_index = __cpu_to_le16(sensor_index);
 331         pkt.type = __cpu_to_le16(attr);
 332 
 333         rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
 334                                         SENSORS_PKT_TIMEOUT, &result);
 335 
 336         if (rc) {
 337                 dev_err(hdev->dev,
 338                         "Failed to get current from sensor %d, error %d\n",
 339                         sensor_index, rc);
 340                 result = 0;
 341         }
 342 
 343         return result;
 344 }
 345 
 346 long hl_get_fan_speed(struct hl_device *hdev, int sensor_index, u32 attr)
 347 {
 348         struct armcp_packet pkt;
 349         long result;
 350         int rc;
 351 
 352         memset(&pkt, 0, sizeof(pkt));
 353 
 354         pkt.ctl = cpu_to_le32(ARMCP_PACKET_FAN_SPEED_GET <<
 355                                 ARMCP_PKT_CTL_OPCODE_SHIFT);
 356         pkt.sensor_index = __cpu_to_le16(sensor_index);
 357         pkt.type = __cpu_to_le16(attr);
 358 
 359         rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
 360                                         SENSORS_PKT_TIMEOUT, &result);
 361 
 362         if (rc) {
 363                 dev_err(hdev->dev,
 364                         "Failed to get fan speed from sensor %d, error %d\n",
 365                         sensor_index, rc);
 366                 result = 0;
 367         }
 368 
 369         return result;
 370 }
 371 
 372 long hl_get_pwm_info(struct hl_device *hdev, int sensor_index, u32 attr)
 373 {
 374         struct armcp_packet pkt;
 375         long result;
 376         int rc;
 377 
 378         memset(&pkt, 0, sizeof(pkt));
 379 
 380         pkt.ctl = cpu_to_le32(ARMCP_PACKET_PWM_GET <<
 381                                 ARMCP_PKT_CTL_OPCODE_SHIFT);
 382         pkt.sensor_index = __cpu_to_le16(sensor_index);
 383         pkt.type = __cpu_to_le16(attr);
 384 
 385         rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
 386                                         SENSORS_PKT_TIMEOUT, &result);
 387 
 388         if (rc) {
 389                 dev_err(hdev->dev,
 390                         "Failed to get pwm info from sensor %d, error %d\n",
 391                         sensor_index, rc);
 392                 result = 0;
 393         }
 394 
 395         return result;
 396 }
 397 
 398 void hl_set_pwm_info(struct hl_device *hdev, int sensor_index, u32 attr,
 399                         long value)
 400 {
 401         struct armcp_packet pkt;
 402         int rc;
 403 
 404         memset(&pkt, 0, sizeof(pkt));
 405 
 406         pkt.ctl = cpu_to_le32(ARMCP_PACKET_PWM_SET <<
 407                                 ARMCP_PKT_CTL_OPCODE_SHIFT);
 408         pkt.sensor_index = __cpu_to_le16(sensor_index);
 409         pkt.type = __cpu_to_le16(attr);
 410         pkt.value = cpu_to_le64(value);
 411 
 412         rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
 413                                         SENSORS_PKT_TIMEOUT, NULL);
 414 
 415         if (rc)
 416                 dev_err(hdev->dev,
 417                         "Failed to set pwm info to sensor %d, error %d\n",
 418                         sensor_index, rc);
 419 }
 420 
 421 int hl_hwmon_init(struct hl_device *hdev)
 422 {
 423         struct device *dev = hdev->pdev ? &hdev->pdev->dev : hdev->dev;
 424         struct asic_fixed_properties *prop = &hdev->asic_prop;
 425         int rc;
 426 
 427         if ((hdev->hwmon_initialized) || !(hdev->fw_loading))
 428                 return 0;
 429 
 430         if (hdev->hl_chip_info->info) {
 431                 hdev->hl_chip_info->ops = &hl_hwmon_ops;
 432 
 433                 hdev->hwmon_dev = hwmon_device_register_with_info(dev,
 434                                         prop->armcp_info.card_name, hdev,
 435                                         hdev->hl_chip_info, NULL);
 436                 if (IS_ERR(hdev->hwmon_dev)) {
 437                         rc = PTR_ERR(hdev->hwmon_dev);
 438                         dev_err(hdev->dev,
 439                                 "Unable to register hwmon device: %d\n", rc);
 440                         return rc;
 441                 }
 442 
 443                 dev_info(hdev->dev, "%s: add sensors information\n",
 444                         dev_name(hdev->hwmon_dev));
 445 
 446                 hdev->hwmon_initialized = true;
 447         } else {
 448                 dev_info(hdev->dev, "no available sensors\n");
 449         }
 450 
 451         return 0;
 452 }
 453 
 454 void hl_hwmon_fini(struct hl_device *hdev)
 455 {
 456         if (!hdev->hwmon_initialized)
 457                 return;
 458 
 459         hwmon_device_unregister(hdev->hwmon_dev);
 460 }

/* [<][>][^][v][top][bottom][index][help] */