root/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c

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

DEFINITIONS

This source file includes following definitions.
  1. mlxsw_hwmon_get_attr_index
  2. mlxsw_hwmon_temp_show
  3. mlxsw_hwmon_temp_max_show
  4. mlxsw_hwmon_temp_rst_store
  5. mlxsw_hwmon_fan_rpm_show
  6. mlxsw_hwmon_fan_fault_show
  7. mlxsw_hwmon_pwm_show
  8. mlxsw_hwmon_pwm_store
  9. mlxsw_hwmon_module_temp_show
  10. mlxsw_hwmon_module_temp_fault_show
  11. mlxsw_hwmon_module_temp_critical_show
  12. mlxsw_hwmon_module_temp_emergency_show
  13. mlxsw_hwmon_module_temp_label_show
  14. mlxsw_hwmon_gbox_temp_label_show
  15. mlxsw_hwmon_attr_add
  16. mlxsw_hwmon_temp_init
  17. mlxsw_hwmon_fans_init
  18. mlxsw_hwmon_module_init
  19. mlxsw_hwmon_gearbox_init
  20. mlxsw_hwmon_init
  21. mlxsw_hwmon_fini

   1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2 /* Copyright (c) 2015-2018 Mellanox Technologies. All rights reserved */
   3 
   4 #include <linux/kernel.h>
   5 #include <linux/types.h>
   6 #include <linux/device.h>
   7 #include <linux/sysfs.h>
   8 #include <linux/hwmon.h>
   9 #include <linux/err.h>
  10 #include <linux/sfp.h>
  11 
  12 #include "core.h"
  13 #include "core_env.h"
  14 
  15 #define MLXSW_HWMON_TEMP_SENSOR_MAX_COUNT 127
  16 #define MLXSW_HWMON_ATTR_COUNT (MLXSW_HWMON_TEMP_SENSOR_MAX_COUNT * 4 + \
  17                                 MLXSW_MFCR_TACHOS_MAX + MLXSW_MFCR_PWMS_MAX)
  18 
  19 struct mlxsw_hwmon_attr {
  20         struct device_attribute dev_attr;
  21         struct mlxsw_hwmon *hwmon;
  22         unsigned int type_index;
  23         char name[32];
  24 };
  25 
  26 static int mlxsw_hwmon_get_attr_index(int index, int count)
  27 {
  28         if (index >= count)
  29                 return index % count + MLXSW_REG_MTMP_GBOX_INDEX_MIN;
  30 
  31         return index;
  32 }
  33 
  34 struct mlxsw_hwmon {
  35         struct mlxsw_core *core;
  36         const struct mlxsw_bus_info *bus_info;
  37         struct device *hwmon_dev;
  38         struct attribute_group group;
  39         const struct attribute_group *groups[2];
  40         struct attribute *attrs[MLXSW_HWMON_ATTR_COUNT + 1];
  41         struct mlxsw_hwmon_attr hwmon_attrs[MLXSW_HWMON_ATTR_COUNT];
  42         unsigned int attrs_count;
  43         u8 sensor_count;
  44         u8 module_sensor_count;
  45 };
  46 
  47 static ssize_t mlxsw_hwmon_temp_show(struct device *dev,
  48                                      struct device_attribute *attr,
  49                                      char *buf)
  50 {
  51         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
  52                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
  53         struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
  54         char mtmp_pl[MLXSW_REG_MTMP_LEN];
  55         int temp, index;
  56         int err;
  57 
  58         index = mlxsw_hwmon_get_attr_index(mlwsw_hwmon_attr->type_index,
  59                                            mlxsw_hwmon->module_sensor_count);
  60         mlxsw_reg_mtmp_pack(mtmp_pl, index, false, false);
  61         err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl);
  62         if (err) {
  63                 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query temp sensor\n");
  64                 return err;
  65         }
  66         mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
  67         return sprintf(buf, "%d\n", temp);
  68 }
  69 
  70 static ssize_t mlxsw_hwmon_temp_max_show(struct device *dev,
  71                                          struct device_attribute *attr,
  72                                          char *buf)
  73 {
  74         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
  75                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
  76         struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
  77         char mtmp_pl[MLXSW_REG_MTMP_LEN];
  78         int temp_max, index;
  79         int err;
  80 
  81         index = mlxsw_hwmon_get_attr_index(mlwsw_hwmon_attr->type_index,
  82                                            mlxsw_hwmon->module_sensor_count);
  83         mlxsw_reg_mtmp_pack(mtmp_pl, index, false, false);
  84         err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl);
  85         if (err) {
  86                 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query temp sensor\n");
  87                 return err;
  88         }
  89         mlxsw_reg_mtmp_unpack(mtmp_pl, NULL, &temp_max, NULL);
  90         return sprintf(buf, "%d\n", temp_max);
  91 }
  92 
  93 static ssize_t mlxsw_hwmon_temp_rst_store(struct device *dev,
  94                                           struct device_attribute *attr,
  95                                           const char *buf, size_t len)
  96 {
  97         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
  98                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
  99         struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
 100         char mtmp_pl[MLXSW_REG_MTMP_LEN];
 101         unsigned long val;
 102         int index;
 103         int err;
 104 
 105         err = kstrtoul(buf, 10, &val);
 106         if (err)
 107                 return err;
 108         if (val != 1)
 109                 return -EINVAL;
 110 
 111         index = mlxsw_hwmon_get_attr_index(mlwsw_hwmon_attr->type_index,
 112                                            mlxsw_hwmon->module_sensor_count);
 113         mlxsw_reg_mtmp_pack(mtmp_pl, index, true, true);
 114         err = mlxsw_reg_write(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl);
 115         if (err) {
 116                 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to reset temp sensor history\n");
 117                 return err;
 118         }
 119         return len;
 120 }
 121 
 122 static ssize_t mlxsw_hwmon_fan_rpm_show(struct device *dev,
 123                                         struct device_attribute *attr,
 124                                         char *buf)
 125 {
 126         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
 127                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
 128         struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
 129         char mfsm_pl[MLXSW_REG_MFSM_LEN];
 130         int err;
 131 
 132         mlxsw_reg_mfsm_pack(mfsm_pl, mlwsw_hwmon_attr->type_index);
 133         err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mfsm), mfsm_pl);
 134         if (err) {
 135                 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query fan\n");
 136                 return err;
 137         }
 138         return sprintf(buf, "%u\n", mlxsw_reg_mfsm_rpm_get(mfsm_pl));
 139 }
 140 
 141 static ssize_t mlxsw_hwmon_fan_fault_show(struct device *dev,
 142                                           struct device_attribute *attr,
 143                                           char *buf)
 144 {
 145         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
 146                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
 147         struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
 148         char fore_pl[MLXSW_REG_FORE_LEN];
 149         bool fault;
 150         int err;
 151 
 152         err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(fore), fore_pl);
 153         if (err) {
 154                 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query fan\n");
 155                 return err;
 156         }
 157         mlxsw_reg_fore_unpack(fore_pl, mlwsw_hwmon_attr->type_index, &fault);
 158 
 159         return sprintf(buf, "%u\n", fault);
 160 }
 161 
 162 static ssize_t mlxsw_hwmon_pwm_show(struct device *dev,
 163                                     struct device_attribute *attr,
 164                                     char *buf)
 165 {
 166         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
 167                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
 168         struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
 169         char mfsc_pl[MLXSW_REG_MFSC_LEN];
 170         int err;
 171 
 172         mlxsw_reg_mfsc_pack(mfsc_pl, mlwsw_hwmon_attr->type_index, 0);
 173         err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mfsc), mfsc_pl);
 174         if (err) {
 175                 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query PWM\n");
 176                 return err;
 177         }
 178         return sprintf(buf, "%u\n",
 179                        mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl));
 180 }
 181 
 182 static ssize_t mlxsw_hwmon_pwm_store(struct device *dev,
 183                                      struct device_attribute *attr,
 184                                      const char *buf, size_t len)
 185 {
 186         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
 187                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
 188         struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
 189         char mfsc_pl[MLXSW_REG_MFSC_LEN];
 190         unsigned long val;
 191         int err;
 192 
 193         err = kstrtoul(buf, 10, &val);
 194         if (err)
 195                 return err;
 196         if (val > 255)
 197                 return -EINVAL;
 198 
 199         mlxsw_reg_mfsc_pack(mfsc_pl, mlwsw_hwmon_attr->type_index, val);
 200         err = mlxsw_reg_write(mlxsw_hwmon->core, MLXSW_REG(mfsc), mfsc_pl);
 201         if (err) {
 202                 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to write PWM\n");
 203                 return err;
 204         }
 205         return len;
 206 }
 207 
 208 static ssize_t mlxsw_hwmon_module_temp_show(struct device *dev,
 209                                             struct device_attribute *attr,
 210                                             char *buf)
 211 {
 212         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
 213                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
 214         struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
 215         char mtmp_pl[MLXSW_REG_MTMP_LEN];
 216         u8 module;
 217         int temp;
 218         int err;
 219 
 220         module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count;
 221         mlxsw_reg_mtmp_pack(mtmp_pl, MLXSW_REG_MTMP_MODULE_INDEX_MIN + module,
 222                             false, false);
 223         err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl);
 224         if (err)
 225                 return err;
 226         mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
 227 
 228         return sprintf(buf, "%d\n", temp);
 229 }
 230 
 231 static ssize_t mlxsw_hwmon_module_temp_fault_show(struct device *dev,
 232                                                   struct device_attribute *attr,
 233                                                   char *buf)
 234 {
 235         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
 236                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
 237         struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
 238         char mtbr_pl[MLXSW_REG_MTBR_LEN] = {0};
 239         u8 module, fault;
 240         u16 temp;
 241         int err;
 242 
 243         module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count;
 244         mlxsw_reg_mtbr_pack(mtbr_pl, MLXSW_REG_MTBR_BASE_MODULE_INDEX + module,
 245                             1);
 246         err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtbr), mtbr_pl);
 247         if (err) {
 248                 dev_err(dev, "Failed to query module temperature sensor\n");
 249                 return err;
 250         }
 251 
 252         mlxsw_reg_mtbr_temp_unpack(mtbr_pl, 0, &temp, NULL);
 253 
 254         /* Update status and temperature cache. */
 255         switch (temp) {
 256         case MLXSW_REG_MTBR_BAD_SENS_INFO:
 257                 /* Untrusted cable is connected. Reading temperature from its
 258                  * sensor is faulty.
 259                  */
 260                 fault = 1;
 261                 break;
 262         case MLXSW_REG_MTBR_NO_CONN: /* fall-through */
 263         case MLXSW_REG_MTBR_NO_TEMP_SENS: /* fall-through */
 264         case MLXSW_REG_MTBR_INDEX_NA:
 265         default:
 266                 fault = 0;
 267                 break;
 268         }
 269 
 270         return sprintf(buf, "%u\n", fault);
 271 }
 272 
 273 static ssize_t
 274 mlxsw_hwmon_module_temp_critical_show(struct device *dev,
 275                                       struct device_attribute *attr, char *buf)
 276 {
 277         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
 278                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
 279         struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
 280         int temp;
 281         u8 module;
 282         int err;
 283 
 284         module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count;
 285         err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, module,
 286                                                    SFP_TEMP_HIGH_WARN, &temp);
 287         if (err) {
 288                 dev_err(dev, "Failed to query module temperature thresholds\n");
 289                 return err;
 290         }
 291 
 292         return sprintf(buf, "%u\n", temp);
 293 }
 294 
 295 static ssize_t
 296 mlxsw_hwmon_module_temp_emergency_show(struct device *dev,
 297                                        struct device_attribute *attr,
 298                                        char *buf)
 299 {
 300         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
 301                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
 302         struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
 303         u8 module;
 304         int temp;
 305         int err;
 306 
 307         module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count;
 308         err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, module,
 309                                                    SFP_TEMP_HIGH_ALARM, &temp);
 310         if (err) {
 311                 dev_err(dev, "Failed to query module temperature thresholds\n");
 312                 return err;
 313         }
 314 
 315         return sprintf(buf, "%u\n", temp);
 316 }
 317 
 318 static ssize_t
 319 mlxsw_hwmon_module_temp_label_show(struct device *dev,
 320                                    struct device_attribute *attr,
 321                                    char *buf)
 322 {
 323         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
 324                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
 325 
 326         return sprintf(buf, "front panel %03u\n",
 327                        mlwsw_hwmon_attr->type_index);
 328 }
 329 
 330 static ssize_t
 331 mlxsw_hwmon_gbox_temp_label_show(struct device *dev,
 332                                  struct device_attribute *attr,
 333                                  char *buf)
 334 {
 335         struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
 336                         container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
 337         struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
 338         int index = mlwsw_hwmon_attr->type_index -
 339                     mlxsw_hwmon->module_sensor_count + 1;
 340 
 341         return sprintf(buf, "gearbox %03u\n", index);
 342 }
 343 
 344 enum mlxsw_hwmon_attr_type {
 345         MLXSW_HWMON_ATTR_TYPE_TEMP,
 346         MLXSW_HWMON_ATTR_TYPE_TEMP_MAX,
 347         MLXSW_HWMON_ATTR_TYPE_TEMP_RST,
 348         MLXSW_HWMON_ATTR_TYPE_FAN_RPM,
 349         MLXSW_HWMON_ATTR_TYPE_FAN_FAULT,
 350         MLXSW_HWMON_ATTR_TYPE_PWM,
 351         MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE,
 352         MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT,
 353         MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT,
 354         MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG,
 355         MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL,
 356         MLXSW_HWMON_ATTR_TYPE_TEMP_GBOX_LABEL,
 357 };
 358 
 359 static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon,
 360                                  enum mlxsw_hwmon_attr_type attr_type,
 361                                  unsigned int type_index, unsigned int num) {
 362         struct mlxsw_hwmon_attr *mlxsw_hwmon_attr;
 363         unsigned int attr_index;
 364 
 365         attr_index = mlxsw_hwmon->attrs_count;
 366         mlxsw_hwmon_attr = &mlxsw_hwmon->hwmon_attrs[attr_index];
 367 
 368         switch (attr_type) {
 369         case MLXSW_HWMON_ATTR_TYPE_TEMP:
 370                 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_temp_show;
 371                 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
 372                 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
 373                          "temp%u_input", num + 1);
 374                 break;
 375         case MLXSW_HWMON_ATTR_TYPE_TEMP_MAX:
 376                 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_temp_max_show;
 377                 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
 378                 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
 379                          "temp%u_highest", num + 1);
 380                 break;
 381         case MLXSW_HWMON_ATTR_TYPE_TEMP_RST:
 382                 mlxsw_hwmon_attr->dev_attr.store = mlxsw_hwmon_temp_rst_store;
 383                 mlxsw_hwmon_attr->dev_attr.attr.mode = 0200;
 384                 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
 385                          "temp%u_reset_history", num + 1);
 386                 break;
 387         case MLXSW_HWMON_ATTR_TYPE_FAN_RPM:
 388                 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_fan_rpm_show;
 389                 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
 390                 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
 391                          "fan%u_input", num + 1);
 392                 break;
 393         case MLXSW_HWMON_ATTR_TYPE_FAN_FAULT:
 394                 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_fan_fault_show;
 395                 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
 396                 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
 397                          "fan%u_fault", num + 1);
 398                 break;
 399         case MLXSW_HWMON_ATTR_TYPE_PWM:
 400                 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_pwm_show;
 401                 mlxsw_hwmon_attr->dev_attr.store = mlxsw_hwmon_pwm_store;
 402                 mlxsw_hwmon_attr->dev_attr.attr.mode = 0644;
 403                 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
 404                          "pwm%u", num + 1);
 405                 break;
 406         case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE:
 407                 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_module_temp_show;
 408                 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
 409                 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
 410                          "temp%u_input", num + 1);
 411                 break;
 412         case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT:
 413                 mlxsw_hwmon_attr->dev_attr.show =
 414                                         mlxsw_hwmon_module_temp_fault_show;
 415                 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
 416                 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
 417                          "temp%u_fault", num + 1);
 418                 break;
 419         case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT:
 420                 mlxsw_hwmon_attr->dev_attr.show =
 421                         mlxsw_hwmon_module_temp_critical_show;
 422                 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
 423                 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
 424                          "temp%u_crit", num + 1);
 425                 break;
 426         case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG:
 427                 mlxsw_hwmon_attr->dev_attr.show =
 428                         mlxsw_hwmon_module_temp_emergency_show;
 429                 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
 430                 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
 431                          "temp%u_emergency", num + 1);
 432                 break;
 433         case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL:
 434                 mlxsw_hwmon_attr->dev_attr.show =
 435                         mlxsw_hwmon_module_temp_label_show;
 436                 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
 437                 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
 438                          "temp%u_label", num + 1);
 439                 break;
 440         case MLXSW_HWMON_ATTR_TYPE_TEMP_GBOX_LABEL:
 441                 mlxsw_hwmon_attr->dev_attr.show =
 442                         mlxsw_hwmon_gbox_temp_label_show;
 443                 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
 444                 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
 445                          "temp%u_label", num + 1);
 446                 break;
 447         default:
 448                 WARN_ON(1);
 449         }
 450 
 451         mlxsw_hwmon_attr->type_index = type_index;
 452         mlxsw_hwmon_attr->hwmon = mlxsw_hwmon;
 453         mlxsw_hwmon_attr->dev_attr.attr.name = mlxsw_hwmon_attr->name;
 454         sysfs_attr_init(&mlxsw_hwmon_attr->dev_attr.attr);
 455 
 456         mlxsw_hwmon->attrs[attr_index] = &mlxsw_hwmon_attr->dev_attr.attr;
 457         mlxsw_hwmon->attrs_count++;
 458 }
 459 
 460 static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon *mlxsw_hwmon)
 461 {
 462         char mtcap_pl[MLXSW_REG_MTCAP_LEN] = {0};
 463         char mtmp_pl[MLXSW_REG_MTMP_LEN];
 464         int i;
 465         int err;
 466 
 467         err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtcap), mtcap_pl);
 468         if (err) {
 469                 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to get number of temp sensors\n");
 470                 return err;
 471         }
 472         mlxsw_hwmon->sensor_count = mlxsw_reg_mtcap_sensor_count_get(mtcap_pl);
 473         for (i = 0; i < mlxsw_hwmon->sensor_count; i++) {
 474                 mlxsw_reg_mtmp_pack(mtmp_pl, i, true, true);
 475                 err = mlxsw_reg_write(mlxsw_hwmon->core,
 476                                       MLXSW_REG(mtmp), mtmp_pl);
 477                 if (err) {
 478                         dev_err(mlxsw_hwmon->bus_info->dev, "Failed to setup temp sensor number %d\n",
 479                                 i);
 480                         return err;
 481                 }
 482                 mlxsw_hwmon_attr_add(mlxsw_hwmon,
 483                                      MLXSW_HWMON_ATTR_TYPE_TEMP, i, i);
 484                 mlxsw_hwmon_attr_add(mlxsw_hwmon,
 485                                      MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, i, i);
 486                 mlxsw_hwmon_attr_add(mlxsw_hwmon,
 487                                      MLXSW_HWMON_ATTR_TYPE_TEMP_RST, i, i);
 488         }
 489         return 0;
 490 }
 491 
 492 static int mlxsw_hwmon_fans_init(struct mlxsw_hwmon *mlxsw_hwmon)
 493 {
 494         char mfcr_pl[MLXSW_REG_MFCR_LEN] = {0};
 495         enum mlxsw_reg_mfcr_pwm_frequency freq;
 496         unsigned int type_index;
 497         unsigned int num;
 498         u16 tacho_active;
 499         u8 pwm_active;
 500         int err;
 501 
 502         err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mfcr), mfcr_pl);
 503         if (err) {
 504                 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to get to probe PWMs and Tachometers\n");
 505                 return err;
 506         }
 507         mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active);
 508         num = 0;
 509         for (type_index = 0; type_index < MLXSW_MFCR_TACHOS_MAX; type_index++) {
 510                 if (tacho_active & BIT(type_index)) {
 511                         mlxsw_hwmon_attr_add(mlxsw_hwmon,
 512                                              MLXSW_HWMON_ATTR_TYPE_FAN_RPM,
 513                                              type_index, num);
 514                         mlxsw_hwmon_attr_add(mlxsw_hwmon,
 515                                              MLXSW_HWMON_ATTR_TYPE_FAN_FAULT,
 516                                              type_index, num++);
 517                 }
 518         }
 519         num = 0;
 520         for (type_index = 0; type_index < MLXSW_MFCR_PWMS_MAX; type_index++) {
 521                 if (pwm_active & BIT(type_index))
 522                         mlxsw_hwmon_attr_add(mlxsw_hwmon,
 523                                              MLXSW_HWMON_ATTR_TYPE_PWM,
 524                                              type_index, num++);
 525         }
 526         return 0;
 527 }
 528 
 529 static int mlxsw_hwmon_module_init(struct mlxsw_hwmon *mlxsw_hwmon)
 530 {
 531         unsigned int module_count = mlxsw_core_max_ports(mlxsw_hwmon->core);
 532         char pmlp_pl[MLXSW_REG_PMLP_LEN] = {0};
 533         int i, index;
 534         u8 width;
 535         int err;
 536 
 537         if (!mlxsw_core_res_query_enabled(mlxsw_hwmon->core))
 538                 return 0;
 539 
 540         /* Add extra attributes for module temperature. Sensor index is
 541          * assigned to sensor_count value, while all indexed before
 542          * sensor_count are already utilized by the sensors connected through
 543          * mtmp register by mlxsw_hwmon_temp_init().
 544          */
 545         index = mlxsw_hwmon->sensor_count;
 546         for (i = 1; i < module_count; i++) {
 547                 mlxsw_reg_pmlp_pack(pmlp_pl, i);
 548                 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(pmlp),
 549                                       pmlp_pl);
 550                 if (err) {
 551                         dev_err(mlxsw_hwmon->bus_info->dev, "Failed to read module index %d\n",
 552                                 i);
 553                         return err;
 554                 }
 555                 width = mlxsw_reg_pmlp_width_get(pmlp_pl);
 556                 if (!width)
 557                         continue;
 558                 mlxsw_hwmon_attr_add(mlxsw_hwmon,
 559                                      MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE, index,
 560                                      index);
 561                 mlxsw_hwmon_attr_add(mlxsw_hwmon,
 562                                      MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT,
 563                                      index, index);
 564                 mlxsw_hwmon_attr_add(mlxsw_hwmon,
 565                                      MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT,
 566                                      index, index);
 567                 mlxsw_hwmon_attr_add(mlxsw_hwmon,
 568                                      MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG,
 569                                      index, index);
 570                 mlxsw_hwmon_attr_add(mlxsw_hwmon,
 571                                      MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL,
 572                                      index, index);
 573                 index++;
 574         }
 575         mlxsw_hwmon->module_sensor_count = index;
 576 
 577         return 0;
 578 }
 579 
 580 static int mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon *mlxsw_hwmon)
 581 {
 582         int index, max_index, sensor_index;
 583         char mgpir_pl[MLXSW_REG_MGPIR_LEN];
 584         char mtmp_pl[MLXSW_REG_MTMP_LEN];
 585         u8 gbox_num;
 586         int err;
 587 
 588         mlxsw_reg_mgpir_pack(mgpir_pl);
 589         err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mgpir), mgpir_pl);
 590         if (err)
 591                 return err;
 592 
 593         mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, NULL, NULL);
 594         if (!gbox_num)
 595                 return 0;
 596 
 597         index = mlxsw_hwmon->module_sensor_count;
 598         max_index = mlxsw_hwmon->module_sensor_count + gbox_num;
 599         while (index < max_index) {
 600                 sensor_index = index % mlxsw_hwmon->module_sensor_count +
 601                                MLXSW_REG_MTMP_GBOX_INDEX_MIN;
 602                 mlxsw_reg_mtmp_pack(mtmp_pl, sensor_index, true, true);
 603                 err = mlxsw_reg_write(mlxsw_hwmon->core,
 604                                       MLXSW_REG(mtmp), mtmp_pl);
 605                 if (err) {
 606                         dev_err(mlxsw_hwmon->bus_info->dev, "Failed to setup temp sensor number %d\n",
 607                                 sensor_index);
 608                         return err;
 609                 }
 610                 mlxsw_hwmon_attr_add(mlxsw_hwmon, MLXSW_HWMON_ATTR_TYPE_TEMP,
 611                                      index, index);
 612                 mlxsw_hwmon_attr_add(mlxsw_hwmon,
 613                                      MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, index,
 614                                      index);
 615                 mlxsw_hwmon_attr_add(mlxsw_hwmon,
 616                                      MLXSW_HWMON_ATTR_TYPE_TEMP_RST, index,
 617                                      index);
 618                 mlxsw_hwmon_attr_add(mlxsw_hwmon,
 619                                      MLXSW_HWMON_ATTR_TYPE_TEMP_GBOX_LABEL,
 620                                      index, index);
 621                 index++;
 622         }
 623 
 624         return 0;
 625 }
 626 
 627 int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core,
 628                      const struct mlxsw_bus_info *mlxsw_bus_info,
 629                      struct mlxsw_hwmon **p_hwmon)
 630 {
 631         struct mlxsw_hwmon *mlxsw_hwmon;
 632         struct device *hwmon_dev;
 633         int err;
 634 
 635         mlxsw_hwmon = kzalloc(sizeof(*mlxsw_hwmon), GFP_KERNEL);
 636         if (!mlxsw_hwmon)
 637                 return -ENOMEM;
 638         mlxsw_hwmon->core = mlxsw_core;
 639         mlxsw_hwmon->bus_info = mlxsw_bus_info;
 640 
 641         err = mlxsw_hwmon_temp_init(mlxsw_hwmon);
 642         if (err)
 643                 goto err_temp_init;
 644 
 645         err = mlxsw_hwmon_fans_init(mlxsw_hwmon);
 646         if (err)
 647                 goto err_fans_init;
 648 
 649         err = mlxsw_hwmon_module_init(mlxsw_hwmon);
 650         if (err)
 651                 goto err_temp_module_init;
 652 
 653         err = mlxsw_hwmon_gearbox_init(mlxsw_hwmon);
 654         if (err)
 655                 goto err_temp_gearbox_init;
 656 
 657         mlxsw_hwmon->groups[0] = &mlxsw_hwmon->group;
 658         mlxsw_hwmon->group.attrs = mlxsw_hwmon->attrs;
 659 
 660         hwmon_dev = hwmon_device_register_with_groups(mlxsw_bus_info->dev,
 661                                                       "mlxsw", mlxsw_hwmon,
 662                                                       mlxsw_hwmon->groups);
 663         if (IS_ERR(hwmon_dev)) {
 664                 err = PTR_ERR(hwmon_dev);
 665                 goto err_hwmon_register;
 666         }
 667 
 668         mlxsw_hwmon->hwmon_dev = hwmon_dev;
 669         *p_hwmon = mlxsw_hwmon;
 670         return 0;
 671 
 672 err_hwmon_register:
 673 err_temp_gearbox_init:
 674 err_temp_module_init:
 675 err_fans_init:
 676 err_temp_init:
 677         kfree(mlxsw_hwmon);
 678         return err;
 679 }
 680 
 681 void mlxsw_hwmon_fini(struct mlxsw_hwmon *mlxsw_hwmon)
 682 {
 683         hwmon_device_unregister(mlxsw_hwmon->hwmon_dev);
 684         kfree(mlxsw_hwmon);
 685 }

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