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_SENSORS_MAX_COUNT 64 16 #define MLXSW_HWMON_MODULES_MAX_COUNT 64 17 #define MLXSW_HWMON_GEARBOXES_MAX_COUNT 32 18 19 #define MLXSW_HWMON_ATTR_PER_SENSOR 3 20 #define MLXSW_HWMON_ATTR_PER_MODULE 7 21 #define MLXSW_HWMON_ATTR_PER_GEARBOX 4 22 #define MLXSW_HWMON_DEV_NAME_LEN_MAX 16 23 24 #define MLXSW_HWMON_ATTR_COUNT (MLXSW_HWMON_SENSORS_MAX_COUNT * MLXSW_HWMON_ATTR_PER_SENSOR + \ 25 MLXSW_HWMON_MODULES_MAX_COUNT * MLXSW_HWMON_ATTR_PER_MODULE + \ 26 MLXSW_HWMON_GEARBOXES_MAX_COUNT * MLXSW_HWMON_ATTR_PER_GEARBOX + \ 27 MLXSW_MFCR_TACHOS_MAX + MLXSW_MFCR_PWMS_MAX) 28 29 struct mlxsw_hwmon_attr { 30 struct device_attribute dev_attr; 31 struct mlxsw_hwmon_dev *mlxsw_hwmon_dev; 32 unsigned int type_index; 33 char name[32]; 34 }; 35 36 static int mlxsw_hwmon_get_attr_index(int index, int count) 37 { 38 if (index >= count) 39 return index % count + MLXSW_REG_MTMP_GBOX_INDEX_MIN; 40 41 return index; 42 } 43 44 struct mlxsw_hwmon_dev { 45 char name[MLXSW_HWMON_DEV_NAME_LEN_MAX]; 46 struct mlxsw_hwmon *hwmon; 47 struct device *hwmon_dev; 48 struct attribute_group group; 49 const struct attribute_group *groups[2]; 50 struct attribute *attrs[MLXSW_HWMON_ATTR_COUNT + 1]; 51 struct mlxsw_hwmon_attr hwmon_attrs[MLXSW_HWMON_ATTR_COUNT]; 52 unsigned int attrs_count; 53 u8 sensor_count; 54 u8 module_sensor_max; 55 u8 slot_index; 56 bool active; 57 }; 58 59 struct mlxsw_hwmon { 60 struct mlxsw_core *core; 61 const struct mlxsw_bus_info *bus_info; 62 struct mlxsw_hwmon_dev line_cards[]; 63 }; 64 65 static ssize_t mlxsw_hwmon_temp_show(struct device *dev, 66 struct device_attribute *attr, 67 char *buf) 68 { 69 struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = 70 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 71 struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; 72 struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; 73 char mtmp_pl[MLXSW_REG_MTMP_LEN]; 74 int temp, index; 75 int err; 76 77 index = mlxsw_hwmon_get_attr_index(mlxsw_hwmon_attr->type_index, 78 mlxsw_hwmon_dev->module_sensor_max); 79 mlxsw_reg_mtmp_pack(mtmp_pl, mlxsw_hwmon_dev->slot_index, index, false, 80 false); 81 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); 82 if (err) { 83 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query temp sensor\n"); 84 return err; 85 } 86 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL, NULL, NULL); 87 return sprintf(buf, "%d\n", temp); 88 } 89 90 static ssize_t mlxsw_hwmon_temp_max_show(struct device *dev, 91 struct device_attribute *attr, 92 char *buf) 93 { 94 struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = 95 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 96 struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; 97 struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; 98 char mtmp_pl[MLXSW_REG_MTMP_LEN]; 99 int temp_max, index; 100 int err; 101 102 index = mlxsw_hwmon_get_attr_index(mlxsw_hwmon_attr->type_index, 103 mlxsw_hwmon_dev->module_sensor_max); 104 mlxsw_reg_mtmp_pack(mtmp_pl, mlxsw_hwmon_dev->slot_index, index, false, 105 false); 106 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); 107 if (err) { 108 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query temp sensor\n"); 109 return err; 110 } 111 mlxsw_reg_mtmp_unpack(mtmp_pl, NULL, &temp_max, NULL, NULL, NULL); 112 return sprintf(buf, "%d\n", temp_max); 113 } 114 115 static ssize_t mlxsw_hwmon_temp_rst_store(struct device *dev, 116 struct device_attribute *attr, 117 const char *buf, size_t len) 118 { 119 struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = 120 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 121 struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; 122 struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; 123 char mtmp_pl[MLXSW_REG_MTMP_LEN]; 124 unsigned long val; 125 int index; 126 int err; 127 128 err = kstrtoul(buf, 10, &val); 129 if (err) 130 return err; 131 if (val != 1) 132 return -EINVAL; 133 134 index = mlxsw_hwmon_get_attr_index(mlxsw_hwmon_attr->type_index, 135 mlxsw_hwmon_dev->module_sensor_max); 136 137 mlxsw_reg_mtmp_slot_index_set(mtmp_pl, mlxsw_hwmon_dev->slot_index); 138 mlxsw_reg_mtmp_sensor_index_set(mtmp_pl, index); 139 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); 140 if (err) 141 return err; 142 mlxsw_reg_mtmp_mte_set(mtmp_pl, true); 143 mlxsw_reg_mtmp_mtr_set(mtmp_pl, true); 144 err = mlxsw_reg_write(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); 145 if (err) { 146 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to reset temp sensor history\n"); 147 return err; 148 } 149 return len; 150 } 151 152 static ssize_t mlxsw_hwmon_fan_rpm_show(struct device *dev, 153 struct device_attribute *attr, 154 char *buf) 155 { 156 struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = 157 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 158 struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; 159 struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; 160 char mfsm_pl[MLXSW_REG_MFSM_LEN]; 161 int err; 162 163 mlxsw_reg_mfsm_pack(mfsm_pl, mlxsw_hwmon_attr->type_index); 164 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mfsm), mfsm_pl); 165 if (err) { 166 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query fan\n"); 167 return err; 168 } 169 return sprintf(buf, "%u\n", mlxsw_reg_mfsm_rpm_get(mfsm_pl)); 170 } 171 172 static ssize_t mlxsw_hwmon_fan_fault_show(struct device *dev, 173 struct device_attribute *attr, 174 char *buf) 175 { 176 struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = 177 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 178 struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; 179 struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; 180 char fore_pl[MLXSW_REG_FORE_LEN]; 181 bool fault; 182 int err; 183 184 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(fore), fore_pl); 185 if (err) { 186 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query fan\n"); 187 return err; 188 } 189 mlxsw_reg_fore_unpack(fore_pl, mlxsw_hwmon_attr->type_index, &fault); 190 191 return sprintf(buf, "%u\n", fault); 192 } 193 194 static ssize_t mlxsw_hwmon_pwm_show(struct device *dev, 195 struct device_attribute *attr, 196 char *buf) 197 { 198 struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = 199 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 200 struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; 201 struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; 202 char mfsc_pl[MLXSW_REG_MFSC_LEN]; 203 int err; 204 205 mlxsw_reg_mfsc_pack(mfsc_pl, mlxsw_hwmon_attr->type_index, 0); 206 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mfsc), mfsc_pl); 207 if (err) { 208 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to query PWM\n"); 209 return err; 210 } 211 return sprintf(buf, "%u\n", 212 mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl)); 213 } 214 215 static ssize_t mlxsw_hwmon_pwm_store(struct device *dev, 216 struct device_attribute *attr, 217 const char *buf, size_t len) 218 { 219 struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = 220 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 221 struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; 222 struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; 223 char mfsc_pl[MLXSW_REG_MFSC_LEN]; 224 unsigned long val; 225 int err; 226 227 err = kstrtoul(buf, 10, &val); 228 if (err) 229 return err; 230 if (val > 255) 231 return -EINVAL; 232 233 mlxsw_reg_mfsc_pack(mfsc_pl, mlxsw_hwmon_attr->type_index, val); 234 err = mlxsw_reg_write(mlxsw_hwmon->core, MLXSW_REG(mfsc), mfsc_pl); 235 if (err) { 236 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to write PWM\n"); 237 return err; 238 } 239 return len; 240 } 241 242 static int mlxsw_hwmon_module_temp_get(struct device *dev, 243 struct device_attribute *attr, 244 int *p_temp) 245 { 246 struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = 247 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 248 struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; 249 struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; 250 char mtmp_pl[MLXSW_REG_MTMP_LEN]; 251 u8 module; 252 int err; 253 254 module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon_dev->sensor_count; 255 mlxsw_reg_mtmp_pack(mtmp_pl, mlxsw_hwmon_dev->slot_index, 256 MLXSW_REG_MTMP_MODULE_INDEX_MIN + module, false, 257 false); 258 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl); 259 if (err) { 260 dev_err(dev, "Failed to query module temperature\n"); 261 return err; 262 } 263 mlxsw_reg_mtmp_unpack(mtmp_pl, p_temp, NULL, NULL, NULL, NULL); 264 265 return 0; 266 } 267 268 static ssize_t mlxsw_hwmon_module_temp_show(struct device *dev, 269 struct device_attribute *attr, 270 char *buf) 271 { 272 int err, temp; 273 274 err = mlxsw_hwmon_module_temp_get(dev, attr, &temp); 275 if (err) 276 return err; 277 278 return sprintf(buf, "%d\n", temp); 279 } 280 281 static ssize_t mlxsw_hwmon_module_temp_fault_show(struct device *dev, 282 struct device_attribute *attr, 283 char *buf) 284 { 285 struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = 286 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 287 struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; 288 struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; 289 char mtbr_pl[MLXSW_REG_MTBR_LEN] = {0}; 290 u8 module, fault; 291 u16 temp; 292 int err; 293 294 module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon_dev->sensor_count; 295 mlxsw_reg_mtbr_pack(mtbr_pl, mlxsw_hwmon_dev->slot_index, 296 MLXSW_REG_MTBR_BASE_MODULE_INDEX + module, 1); 297 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtbr), mtbr_pl); 298 if (err) { 299 dev_err(dev, "Failed to query module temperature sensor\n"); 300 return err; 301 } 302 303 mlxsw_reg_mtbr_temp_unpack(mtbr_pl, 0, &temp, NULL); 304 305 /* Update status and temperature cache. */ 306 switch (temp) { 307 case MLXSW_REG_MTBR_BAD_SENS_INFO: 308 /* Untrusted cable is connected. Reading temperature from its 309 * sensor is faulty. 310 */ 311 fault = 1; 312 break; 313 case MLXSW_REG_MTBR_NO_CONN: 314 case MLXSW_REG_MTBR_NO_TEMP_SENS: 315 case MLXSW_REG_MTBR_INDEX_NA: 316 default: 317 fault = 0; 318 break; 319 } 320 321 return sprintf(buf, "%u\n", fault); 322 } 323 324 static int mlxsw_hwmon_module_temp_critical_get(struct device *dev, 325 struct device_attribute *attr, 326 int *p_temp) 327 { 328 struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = 329 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 330 struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; 331 struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; 332 u8 module; 333 int err; 334 335 module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon_dev->sensor_count; 336 err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, 337 mlxsw_hwmon_dev->slot_index, 338 module, SFP_TEMP_HIGH_WARN, 339 p_temp); 340 if (err) { 341 dev_err(dev, "Failed to query module temperature thresholds\n"); 342 return err; 343 } 344 345 return 0; 346 } 347 348 static ssize_t 349 mlxsw_hwmon_module_temp_critical_show(struct device *dev, 350 struct device_attribute *attr, char *buf) 351 { 352 int err, temp; 353 354 err = mlxsw_hwmon_module_temp_critical_get(dev, attr, &temp); 355 if (err) 356 return err; 357 358 return sprintf(buf, "%u\n", temp); 359 } 360 361 static int mlxsw_hwmon_module_temp_emergency_get(struct device *dev, 362 struct device_attribute *attr, 363 int *p_temp) 364 { 365 struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = 366 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 367 struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; 368 struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; 369 u8 module; 370 int err; 371 372 module = mlxsw_hwmon_attr->type_index - mlxsw_hwmon_dev->sensor_count; 373 err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, 374 mlxsw_hwmon_dev->slot_index, 375 module, SFP_TEMP_HIGH_ALARM, 376 p_temp); 377 if (err) { 378 dev_err(dev, "Failed to query module temperature thresholds\n"); 379 return err; 380 } 381 382 return 0; 383 } 384 385 static ssize_t 386 mlxsw_hwmon_module_temp_emergency_show(struct device *dev, 387 struct device_attribute *attr, 388 char *buf) 389 { 390 int err, temp; 391 392 err = mlxsw_hwmon_module_temp_emergency_get(dev, attr, &temp); 393 if (err) 394 return err; 395 396 return sprintf(buf, "%u\n", temp); 397 } 398 399 static ssize_t 400 mlxsw_hwmon_module_temp_label_show(struct device *dev, 401 struct device_attribute *attr, 402 char *buf) 403 { 404 struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = 405 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 406 407 return sprintf(buf, "front panel %03u\n", 408 mlxsw_hwmon_attr->type_index + 1 - 409 mlxsw_hwmon_attr->mlxsw_hwmon_dev->sensor_count); 410 } 411 412 static ssize_t 413 mlxsw_hwmon_gbox_temp_label_show(struct device *dev, 414 struct device_attribute *attr, 415 char *buf) 416 { 417 struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = 418 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 419 struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; 420 int index = mlxsw_hwmon_attr->type_index - 421 mlxsw_hwmon_dev->module_sensor_max + 1; 422 423 return sprintf(buf, "gearbox %03u\n", index); 424 } 425 426 static ssize_t mlxsw_hwmon_temp_critical_alarm_show(struct device *dev, 427 struct device_attribute *attr, 428 char *buf) 429 { 430 int err, temp, emergency_temp, critic_temp; 431 432 err = mlxsw_hwmon_module_temp_get(dev, attr, &temp); 433 if (err) 434 return err; 435 436 if (temp <= 0) 437 return sprintf(buf, "%d\n", false); 438 439 err = mlxsw_hwmon_module_temp_emergency_get(dev, attr, &emergency_temp); 440 if (err) 441 return err; 442 443 if (temp >= emergency_temp) 444 return sprintf(buf, "%d\n", false); 445 446 err = mlxsw_hwmon_module_temp_critical_get(dev, attr, &critic_temp); 447 if (err) 448 return err; 449 450 return sprintf(buf, "%d\n", temp >= critic_temp); 451 } 452 453 static ssize_t mlxsw_hwmon_temp_emergency_alarm_show(struct device *dev, 454 struct device_attribute *attr, 455 char *buf) 456 { 457 int err, temp, emergency_temp; 458 459 err = mlxsw_hwmon_module_temp_get(dev, attr, &temp); 460 if (err) 461 return err; 462 463 if (temp <= 0) 464 return sprintf(buf, "%d\n", false); 465 466 err = mlxsw_hwmon_module_temp_emergency_get(dev, attr, &emergency_temp); 467 if (err) 468 return err; 469 470 return sprintf(buf, "%d\n", temp >= emergency_temp); 471 } 472 473 enum mlxsw_hwmon_attr_type { 474 MLXSW_HWMON_ATTR_TYPE_TEMP, 475 MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, 476 MLXSW_HWMON_ATTR_TYPE_TEMP_RST, 477 MLXSW_HWMON_ATTR_TYPE_FAN_RPM, 478 MLXSW_HWMON_ATTR_TYPE_FAN_FAULT, 479 MLXSW_HWMON_ATTR_TYPE_PWM, 480 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE, 481 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT, 482 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT, 483 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG, 484 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL, 485 MLXSW_HWMON_ATTR_TYPE_TEMP_GBOX_LABEL, 486 MLXSW_HWMON_ATTR_TYPE_TEMP_CRIT_ALARM, 487 MLXSW_HWMON_ATTR_TYPE_TEMP_EMERGENCY_ALARM, 488 }; 489 490 static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev, 491 enum mlxsw_hwmon_attr_type attr_type, 492 unsigned int type_index, unsigned int num) 493 { 494 struct mlxsw_hwmon_attr *mlxsw_hwmon_attr; 495 unsigned int attr_index; 496 497 attr_index = mlxsw_hwmon_dev->attrs_count; 498 mlxsw_hwmon_attr = &mlxsw_hwmon_dev->hwmon_attrs[attr_index]; 499 500 switch (attr_type) { 501 case MLXSW_HWMON_ATTR_TYPE_TEMP: 502 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_temp_show; 503 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 504 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 505 "temp%u_input", num + 1); 506 break; 507 case MLXSW_HWMON_ATTR_TYPE_TEMP_MAX: 508 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_temp_max_show; 509 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 510 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 511 "temp%u_highest", num + 1); 512 break; 513 case MLXSW_HWMON_ATTR_TYPE_TEMP_RST: 514 mlxsw_hwmon_attr->dev_attr.store = mlxsw_hwmon_temp_rst_store; 515 mlxsw_hwmon_attr->dev_attr.attr.mode = 0200; 516 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 517 "temp%u_reset_history", num + 1); 518 break; 519 case MLXSW_HWMON_ATTR_TYPE_FAN_RPM: 520 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_fan_rpm_show; 521 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 522 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 523 "fan%u_input", num + 1); 524 break; 525 case MLXSW_HWMON_ATTR_TYPE_FAN_FAULT: 526 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_fan_fault_show; 527 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 528 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 529 "fan%u_fault", num + 1); 530 break; 531 case MLXSW_HWMON_ATTR_TYPE_PWM: 532 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_pwm_show; 533 mlxsw_hwmon_attr->dev_attr.store = mlxsw_hwmon_pwm_store; 534 mlxsw_hwmon_attr->dev_attr.attr.mode = 0644; 535 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 536 "pwm%u", num + 1); 537 break; 538 case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE: 539 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_module_temp_show; 540 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 541 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 542 "temp%u_input", num + 1); 543 break; 544 case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT: 545 mlxsw_hwmon_attr->dev_attr.show = 546 mlxsw_hwmon_module_temp_fault_show; 547 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 548 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 549 "temp%u_fault", num + 1); 550 break; 551 case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT: 552 mlxsw_hwmon_attr->dev_attr.show = 553 mlxsw_hwmon_module_temp_critical_show; 554 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 555 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 556 "temp%u_crit", num + 1); 557 break; 558 case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG: 559 mlxsw_hwmon_attr->dev_attr.show = 560 mlxsw_hwmon_module_temp_emergency_show; 561 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 562 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 563 "temp%u_emergency", num + 1); 564 break; 565 case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL: 566 mlxsw_hwmon_attr->dev_attr.show = 567 mlxsw_hwmon_module_temp_label_show; 568 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 569 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 570 "temp%u_label", num + 1); 571 break; 572 case MLXSW_HWMON_ATTR_TYPE_TEMP_GBOX_LABEL: 573 mlxsw_hwmon_attr->dev_attr.show = 574 mlxsw_hwmon_gbox_temp_label_show; 575 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 576 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 577 "temp%u_label", num + 1); 578 break; 579 case MLXSW_HWMON_ATTR_TYPE_TEMP_CRIT_ALARM: 580 mlxsw_hwmon_attr->dev_attr.show = 581 mlxsw_hwmon_temp_critical_alarm_show; 582 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 583 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 584 "temp%u_crit_alarm", num + 1); 585 break; 586 case MLXSW_HWMON_ATTR_TYPE_TEMP_EMERGENCY_ALARM: 587 mlxsw_hwmon_attr->dev_attr.show = 588 mlxsw_hwmon_temp_emergency_alarm_show; 589 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 590 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 591 "temp%u_emergency_alarm", num + 1); 592 break; 593 default: 594 WARN_ON(1); 595 } 596 597 mlxsw_hwmon_attr->type_index = type_index; 598 mlxsw_hwmon_attr->mlxsw_hwmon_dev = mlxsw_hwmon_dev; 599 mlxsw_hwmon_attr->dev_attr.attr.name = mlxsw_hwmon_attr->name; 600 sysfs_attr_init(&mlxsw_hwmon_attr->dev_attr.attr); 601 602 mlxsw_hwmon_dev->attrs[attr_index] = &mlxsw_hwmon_attr->dev_attr.attr; 603 mlxsw_hwmon_dev->attrs_count++; 604 } 605 606 static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev) 607 { 608 struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; 609 char mtcap_pl[MLXSW_REG_MTCAP_LEN] = {0}; 610 int i; 611 int err; 612 613 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtcap), mtcap_pl); 614 if (err) { 615 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to get number of temp sensors\n"); 616 return err; 617 } 618 mlxsw_hwmon_dev->sensor_count = mlxsw_reg_mtcap_sensor_count_get(mtcap_pl); 619 for (i = 0; i < mlxsw_hwmon_dev->sensor_count; i++) { 620 char mtmp_pl[MLXSW_REG_MTMP_LEN] = {0}; 621 622 mlxsw_reg_mtmp_slot_index_set(mtmp_pl, 623 mlxsw_hwmon_dev->slot_index); 624 mlxsw_reg_mtmp_sensor_index_set(mtmp_pl, i); 625 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), 626 mtmp_pl); 627 if (err) 628 return err; 629 mlxsw_reg_mtmp_mte_set(mtmp_pl, true); 630 mlxsw_reg_mtmp_mtr_set(mtmp_pl, true); 631 err = mlxsw_reg_write(mlxsw_hwmon->core, 632 MLXSW_REG(mtmp), mtmp_pl); 633 if (err) { 634 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to setup temp sensor number %d\n", 635 i); 636 return err; 637 } 638 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 639 MLXSW_HWMON_ATTR_TYPE_TEMP, i, i); 640 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 641 MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, i, i); 642 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 643 MLXSW_HWMON_ATTR_TYPE_TEMP_RST, i, i); 644 } 645 return 0; 646 } 647 648 static int mlxsw_hwmon_fans_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev) 649 { 650 struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; 651 char mfcr_pl[MLXSW_REG_MFCR_LEN] = {0}; 652 enum mlxsw_reg_mfcr_pwm_frequency freq; 653 unsigned int type_index; 654 unsigned int num; 655 u16 tacho_active; 656 u8 pwm_active; 657 int err; 658 659 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mfcr), mfcr_pl); 660 if (err) { 661 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to get to probe PWMs and Tachometers\n"); 662 return err; 663 } 664 mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active); 665 num = 0; 666 for (type_index = 0; type_index < MLXSW_MFCR_TACHOS_MAX; type_index++) { 667 if (tacho_active & BIT(type_index)) { 668 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 669 MLXSW_HWMON_ATTR_TYPE_FAN_RPM, 670 type_index, num); 671 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 672 MLXSW_HWMON_ATTR_TYPE_FAN_FAULT, 673 type_index, num++); 674 } 675 } 676 num = 0; 677 for (type_index = 0; type_index < MLXSW_MFCR_PWMS_MAX; type_index++) { 678 if (pwm_active & BIT(type_index)) 679 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 680 MLXSW_HWMON_ATTR_TYPE_PWM, 681 type_index, num++); 682 } 683 return 0; 684 } 685 686 static int mlxsw_hwmon_module_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev) 687 { 688 struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; 689 char mgpir_pl[MLXSW_REG_MGPIR_LEN]; 690 u8 module_sensor_max; 691 int i, err; 692 693 mlxsw_reg_mgpir_pack(mgpir_pl, mlxsw_hwmon_dev->slot_index); 694 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mgpir), mgpir_pl); 695 if (err) 696 return err; 697 698 mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, 699 &module_sensor_max, NULL); 700 701 /* Add extra attributes for module temperature. Sensor index is 702 * assigned to sensor_count value, while all indexed before 703 * sensor_count are already utilized by the sensors connected through 704 * mtmp register by mlxsw_hwmon_temp_init(). 705 */ 706 mlxsw_hwmon_dev->module_sensor_max = mlxsw_hwmon_dev->sensor_count + 707 module_sensor_max; 708 for (i = mlxsw_hwmon_dev->sensor_count; 709 i < mlxsw_hwmon_dev->module_sensor_max; i++) { 710 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 711 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE, i, i); 712 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 713 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT, 714 i, i); 715 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 716 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT, i, 717 i); 718 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 719 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG, 720 i, i); 721 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 722 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL, 723 i, i); 724 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 725 MLXSW_HWMON_ATTR_TYPE_TEMP_CRIT_ALARM, 726 i, i); 727 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 728 MLXSW_HWMON_ATTR_TYPE_TEMP_EMERGENCY_ALARM, 729 i, i); 730 } 731 732 return 0; 733 } 734 735 static int mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev) 736 { 737 struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; 738 enum mlxsw_reg_mgpir_device_type device_type; 739 int index, max_index, sensor_index; 740 char mgpir_pl[MLXSW_REG_MGPIR_LEN]; 741 char mtmp_pl[MLXSW_REG_MTMP_LEN]; 742 u8 gbox_num; 743 int err; 744 745 mlxsw_reg_mgpir_pack(mgpir_pl, mlxsw_hwmon_dev->slot_index); 746 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mgpir), mgpir_pl); 747 if (err) 748 return err; 749 750 mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, &device_type, NULL, NULL, 751 NULL); 752 if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE || 753 !gbox_num) 754 return 0; 755 756 index = mlxsw_hwmon_dev->module_sensor_max; 757 max_index = mlxsw_hwmon_dev->module_sensor_max + gbox_num; 758 while (index < max_index) { 759 sensor_index = index % mlxsw_hwmon_dev->module_sensor_max + 760 MLXSW_REG_MTMP_GBOX_INDEX_MIN; 761 mlxsw_reg_mtmp_pack(mtmp_pl, mlxsw_hwmon_dev->slot_index, 762 sensor_index, true, true); 763 err = mlxsw_reg_write(mlxsw_hwmon->core, 764 MLXSW_REG(mtmp), mtmp_pl); 765 if (err) { 766 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to setup temp sensor number %d\n", 767 sensor_index); 768 return err; 769 } 770 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 771 MLXSW_HWMON_ATTR_TYPE_TEMP, index, index); 772 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 773 MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, index, 774 index); 775 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 776 MLXSW_HWMON_ATTR_TYPE_TEMP_RST, index, 777 index); 778 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 779 MLXSW_HWMON_ATTR_TYPE_TEMP_GBOX_LABEL, 780 index, index); 781 index++; 782 } 783 784 return 0; 785 } 786 787 static void 788 mlxsw_hwmon_got_active(struct mlxsw_core *mlxsw_core, u8 slot_index, 789 void *priv) 790 { 791 struct mlxsw_hwmon *hwmon = priv; 792 struct mlxsw_hwmon_dev *linecard; 793 struct device *dev; 794 int err; 795 796 dev = hwmon->bus_info->dev; 797 linecard = &hwmon->line_cards[slot_index]; 798 if (linecard->active) 799 return; 800 /* For the main board, module sensor indexes start from 1, sensor index 801 * 0 is used for the ASIC. Use the same numbering for line cards. 802 */ 803 linecard->sensor_count = 1; 804 linecard->slot_index = slot_index; 805 linecard->hwmon = hwmon; 806 err = mlxsw_hwmon_module_init(linecard); 807 if (err) { 808 dev_err(dev, "Failed to configure hwmon objects for line card modules in slot %d\n", 809 slot_index); 810 return; 811 } 812 813 err = mlxsw_hwmon_gearbox_init(linecard); 814 if (err) { 815 dev_err(dev, "Failed to configure hwmon objects for line card gearboxes in slot %d\n", 816 slot_index); 817 return; 818 } 819 820 linecard->groups[0] = &linecard->group; 821 linecard->group.attrs = linecard->attrs; 822 sprintf(linecard->name, "%s#%02u", "linecard", slot_index); 823 linecard->hwmon_dev = 824 hwmon_device_register_with_groups(dev, linecard->name, 825 linecard, linecard->groups); 826 if (IS_ERR(linecard->hwmon_dev)) { 827 dev_err(dev, "Failed to register hwmon objects for line card in slot %d\n", 828 slot_index); 829 return; 830 } 831 832 linecard->active = true; 833 } 834 835 static void 836 mlxsw_hwmon_got_inactive(struct mlxsw_core *mlxsw_core, u8 slot_index, 837 void *priv) 838 { 839 struct mlxsw_hwmon *hwmon = priv; 840 struct mlxsw_hwmon_dev *linecard; 841 842 linecard = &hwmon->line_cards[slot_index]; 843 if (!linecard->active) 844 return; 845 linecard->active = false; 846 hwmon_device_unregister(linecard->hwmon_dev); 847 /* Reset attributes counter */ 848 linecard->attrs_count = 0; 849 } 850 851 static struct mlxsw_linecards_event_ops mlxsw_hwmon_event_ops = { 852 .got_active = mlxsw_hwmon_got_active, 853 .got_inactive = mlxsw_hwmon_got_inactive, 854 }; 855 856 int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core, 857 const struct mlxsw_bus_info *mlxsw_bus_info, 858 struct mlxsw_hwmon **p_hwmon) 859 { 860 char mgpir_pl[MLXSW_REG_MGPIR_LEN]; 861 struct mlxsw_hwmon *mlxsw_hwmon; 862 struct device *hwmon_dev; 863 u8 num_of_slots; 864 int err; 865 866 mlxsw_reg_mgpir_pack(mgpir_pl, 0); 867 err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mgpir), mgpir_pl); 868 if (err) 869 return err; 870 871 mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, NULL, 872 &num_of_slots); 873 874 mlxsw_hwmon = kzalloc(struct_size(mlxsw_hwmon, line_cards, 875 num_of_slots + 1), GFP_KERNEL); 876 if (!mlxsw_hwmon) 877 return -ENOMEM; 878 879 mlxsw_hwmon->core = mlxsw_core; 880 mlxsw_hwmon->bus_info = mlxsw_bus_info; 881 mlxsw_hwmon->line_cards[0].hwmon = mlxsw_hwmon; 882 mlxsw_hwmon->line_cards[0].slot_index = 0; 883 884 err = mlxsw_hwmon_temp_init(&mlxsw_hwmon->line_cards[0]); 885 if (err) 886 goto err_temp_init; 887 888 err = mlxsw_hwmon_fans_init(&mlxsw_hwmon->line_cards[0]); 889 if (err) 890 goto err_fans_init; 891 892 err = mlxsw_hwmon_module_init(&mlxsw_hwmon->line_cards[0]); 893 if (err) 894 goto err_temp_module_init; 895 896 err = mlxsw_hwmon_gearbox_init(&mlxsw_hwmon->line_cards[0]); 897 if (err) 898 goto err_temp_gearbox_init; 899 900 mlxsw_hwmon->line_cards[0].groups[0] = &mlxsw_hwmon->line_cards[0].group; 901 mlxsw_hwmon->line_cards[0].group.attrs = mlxsw_hwmon->line_cards[0].attrs; 902 903 hwmon_dev = hwmon_device_register_with_groups(mlxsw_bus_info->dev, 904 "mlxsw", 905 &mlxsw_hwmon->line_cards[0], 906 mlxsw_hwmon->line_cards[0].groups); 907 if (IS_ERR(hwmon_dev)) { 908 err = PTR_ERR(hwmon_dev); 909 goto err_hwmon_register; 910 } 911 912 err = mlxsw_linecards_event_ops_register(mlxsw_hwmon->core, 913 &mlxsw_hwmon_event_ops, 914 mlxsw_hwmon); 915 if (err) 916 goto err_linecards_event_ops_register; 917 918 mlxsw_hwmon->line_cards[0].hwmon_dev = hwmon_dev; 919 mlxsw_hwmon->line_cards[0].active = true; 920 *p_hwmon = mlxsw_hwmon; 921 return 0; 922 923 err_linecards_event_ops_register: 924 hwmon_device_unregister(mlxsw_hwmon->line_cards[0].hwmon_dev); 925 err_hwmon_register: 926 err_temp_gearbox_init: 927 err_temp_module_init: 928 err_fans_init: 929 err_temp_init: 930 kfree(mlxsw_hwmon); 931 return err; 932 } 933 934 void mlxsw_hwmon_fini(struct mlxsw_hwmon *mlxsw_hwmon) 935 { 936 mlxsw_hwmon->line_cards[0].active = false; 937 mlxsw_linecards_event_ops_unregister(mlxsw_hwmon->core, 938 &mlxsw_hwmon_event_ops, mlxsw_hwmon); 939 hwmon_device_unregister(mlxsw_hwmon->line_cards[0].hwmon_dev); 940 kfree(mlxsw_hwmon); 941 } 942