Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /* Copyright (c) 2015-2018 Mellanox Technologies. All rights reserved */
0003 
0004 #include <linux/kernel.h>
0005 #include <linux/types.h>
0006 #include <linux/device.h>
0007 #include <linux/sysfs.h>
0008 #include <linux/hwmon.h>
0009 #include <linux/err.h>
0010 #include <linux/sfp.h>
0011 
0012 #include "core.h"
0013 #include "core_env.h"
0014 
0015 #define MLXSW_HWMON_SENSORS_MAX_COUNT 64
0016 #define MLXSW_HWMON_MODULES_MAX_COUNT 64
0017 #define MLXSW_HWMON_GEARBOXES_MAX_COUNT 32
0018 
0019 #define MLXSW_HWMON_ATTR_PER_SENSOR 3
0020 #define MLXSW_HWMON_ATTR_PER_MODULE 7
0021 #define MLXSW_HWMON_ATTR_PER_GEARBOX 4
0022 #define MLXSW_HWMON_DEV_NAME_LEN_MAX 16
0023 
0024 #define MLXSW_HWMON_ATTR_COUNT (MLXSW_HWMON_SENSORS_MAX_COUNT * MLXSW_HWMON_ATTR_PER_SENSOR + \
0025                 MLXSW_HWMON_MODULES_MAX_COUNT * MLXSW_HWMON_ATTR_PER_MODULE + \
0026                 MLXSW_HWMON_GEARBOXES_MAX_COUNT * MLXSW_HWMON_ATTR_PER_GEARBOX + \
0027                 MLXSW_MFCR_TACHOS_MAX + MLXSW_MFCR_PWMS_MAX)
0028 
0029 struct mlxsw_hwmon_attr {
0030     struct device_attribute dev_attr;
0031     struct mlxsw_hwmon_dev *mlxsw_hwmon_dev;
0032     unsigned int type_index;
0033     char name[32];
0034 };
0035 
0036 static int mlxsw_hwmon_get_attr_index(int index, int count)
0037 {
0038     if (index >= count)
0039         return index % count + MLXSW_REG_MTMP_GBOX_INDEX_MIN;
0040 
0041     return index;
0042 }
0043 
0044 struct mlxsw_hwmon_dev {
0045     char name[MLXSW_HWMON_DEV_NAME_LEN_MAX];
0046     struct mlxsw_hwmon *hwmon;
0047     struct device *hwmon_dev;
0048     struct attribute_group group;
0049     const struct attribute_group *groups[2];
0050     struct attribute *attrs[MLXSW_HWMON_ATTR_COUNT + 1];
0051     struct mlxsw_hwmon_attr hwmon_attrs[MLXSW_HWMON_ATTR_COUNT];
0052     unsigned int attrs_count;
0053     u8 sensor_count;
0054     u8 module_sensor_max;
0055     u8 slot_index;
0056     bool active;
0057 };
0058 
0059 struct mlxsw_hwmon {
0060     struct mlxsw_core *core;
0061     const struct mlxsw_bus_info *bus_info;
0062     struct mlxsw_hwmon_dev line_cards[];
0063 };
0064 
0065 static ssize_t mlxsw_hwmon_temp_show(struct device *dev,
0066                      struct device_attribute *attr,
0067                      char *buf)
0068 {
0069     struct mlxsw_hwmon_attr *mlxsw_hwmon_attr =
0070             container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
0071     struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev;
0072     struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon;
0073     char mtmp_pl[MLXSW_REG_MTMP_LEN];
0074     int temp, index;
0075     int err;
0076 
0077     index = mlxsw_hwmon_get_attr_index(mlxsw_hwmon_attr->type_index,
0078                        mlxsw_hwmon_dev->module_sensor_max);
0079     mlxsw_reg_mtmp_pack(mtmp_pl, mlxsw_hwmon_dev->slot_index, index, false,
0080                 false);
0081     err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl);
0082     if (err) {
0083         dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query temp sensor\n");
0084         return err;
0085     }
0086     mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL, NULL, NULL);
0087     return sprintf(buf, "%d\n", temp);
0088 }
0089 
0090 static ssize_t mlxsw_hwmon_temp_max_show(struct device *dev,
0091                      struct device_attribute *attr,
0092                      char *buf)
0093 {
0094     struct mlxsw_hwmon_attr *mlxsw_hwmon_attr =
0095             container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
0096     struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev;
0097     struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon;
0098     char mtmp_pl[MLXSW_REG_MTMP_LEN];
0099     int temp_max, index;
0100     int err;
0101 
0102     index = mlxsw_hwmon_get_attr_index(mlxsw_hwmon_attr->type_index,
0103                        mlxsw_hwmon_dev->module_sensor_max);
0104     mlxsw_reg_mtmp_pack(mtmp_pl, mlxsw_hwmon_dev->slot_index, index, false,
0105                 false);
0106     err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl);
0107     if (err) {
0108         dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query temp sensor\n");
0109         return err;
0110     }
0111     mlxsw_reg_mtmp_unpack(mtmp_pl, NULL, &temp_max, NULL, NULL, NULL);
0112     return sprintf(buf, "%d\n", temp_max);
0113 }
0114 
0115 static ssize_t mlxsw_hwmon_temp_rst_store(struct device *dev,
0116                       struct device_attribute *attr,
0117                       const char *buf, size_t len)
0118 {
0119     struct mlxsw_hwmon_attr *mlxsw_hwmon_attr =
0120             container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
0121     struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev;
0122     struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon;
0123     char mtmp_pl[MLXSW_REG_MTMP_LEN];
0124     unsigned long val;
0125     int index;
0126     int err;
0127 
0128     err = kstrtoul(buf, 10, &val);
0129     if (err)
0130         return err;
0131     if (val != 1)
0132         return -EINVAL;
0133 
0134     index = mlxsw_hwmon_get_attr_index(mlxsw_hwmon_attr->type_index,
0135                        mlxsw_hwmon_dev->module_sensor_max);
0136 
0137     mlxsw_reg_mtmp_slot_index_set(mtmp_pl, mlxsw_hwmon_dev->slot_index);
0138     mlxsw_reg_mtmp_sensor_index_set(mtmp_pl, index);
0139     err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl);
0140     if (err)
0141         return err;
0142     mlxsw_reg_mtmp_mte_set(mtmp_pl, true);
0143     mlxsw_reg_mtmp_mtr_set(mtmp_pl, true);
0144     err = mlxsw_reg_write(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl);
0145     if (err) {
0146         dev_err(mlxsw_hwmon->bus_info->dev, "Failed to reset temp sensor history\n");
0147         return err;
0148     }
0149     return len;
0150 }
0151 
0152 static ssize_t mlxsw_hwmon_fan_rpm_show(struct device *dev,
0153                     struct device_attribute *attr,
0154                     char *buf)
0155 {
0156     struct mlxsw_hwmon_attr *mlxsw_hwmon_attr =
0157             container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
0158     struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev;
0159     struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon;
0160     char mfsm_pl[MLXSW_REG_MFSM_LEN];
0161     int err;
0162 
0163     mlxsw_reg_mfsm_pack(mfsm_pl, mlxsw_hwmon_attr->type_index);
0164     err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mfsm), mfsm_pl);
0165     if (err) {
0166         dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query fan\n");
0167         return err;
0168     }
0169     return sprintf(buf, "%u\n", mlxsw_reg_mfsm_rpm_get(mfsm_pl));
0170 }
0171 
0172 static ssize_t mlxsw_hwmon_fan_fault_show(struct device *dev,
0173                       struct device_attribute *attr,
0174                       char *buf)
0175 {
0176     struct mlxsw_hwmon_attr *mlxsw_hwmon_attr =
0177             container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
0178     struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev;
0179     struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon;
0180     char fore_pl[MLXSW_REG_FORE_LEN];
0181     bool fault;
0182     int err;
0183 
0184     err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(fore), fore_pl);
0185     if (err) {
0186         dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query fan\n");
0187         return err;
0188     }
0189     mlxsw_reg_fore_unpack(fore_pl, mlxsw_hwmon_attr->type_index, &fault);
0190 
0191     return sprintf(buf, "%u\n", fault);
0192 }
0193 
0194 static ssize_t mlxsw_hwmon_pwm_show(struct device *dev,
0195                     struct device_attribute *attr,
0196                     char *buf)
0197 {
0198     struct mlxsw_hwmon_attr *mlxsw_hwmon_attr =
0199             container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
0200     struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev;
0201     struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon;
0202     char mfsc_pl[MLXSW_REG_MFSC_LEN];
0203     int err;
0204 
0205     mlxsw_reg_mfsc_pack(mfsc_pl, mlxsw_hwmon_attr->type_index, 0);
0206     err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mfsc), mfsc_pl);
0207     if (err) {
0208         dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query PWM\n");
0209         return err;
0210     }
0211     return sprintf(buf, "%u\n",
0212                mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl));
0213 }
0214 
0215 static ssize_t mlxsw_hwmon_pwm_store(struct device *dev,
0216                      struct device_attribute *attr,
0217                      const char *buf, size_t len)
0218 {
0219     struct mlxsw_hwmon_attr *mlxsw_hwmon_attr =
0220             container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
0221     struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev;
0222     struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon;
0223     char mfsc_pl[MLXSW_REG_MFSC_LEN];
0224     unsigned long val;
0225     int err;
0226 
0227     err = kstrtoul(buf, 10, &val);
0228     if (err)
0229         return err;
0230     if (val > 255)
0231         return -EINVAL;
0232 
0233     mlxsw_reg_mfsc_pack(mfsc_pl, mlxsw_hwmon_attr->type_index, val);
0234     err = mlxsw_reg_write(mlxsw_hwmon->core, MLXSW_REG(mfsc), mfsc_pl);
0235     if (err) {
0236         dev_err(mlxsw_hwmon->bus_info->dev, "Failed to write PWM\n");
0237         return err;
0238     }
0239     return len;
0240 }
0241 
0242 static int mlxsw_hwmon_module_temp_get(struct device *dev,
0243                        struct device_attribute *attr,
0244                        int *p_temp)
0245 {
0246     struct mlxsw_hwmon_attr *mlxsw_hwmon_attr =
0247             container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
0248     struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev;
0249     struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon;
0250     char mtmp_pl[MLXSW_REG_MTMP_LEN];
0251     u8 module;
0252     int err;
0253 
0254     module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon_dev->sensor_count;
0255     mlxsw_reg_mtmp_pack(mtmp_pl, mlxsw_hwmon_dev->slot_index,
0256                 MLXSW_REG_MTMP_MODULE_INDEX_MIN + module, false,
0257                 false);
0258     err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl);
0259     if (err) {
0260         dev_err(dev, "Failed to query module temperature\n");
0261         return err;
0262     }
0263     mlxsw_reg_mtmp_unpack(mtmp_pl, p_temp, NULL, NULL, NULL, NULL);
0264 
0265     return 0;
0266 }
0267 
0268 static ssize_t mlxsw_hwmon_module_temp_show(struct device *dev,
0269                         struct device_attribute *attr,
0270                         char *buf)
0271 {
0272     int err, temp;
0273 
0274     err = mlxsw_hwmon_module_temp_get(dev, attr, &temp);
0275     if (err)
0276         return err;
0277 
0278     return sprintf(buf, "%d\n", temp);
0279 }
0280 
0281 static ssize_t mlxsw_hwmon_module_temp_fault_show(struct device *dev,
0282                           struct device_attribute *attr,
0283                           char *buf)
0284 {
0285     struct mlxsw_hwmon_attr *mlxsw_hwmon_attr =
0286             container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
0287     struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev;
0288     struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon;
0289     char mtbr_pl[MLXSW_REG_MTBR_LEN] = {0};
0290     u8 module, fault;
0291     u16 temp;
0292     int err;
0293 
0294     module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon_dev->sensor_count;
0295     mlxsw_reg_mtbr_pack(mtbr_pl, mlxsw_hwmon_dev->slot_index,
0296                 MLXSW_REG_MTBR_BASE_MODULE_INDEX + module, 1);
0297     err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtbr), mtbr_pl);
0298     if (err) {
0299         dev_err(dev, "Failed to query module temperature sensor\n");
0300         return err;
0301     }
0302 
0303     mlxsw_reg_mtbr_temp_unpack(mtbr_pl, 0, &temp, NULL);
0304 
0305     /* Update status and temperature cache. */
0306     switch (temp) {
0307     case MLXSW_REG_MTBR_BAD_SENS_INFO:
0308         /* Untrusted cable is connected. Reading temperature from its
0309          * sensor is faulty.
0310          */
0311         fault = 1;
0312         break;
0313     case MLXSW_REG_MTBR_NO_CONN:
0314     case MLXSW_REG_MTBR_NO_TEMP_SENS:
0315     case MLXSW_REG_MTBR_INDEX_NA:
0316     default:
0317         fault = 0;
0318         break;
0319     }
0320 
0321     return sprintf(buf, "%u\n", fault);
0322 }
0323 
0324 static int mlxsw_hwmon_module_temp_critical_get(struct device *dev,
0325                         struct device_attribute *attr,
0326                         int *p_temp)
0327 {
0328     struct mlxsw_hwmon_attr *mlxsw_hwmon_attr =
0329             container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
0330     struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev;
0331     struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon;
0332     u8 module;
0333     int err;
0334 
0335     module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon_dev->sensor_count;
0336     err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core,
0337                            mlxsw_hwmon_dev->slot_index,
0338                            module, SFP_TEMP_HIGH_WARN,
0339                            p_temp);
0340     if (err) {
0341         dev_err(dev, "Failed to query module temperature thresholds\n");
0342         return err;
0343     }
0344 
0345     return 0;
0346 }
0347 
0348 static ssize_t
0349 mlxsw_hwmon_module_temp_critical_show(struct device *dev,
0350                       struct device_attribute *attr, char *buf)
0351 {
0352     int err, temp;
0353 
0354     err = mlxsw_hwmon_module_temp_critical_get(dev, attr, &temp);
0355     if (err)
0356         return err;
0357 
0358     return sprintf(buf, "%u\n", temp);
0359 }
0360 
0361 static int mlxsw_hwmon_module_temp_emergency_get(struct device *dev,
0362                          struct device_attribute *attr,
0363                          int *p_temp)
0364 {
0365     struct mlxsw_hwmon_attr *mlxsw_hwmon_attr =
0366             container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
0367     struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev;
0368     struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon;
0369     u8 module;
0370     int err;
0371 
0372     module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon_dev->sensor_count;
0373     err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core,
0374                            mlxsw_hwmon_dev->slot_index,
0375                            module, SFP_TEMP_HIGH_ALARM,
0376                            p_temp);
0377     if (err) {
0378         dev_err(dev, "Failed to query module temperature thresholds\n");
0379         return err;
0380     }
0381 
0382     return 0;
0383 }
0384 
0385 static ssize_t
0386 mlxsw_hwmon_module_temp_emergency_show(struct device *dev,
0387                        struct device_attribute *attr,
0388                        char *buf)
0389 {
0390     int err, temp;
0391 
0392     err = mlxsw_hwmon_module_temp_emergency_get(dev, attr, &temp);
0393     if (err)
0394         return err;
0395 
0396     return sprintf(buf, "%u\n", temp);
0397 }
0398 
0399 static ssize_t
0400 mlxsw_hwmon_module_temp_label_show(struct device *dev,
0401                    struct device_attribute *attr,
0402                    char *buf)
0403 {
0404     struct mlxsw_hwmon_attr *mlxsw_hwmon_attr =
0405             container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
0406 
0407     return sprintf(buf, "front panel %03u\n",
0408                mlxsw_hwmon_attr->type_index);
0409 }
0410 
0411 static ssize_t
0412 mlxsw_hwmon_gbox_temp_label_show(struct device *dev,
0413                  struct device_attribute *attr,
0414                  char *buf)
0415 {
0416     struct mlxsw_hwmon_attr *mlxsw_hwmon_attr =
0417             container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
0418     struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev;
0419     int index = mlxsw_hwmon_attr->type_index -
0420             mlxsw_hwmon_dev->module_sensor_max + 1;
0421 
0422     return sprintf(buf, "gearbox %03u\n", index);
0423 }
0424 
0425 static ssize_t mlxsw_hwmon_temp_critical_alarm_show(struct device *dev,
0426                             struct device_attribute *attr,
0427                             char *buf)
0428 {
0429     int err, temp, emergency_temp, critic_temp;
0430 
0431     err = mlxsw_hwmon_module_temp_get(dev, attr, &temp);
0432     if (err)
0433         return err;
0434 
0435     if (temp <= 0)
0436         return sprintf(buf, "%d\n", false);
0437 
0438     err = mlxsw_hwmon_module_temp_emergency_get(dev, attr, &emergency_temp);
0439     if (err)
0440         return err;
0441 
0442     if (temp >= emergency_temp)
0443         return sprintf(buf, "%d\n", false);
0444 
0445     err = mlxsw_hwmon_module_temp_critical_get(dev, attr, &critic_temp);
0446     if (err)
0447         return err;
0448 
0449     return sprintf(buf, "%d\n", temp >= critic_temp);
0450 }
0451 
0452 static ssize_t mlxsw_hwmon_temp_emergency_alarm_show(struct device *dev,
0453                              struct device_attribute *attr,
0454                              char *buf)
0455 {
0456     int err, temp, emergency_temp;
0457 
0458     err = mlxsw_hwmon_module_temp_get(dev, attr, &temp);
0459     if (err)
0460         return err;
0461 
0462     if (temp <= 0)
0463         return sprintf(buf, "%d\n", false);
0464 
0465     err = mlxsw_hwmon_module_temp_emergency_get(dev, attr, &emergency_temp);
0466     if (err)
0467         return err;
0468 
0469     return sprintf(buf, "%d\n", temp >= emergency_temp);
0470 }
0471 
0472 enum mlxsw_hwmon_attr_type {
0473     MLXSW_HWMON_ATTR_TYPE_TEMP,
0474     MLXSW_HWMON_ATTR_TYPE_TEMP_MAX,
0475     MLXSW_HWMON_ATTR_TYPE_TEMP_RST,
0476     MLXSW_HWMON_ATTR_TYPE_FAN_RPM,
0477     MLXSW_HWMON_ATTR_TYPE_FAN_FAULT,
0478     MLXSW_HWMON_ATTR_TYPE_PWM,
0479     MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE,
0480     MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT,
0481     MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT,
0482     MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG,
0483     MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL,
0484     MLXSW_HWMON_ATTR_TYPE_TEMP_GBOX_LABEL,
0485     MLXSW_HWMON_ATTR_TYPE_TEMP_CRIT_ALARM,
0486     MLXSW_HWMON_ATTR_TYPE_TEMP_EMERGENCY_ALARM,
0487 };
0488 
0489 static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev,
0490                  enum mlxsw_hwmon_attr_type attr_type,
0491                  unsigned int type_index, unsigned int num)
0492 {
0493     struct mlxsw_hwmon_attr *mlxsw_hwmon_attr;
0494     unsigned int attr_index;
0495 
0496     attr_index = mlxsw_hwmon_dev->attrs_count;
0497     mlxsw_hwmon_attr = &mlxsw_hwmon_dev->hwmon_attrs[attr_index];
0498 
0499     switch (attr_type) {
0500     case MLXSW_HWMON_ATTR_TYPE_TEMP:
0501         mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_temp_show;
0502         mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
0503         snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
0504              "temp%u_input", num + 1);
0505         break;
0506     case MLXSW_HWMON_ATTR_TYPE_TEMP_MAX:
0507         mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_temp_max_show;
0508         mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
0509         snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
0510              "temp%u_highest", num + 1);
0511         break;
0512     case MLXSW_HWMON_ATTR_TYPE_TEMP_RST:
0513         mlxsw_hwmon_attr->dev_attr.store = mlxsw_hwmon_temp_rst_store;
0514         mlxsw_hwmon_attr->dev_attr.attr.mode = 0200;
0515         snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
0516              "temp%u_reset_history", num + 1);
0517         break;
0518     case MLXSW_HWMON_ATTR_TYPE_FAN_RPM:
0519         mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_fan_rpm_show;
0520         mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
0521         snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
0522              "fan%u_input", num + 1);
0523         break;
0524     case MLXSW_HWMON_ATTR_TYPE_FAN_FAULT:
0525         mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_fan_fault_show;
0526         mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
0527         snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
0528              "fan%u_fault", num + 1);
0529         break;
0530     case MLXSW_HWMON_ATTR_TYPE_PWM:
0531         mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_pwm_show;
0532         mlxsw_hwmon_attr->dev_attr.store = mlxsw_hwmon_pwm_store;
0533         mlxsw_hwmon_attr->dev_attr.attr.mode = 0644;
0534         snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
0535              "pwm%u", num + 1);
0536         break;
0537     case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE:
0538         mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_module_temp_show;
0539         mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
0540         snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
0541              "temp%u_input", num + 1);
0542         break;
0543     case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT:
0544         mlxsw_hwmon_attr->dev_attr.show =
0545                     mlxsw_hwmon_module_temp_fault_show;
0546         mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
0547         snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
0548              "temp%u_fault", num + 1);
0549         break;
0550     case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT:
0551         mlxsw_hwmon_attr->dev_attr.show =
0552             mlxsw_hwmon_module_temp_critical_show;
0553         mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
0554         snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
0555              "temp%u_crit", num + 1);
0556         break;
0557     case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG:
0558         mlxsw_hwmon_attr->dev_attr.show =
0559             mlxsw_hwmon_module_temp_emergency_show;
0560         mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
0561         snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
0562              "temp%u_emergency", num + 1);
0563         break;
0564     case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL:
0565         mlxsw_hwmon_attr->dev_attr.show =
0566             mlxsw_hwmon_module_temp_label_show;
0567         mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
0568         snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
0569              "temp%u_label", num + 1);
0570         break;
0571     case MLXSW_HWMON_ATTR_TYPE_TEMP_GBOX_LABEL:
0572         mlxsw_hwmon_attr->dev_attr.show =
0573             mlxsw_hwmon_gbox_temp_label_show;
0574         mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
0575         snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
0576              "temp%u_label", num + 1);
0577         break;
0578     case MLXSW_HWMON_ATTR_TYPE_TEMP_CRIT_ALARM:
0579         mlxsw_hwmon_attr->dev_attr.show =
0580             mlxsw_hwmon_temp_critical_alarm_show;
0581         mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
0582         snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
0583              "temp%u_crit_alarm", num + 1);
0584         break;
0585     case MLXSW_HWMON_ATTR_TYPE_TEMP_EMERGENCY_ALARM:
0586         mlxsw_hwmon_attr->dev_attr.show =
0587             mlxsw_hwmon_temp_emergency_alarm_show;
0588         mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
0589         snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
0590              "temp%u_emergency_alarm", num + 1);
0591         break;
0592     default:
0593         WARN_ON(1);
0594     }
0595 
0596     mlxsw_hwmon_attr->type_index = type_index;
0597     mlxsw_hwmon_attr->mlxsw_hwmon_dev = mlxsw_hwmon_dev;
0598     mlxsw_hwmon_attr->dev_attr.attr.name = mlxsw_hwmon_attr->name;
0599     sysfs_attr_init(&mlxsw_hwmon_attr->dev_attr.attr);
0600 
0601     mlxsw_hwmon_dev->attrs[attr_index] = &mlxsw_hwmon_attr->dev_attr.attr;
0602     mlxsw_hwmon_dev->attrs_count++;
0603 }
0604 
0605 static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev)
0606 {
0607     struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon;
0608     char mtcap_pl[MLXSW_REG_MTCAP_LEN] = {0};
0609     int i;
0610     int err;
0611 
0612     err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtcap), mtcap_pl);
0613     if (err) {
0614         dev_err(mlxsw_hwmon->bus_info->dev, "Failed to get number of temp sensors\n");
0615         return err;
0616     }
0617     mlxsw_hwmon_dev->sensor_count = mlxsw_reg_mtcap_sensor_count_get(mtcap_pl);
0618     for (i = 0; i < mlxsw_hwmon_dev->sensor_count; i++) {
0619         char mtmp_pl[MLXSW_REG_MTMP_LEN] = {0};
0620 
0621         mlxsw_reg_mtmp_slot_index_set(mtmp_pl,
0622                           mlxsw_hwmon_dev->slot_index);
0623         mlxsw_reg_mtmp_sensor_index_set(mtmp_pl, i);
0624         err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp),
0625                       mtmp_pl);
0626         if (err)
0627             return err;
0628         mlxsw_reg_mtmp_mte_set(mtmp_pl, true);
0629         mlxsw_reg_mtmp_mtr_set(mtmp_pl, true);
0630         err = mlxsw_reg_write(mlxsw_hwmon->core,
0631                       MLXSW_REG(mtmp), mtmp_pl);
0632         if (err) {
0633             dev_err(mlxsw_hwmon->bus_info->dev, "Failed to setup temp sensor number %d\n",
0634                 i);
0635             return err;
0636         }
0637         mlxsw_hwmon_attr_add(mlxsw_hwmon_dev,
0638                      MLXSW_HWMON_ATTR_TYPE_TEMP, i, i);
0639         mlxsw_hwmon_attr_add(mlxsw_hwmon_dev,
0640                      MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, i, i);
0641         mlxsw_hwmon_attr_add(mlxsw_hwmon_dev,
0642                      MLXSW_HWMON_ATTR_TYPE_TEMP_RST, i, i);
0643     }
0644     return 0;
0645 }
0646 
0647 static int mlxsw_hwmon_fans_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev)
0648 {
0649     struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon;
0650     char mfcr_pl[MLXSW_REG_MFCR_LEN] = {0};
0651     enum mlxsw_reg_mfcr_pwm_frequency freq;
0652     unsigned int type_index;
0653     unsigned int num;
0654     u16 tacho_active;
0655     u8 pwm_active;
0656     int err;
0657 
0658     err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mfcr), mfcr_pl);
0659     if (err) {
0660         dev_err(mlxsw_hwmon->bus_info->dev, "Failed to get to probe PWMs and Tachometers\n");
0661         return err;
0662     }
0663     mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active);
0664     num = 0;
0665     for (type_index = 0; type_index < MLXSW_MFCR_TACHOS_MAX; type_index++) {
0666         if (tacho_active & BIT(type_index)) {
0667             mlxsw_hwmon_attr_add(mlxsw_hwmon_dev,
0668                          MLXSW_HWMON_ATTR_TYPE_FAN_RPM,
0669                          type_index, num);
0670             mlxsw_hwmon_attr_add(mlxsw_hwmon_dev,
0671                          MLXSW_HWMON_ATTR_TYPE_FAN_FAULT,
0672                          type_index, num++);
0673         }
0674     }
0675     num = 0;
0676     for (type_index = 0; type_index < MLXSW_MFCR_PWMS_MAX; type_index++) {
0677         if (pwm_active & BIT(type_index))
0678             mlxsw_hwmon_attr_add(mlxsw_hwmon_dev,
0679                          MLXSW_HWMON_ATTR_TYPE_PWM,
0680                          type_index, num++);
0681     }
0682     return 0;
0683 }
0684 
0685 static int mlxsw_hwmon_module_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev)
0686 {
0687     struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon;
0688     char mgpir_pl[MLXSW_REG_MGPIR_LEN];
0689     u8 module_sensor_max;
0690     int i, err;
0691 
0692     mlxsw_reg_mgpir_pack(mgpir_pl, mlxsw_hwmon_dev->slot_index);
0693     err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mgpir), mgpir_pl);
0694     if (err)
0695         return err;
0696 
0697     mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL,
0698                    &module_sensor_max, NULL);
0699 
0700     /* Add extra attributes for module temperature. Sensor index is
0701      * assigned to sensor_count value, while all indexed before
0702      * sensor_count are already utilized by the sensors connected through
0703      * mtmp register by mlxsw_hwmon_temp_init().
0704      */
0705     mlxsw_hwmon_dev->module_sensor_max = mlxsw_hwmon_dev->sensor_count +
0706                          module_sensor_max;
0707     for (i = mlxsw_hwmon_dev->sensor_count;
0708          i < mlxsw_hwmon_dev->module_sensor_max; i++) {
0709         mlxsw_hwmon_attr_add(mlxsw_hwmon_dev,
0710                      MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE, i, i);
0711         mlxsw_hwmon_attr_add(mlxsw_hwmon_dev,
0712                      MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT,
0713                      i, i);
0714         mlxsw_hwmon_attr_add(mlxsw_hwmon_dev,
0715                      MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT, i,
0716                      i);
0717         mlxsw_hwmon_attr_add(mlxsw_hwmon_dev,
0718                      MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG,
0719                      i, i);
0720         mlxsw_hwmon_attr_add(mlxsw_hwmon_dev,
0721                      MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL,
0722                      i, i);
0723         mlxsw_hwmon_attr_add(mlxsw_hwmon_dev,
0724                      MLXSW_HWMON_ATTR_TYPE_TEMP_CRIT_ALARM,
0725                      i, i);
0726         mlxsw_hwmon_attr_add(mlxsw_hwmon_dev,
0727                      MLXSW_HWMON_ATTR_TYPE_TEMP_EMERGENCY_ALARM,
0728                      i, i);
0729     }
0730 
0731     return 0;
0732 }
0733 
0734 static int mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev)
0735 {
0736     struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon;
0737     enum mlxsw_reg_mgpir_device_type device_type;
0738     int index, max_index, sensor_index;
0739     char mgpir_pl[MLXSW_REG_MGPIR_LEN];
0740     char mtmp_pl[MLXSW_REG_MTMP_LEN];
0741     u8 gbox_num;
0742     int err;
0743 
0744     mlxsw_reg_mgpir_pack(mgpir_pl, mlxsw_hwmon_dev->slot_index);
0745     err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mgpir), mgpir_pl);
0746     if (err)
0747         return err;
0748 
0749     mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, &device_type, NULL, NULL,
0750                    NULL);
0751     if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE ||
0752         !gbox_num)
0753         return 0;
0754 
0755     index = mlxsw_hwmon_dev->module_sensor_max;
0756     max_index = mlxsw_hwmon_dev->module_sensor_max + gbox_num;
0757     while (index < max_index) {
0758         sensor_index = index % mlxsw_hwmon_dev->module_sensor_max +
0759                    MLXSW_REG_MTMP_GBOX_INDEX_MIN;
0760         mlxsw_reg_mtmp_pack(mtmp_pl, mlxsw_hwmon_dev->slot_index,
0761                     sensor_index, true, true);
0762         err = mlxsw_reg_write(mlxsw_hwmon->core,
0763                       MLXSW_REG(mtmp), mtmp_pl);
0764         if (err) {
0765             dev_err(mlxsw_hwmon->bus_info->dev, "Failed to setup temp sensor number %d\n",
0766                 sensor_index);
0767             return err;
0768         }
0769         mlxsw_hwmon_attr_add(mlxsw_hwmon_dev,
0770                      MLXSW_HWMON_ATTR_TYPE_TEMP, index, index);
0771         mlxsw_hwmon_attr_add(mlxsw_hwmon_dev,
0772                      MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, index,
0773                      index);
0774         mlxsw_hwmon_attr_add(mlxsw_hwmon_dev,
0775                      MLXSW_HWMON_ATTR_TYPE_TEMP_RST, index,
0776                      index);
0777         mlxsw_hwmon_attr_add(mlxsw_hwmon_dev,
0778                      MLXSW_HWMON_ATTR_TYPE_TEMP_GBOX_LABEL,
0779                      index, index);
0780         index++;
0781     }
0782 
0783     return 0;
0784 }
0785 
0786 static void
0787 mlxsw_hwmon_got_active(struct mlxsw_core *mlxsw_core, u8 slot_index,
0788                void *priv)
0789 {
0790     struct mlxsw_hwmon *hwmon = priv;
0791     struct mlxsw_hwmon_dev *linecard;
0792     struct device *dev;
0793     int err;
0794 
0795     dev = hwmon->bus_info->dev;
0796     linecard = &hwmon->line_cards[slot_index];
0797     if (linecard->active)
0798         return;
0799     /* For the main board, module sensor indexes start from 1, sensor index
0800      * 0 is used for the ASIC. Use the same numbering for line cards.
0801      */
0802     linecard->sensor_count = 1;
0803     linecard->slot_index = slot_index;
0804     linecard->hwmon = hwmon;
0805     err = mlxsw_hwmon_module_init(linecard);
0806     if (err) {
0807         dev_err(dev, "Failed to configure hwmon objects for line card modules in slot %d\n",
0808             slot_index);
0809         return;
0810     }
0811 
0812     err = mlxsw_hwmon_gearbox_init(linecard);
0813     if (err) {
0814         dev_err(dev, "Failed to configure hwmon objects for line card gearboxes in slot %d\n",
0815             slot_index);
0816         return;
0817     }
0818 
0819     linecard->groups[0] = &linecard->group;
0820     linecard->group.attrs = linecard->attrs;
0821     sprintf(linecard->name, "%s#%02u", "linecard", slot_index);
0822     linecard->hwmon_dev =
0823         hwmon_device_register_with_groups(dev, linecard->name,
0824                           linecard, linecard->groups);
0825     if (IS_ERR(linecard->hwmon_dev)) {
0826         dev_err(dev, "Failed to register hwmon objects for line card in slot %d\n",
0827             slot_index);
0828         return;
0829     }
0830 
0831     linecard->active = true;
0832 }
0833 
0834 static void
0835 mlxsw_hwmon_got_inactive(struct mlxsw_core *mlxsw_core, u8 slot_index,
0836              void *priv)
0837 {
0838     struct mlxsw_hwmon *hwmon = priv;
0839     struct mlxsw_hwmon_dev *linecard;
0840 
0841     linecard = &hwmon->line_cards[slot_index];
0842     if (!linecard->active)
0843         return;
0844     linecard->active = false;
0845     hwmon_device_unregister(linecard->hwmon_dev);
0846     /* Reset attributes counter */
0847     linecard->attrs_count = 0;
0848 }
0849 
0850 static struct mlxsw_linecards_event_ops mlxsw_hwmon_event_ops = {
0851     .got_active = mlxsw_hwmon_got_active,
0852     .got_inactive = mlxsw_hwmon_got_inactive,
0853 };
0854 
0855 int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core,
0856              const struct mlxsw_bus_info *mlxsw_bus_info,
0857              struct mlxsw_hwmon **p_hwmon)
0858 {
0859     char mgpir_pl[MLXSW_REG_MGPIR_LEN];
0860     struct mlxsw_hwmon *mlxsw_hwmon;
0861     struct device *hwmon_dev;
0862     u8 num_of_slots;
0863     int err;
0864 
0865     mlxsw_reg_mgpir_pack(mgpir_pl, 0);
0866     err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mgpir), mgpir_pl);
0867     if (err)
0868         return err;
0869 
0870     mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, NULL,
0871                    &num_of_slots);
0872 
0873     mlxsw_hwmon = kzalloc(struct_size(mlxsw_hwmon, line_cards,
0874                       num_of_slots + 1), GFP_KERNEL);
0875     if (!mlxsw_hwmon)
0876         return -ENOMEM;
0877 
0878     mlxsw_hwmon->core = mlxsw_core;
0879     mlxsw_hwmon->bus_info = mlxsw_bus_info;
0880     mlxsw_hwmon->line_cards[0].hwmon = mlxsw_hwmon;
0881     mlxsw_hwmon->line_cards[0].slot_index = 0;
0882 
0883     err = mlxsw_hwmon_temp_init(&mlxsw_hwmon->line_cards[0]);
0884     if (err)
0885         goto err_temp_init;
0886 
0887     err = mlxsw_hwmon_fans_init(&mlxsw_hwmon->line_cards[0]);
0888     if (err)
0889         goto err_fans_init;
0890 
0891     err = mlxsw_hwmon_module_init(&mlxsw_hwmon->line_cards[0]);
0892     if (err)
0893         goto err_temp_module_init;
0894 
0895     err = mlxsw_hwmon_gearbox_init(&mlxsw_hwmon->line_cards[0]);
0896     if (err)
0897         goto err_temp_gearbox_init;
0898 
0899     mlxsw_hwmon->line_cards[0].groups[0] = &mlxsw_hwmon->line_cards[0].group;
0900     mlxsw_hwmon->line_cards[0].group.attrs = mlxsw_hwmon->line_cards[0].attrs;
0901 
0902     hwmon_dev = hwmon_device_register_with_groups(mlxsw_bus_info->dev,
0903                               "mlxsw",
0904                               &mlxsw_hwmon->line_cards[0],
0905                               mlxsw_hwmon->line_cards[0].groups);
0906     if (IS_ERR(hwmon_dev)) {
0907         err = PTR_ERR(hwmon_dev);
0908         goto err_hwmon_register;
0909     }
0910 
0911     err = mlxsw_linecards_event_ops_register(mlxsw_hwmon->core,
0912                          &mlxsw_hwmon_event_ops,
0913                          mlxsw_hwmon);
0914     if (err)
0915         goto err_linecards_event_ops_register;
0916 
0917     mlxsw_hwmon->line_cards[0].hwmon_dev = hwmon_dev;
0918     mlxsw_hwmon->line_cards[0].active = true;
0919     *p_hwmon = mlxsw_hwmon;
0920     return 0;
0921 
0922 err_linecards_event_ops_register:
0923     hwmon_device_unregister(mlxsw_hwmon->line_cards[0].hwmon_dev);
0924 err_hwmon_register:
0925 err_temp_gearbox_init:
0926 err_temp_module_init:
0927 err_fans_init:
0928 err_temp_init:
0929     kfree(mlxsw_hwmon);
0930     return err;
0931 }
0932 
0933 void mlxsw_hwmon_fini(struct mlxsw_hwmon *mlxsw_hwmon)
0934 {
0935     mlxsw_hwmon->line_cards[0].active = false;
0936     mlxsw_linecards_event_ops_unregister(mlxsw_hwmon->core,
0937                          &mlxsw_hwmon_event_ops, mlxsw_hwmon);
0938     hwmon_device_unregister(mlxsw_hwmon->line_cards[0].hwmon_dev);
0939     kfree(mlxsw_hwmon);
0940 }