0001
0002
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
0306 switch (temp) {
0307 case MLXSW_REG_MTBR_BAD_SENS_INFO:
0308
0309
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
0701
0702
0703
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
0800
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
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 }