core_hwmon.c (28931B)
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 29struct 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 36static 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 44struct 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 59struct mlxsw_hwmon { 60 struct mlxsw_core *core; 61 const struct mlxsw_bus_info *bus_info; 62 struct mlxsw_hwmon_dev line_cards[]; 63}; 64 65static 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 90static 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 115static 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 152static 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 172static 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 194static 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 215static 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 242static 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 268static 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 281static 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 324static 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 348static ssize_t 349mlxsw_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 361static 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 385static ssize_t 386mlxsw_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 399static ssize_t 400mlxsw_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); 409} 410 411static ssize_t 412mlxsw_hwmon_gbox_temp_label_show(struct device *dev, 413 struct device_attribute *attr, 414 char *buf) 415{ 416 struct mlxsw_hwmon_attr *mlxsw_hwmon_attr = 417 container_of(attr, struct mlxsw_hwmon_attr, dev_attr); 418 struct mlxsw_hwmon_dev *mlxsw_hwmon_dev = mlxsw_hwmon_attr->mlxsw_hwmon_dev; 419 int index = mlxsw_hwmon_attr->type_index - 420 mlxsw_hwmon_dev->module_sensor_max + 1; 421 422 return sprintf(buf, "gearbox %03u\n", index); 423} 424 425static ssize_t mlxsw_hwmon_temp_critical_alarm_show(struct device *dev, 426 struct device_attribute *attr, 427 char *buf) 428{ 429 int err, temp, emergency_temp, critic_temp; 430 431 err = mlxsw_hwmon_module_temp_get(dev, attr, &temp); 432 if (err) 433 return err; 434 435 if (temp <= 0) 436 return sprintf(buf, "%d\n", false); 437 438 err = mlxsw_hwmon_module_temp_emergency_get(dev, attr, &emergency_temp); 439 if (err) 440 return err; 441 442 if (temp >= emergency_temp) 443 return sprintf(buf, "%d\n", false); 444 445 err = mlxsw_hwmon_module_temp_critical_get(dev, attr, &critic_temp); 446 if (err) 447 return err; 448 449 return sprintf(buf, "%d\n", temp >= critic_temp); 450} 451 452static ssize_t mlxsw_hwmon_temp_emergency_alarm_show(struct device *dev, 453 struct device_attribute *attr, 454 char *buf) 455{ 456 int err, temp, emergency_temp; 457 458 err = mlxsw_hwmon_module_temp_get(dev, attr, &temp); 459 if (err) 460 return err; 461 462 if (temp <= 0) 463 return sprintf(buf, "%d\n", false); 464 465 err = mlxsw_hwmon_module_temp_emergency_get(dev, attr, &emergency_temp); 466 if (err) 467 return err; 468 469 return sprintf(buf, "%d\n", temp >= emergency_temp); 470} 471 472enum mlxsw_hwmon_attr_type { 473 MLXSW_HWMON_ATTR_TYPE_TEMP, 474 MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, 475 MLXSW_HWMON_ATTR_TYPE_TEMP_RST, 476 MLXSW_HWMON_ATTR_TYPE_FAN_RPM, 477 MLXSW_HWMON_ATTR_TYPE_FAN_FAULT, 478 MLXSW_HWMON_ATTR_TYPE_PWM, 479 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE, 480 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT, 481 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT, 482 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG, 483 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL, 484 MLXSW_HWMON_ATTR_TYPE_TEMP_GBOX_LABEL, 485 MLXSW_HWMON_ATTR_TYPE_TEMP_CRIT_ALARM, 486 MLXSW_HWMON_ATTR_TYPE_TEMP_EMERGENCY_ALARM, 487}; 488 489static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev, 490 enum mlxsw_hwmon_attr_type attr_type, 491 unsigned int type_index, unsigned int num) 492{ 493 struct mlxsw_hwmon_attr *mlxsw_hwmon_attr; 494 unsigned int attr_index; 495 496 attr_index = mlxsw_hwmon_dev->attrs_count; 497 mlxsw_hwmon_attr = &mlxsw_hwmon_dev->hwmon_attrs[attr_index]; 498 499 switch (attr_type) { 500 case MLXSW_HWMON_ATTR_TYPE_TEMP: 501 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_temp_show; 502 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 503 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 504 "temp%u_input", num + 1); 505 break; 506 case MLXSW_HWMON_ATTR_TYPE_TEMP_MAX: 507 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_temp_max_show; 508 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 509 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 510 "temp%u_highest", num + 1); 511 break; 512 case MLXSW_HWMON_ATTR_TYPE_TEMP_RST: 513 mlxsw_hwmon_attr->dev_attr.store = mlxsw_hwmon_temp_rst_store; 514 mlxsw_hwmon_attr->dev_attr.attr.mode = 0200; 515 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 516 "temp%u_reset_history", num + 1); 517 break; 518 case MLXSW_HWMON_ATTR_TYPE_FAN_RPM: 519 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_fan_rpm_show; 520 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 521 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 522 "fan%u_input", num + 1); 523 break; 524 case MLXSW_HWMON_ATTR_TYPE_FAN_FAULT: 525 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_fan_fault_show; 526 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 527 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 528 "fan%u_fault", num + 1); 529 break; 530 case MLXSW_HWMON_ATTR_TYPE_PWM: 531 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_pwm_show; 532 mlxsw_hwmon_attr->dev_attr.store = mlxsw_hwmon_pwm_store; 533 mlxsw_hwmon_attr->dev_attr.attr.mode = 0644; 534 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 535 "pwm%u", num + 1); 536 break; 537 case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE: 538 mlxsw_hwmon_attr->dev_attr.show = mlxsw_hwmon_module_temp_show; 539 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 540 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 541 "temp%u_input", num + 1); 542 break; 543 case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT: 544 mlxsw_hwmon_attr->dev_attr.show = 545 mlxsw_hwmon_module_temp_fault_show; 546 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 547 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 548 "temp%u_fault", num + 1); 549 break; 550 case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT: 551 mlxsw_hwmon_attr->dev_attr.show = 552 mlxsw_hwmon_module_temp_critical_show; 553 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 554 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 555 "temp%u_crit", num + 1); 556 break; 557 case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG: 558 mlxsw_hwmon_attr->dev_attr.show = 559 mlxsw_hwmon_module_temp_emergency_show; 560 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 561 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 562 "temp%u_emergency", num + 1); 563 break; 564 case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL: 565 mlxsw_hwmon_attr->dev_attr.show = 566 mlxsw_hwmon_module_temp_label_show; 567 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 568 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 569 "temp%u_label", num + 1); 570 break; 571 case MLXSW_HWMON_ATTR_TYPE_TEMP_GBOX_LABEL: 572 mlxsw_hwmon_attr->dev_attr.show = 573 mlxsw_hwmon_gbox_temp_label_show; 574 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 575 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 576 "temp%u_label", num + 1); 577 break; 578 case MLXSW_HWMON_ATTR_TYPE_TEMP_CRIT_ALARM: 579 mlxsw_hwmon_attr->dev_attr.show = 580 mlxsw_hwmon_temp_critical_alarm_show; 581 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 582 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 583 "temp%u_crit_alarm", num + 1); 584 break; 585 case MLXSW_HWMON_ATTR_TYPE_TEMP_EMERGENCY_ALARM: 586 mlxsw_hwmon_attr->dev_attr.show = 587 mlxsw_hwmon_temp_emergency_alarm_show; 588 mlxsw_hwmon_attr->dev_attr.attr.mode = 0444; 589 snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name), 590 "temp%u_emergency_alarm", num + 1); 591 break; 592 default: 593 WARN_ON(1); 594 } 595 596 mlxsw_hwmon_attr->type_index = type_index; 597 mlxsw_hwmon_attr->mlxsw_hwmon_dev = mlxsw_hwmon_dev; 598 mlxsw_hwmon_attr->dev_attr.attr.name = mlxsw_hwmon_attr->name; 599 sysfs_attr_init(&mlxsw_hwmon_attr->dev_attr.attr); 600 601 mlxsw_hwmon_dev->attrs[attr_index] = &mlxsw_hwmon_attr->dev_attr.attr; 602 mlxsw_hwmon_dev->attrs_count++; 603} 604 605static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev) 606{ 607 struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; 608 char mtcap_pl[MLXSW_REG_MTCAP_LEN] = {0}; 609 int i; 610 int err; 611 612 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtcap), mtcap_pl); 613 if (err) { 614 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to get number of temp sensors\n"); 615 return err; 616 } 617 mlxsw_hwmon_dev->sensor_count = mlxsw_reg_mtcap_sensor_count_get(mtcap_pl); 618 for (i = 0; i < mlxsw_hwmon_dev->sensor_count; i++) { 619 char mtmp_pl[MLXSW_REG_MTMP_LEN] = {0}; 620 621 mlxsw_reg_mtmp_slot_index_set(mtmp_pl, 622 mlxsw_hwmon_dev->slot_index); 623 mlxsw_reg_mtmp_sensor_index_set(mtmp_pl, i); 624 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), 625 mtmp_pl); 626 if (err) 627 return err; 628 mlxsw_reg_mtmp_mte_set(mtmp_pl, true); 629 mlxsw_reg_mtmp_mtr_set(mtmp_pl, true); 630 err = mlxsw_reg_write(mlxsw_hwmon->core, 631 MLXSW_REG(mtmp), mtmp_pl); 632 if (err) { 633 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to setup temp sensor number %d\n", 634 i); 635 return err; 636 } 637 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 638 MLXSW_HWMON_ATTR_TYPE_TEMP, i, i); 639 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 640 MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, i, i); 641 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 642 MLXSW_HWMON_ATTR_TYPE_TEMP_RST, i, i); 643 } 644 return 0; 645} 646 647static int mlxsw_hwmon_fans_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev) 648{ 649 struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; 650 char mfcr_pl[MLXSW_REG_MFCR_LEN] = {0}; 651 enum mlxsw_reg_mfcr_pwm_frequency freq; 652 unsigned int type_index; 653 unsigned int num; 654 u16 tacho_active; 655 u8 pwm_active; 656 int err; 657 658 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mfcr), mfcr_pl); 659 if (err) { 660 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to get to probe PWMs and Tachometers\n"); 661 return err; 662 } 663 mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active); 664 num = 0; 665 for (type_index = 0; type_index < MLXSW_MFCR_TACHOS_MAX; type_index++) { 666 if (tacho_active & BIT(type_index)) { 667 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 668 MLXSW_HWMON_ATTR_TYPE_FAN_RPM, 669 type_index, num); 670 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 671 MLXSW_HWMON_ATTR_TYPE_FAN_FAULT, 672 type_index, num++); 673 } 674 } 675 num = 0; 676 for (type_index = 0; type_index < MLXSW_MFCR_PWMS_MAX; type_index++) { 677 if (pwm_active & BIT(type_index)) 678 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 679 MLXSW_HWMON_ATTR_TYPE_PWM, 680 type_index, num++); 681 } 682 return 0; 683} 684 685static int mlxsw_hwmon_module_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev) 686{ 687 struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; 688 char mgpir_pl[MLXSW_REG_MGPIR_LEN]; 689 u8 module_sensor_max; 690 int i, err; 691 692 mlxsw_reg_mgpir_pack(mgpir_pl, mlxsw_hwmon_dev->slot_index); 693 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mgpir), mgpir_pl); 694 if (err) 695 return err; 696 697 mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, 698 &module_sensor_max, NULL); 699 700 /* Add extra attributes for module temperature. Sensor index is 701 * assigned to sensor_count value, while all indexed before 702 * sensor_count are already utilized by the sensors connected through 703 * mtmp register by mlxsw_hwmon_temp_init(). 704 */ 705 mlxsw_hwmon_dev->module_sensor_max = mlxsw_hwmon_dev->sensor_count + 706 module_sensor_max; 707 for (i = mlxsw_hwmon_dev->sensor_count; 708 i < mlxsw_hwmon_dev->module_sensor_max; i++) { 709 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 710 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE, i, i); 711 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 712 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT, 713 i, i); 714 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 715 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT, i, 716 i); 717 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 718 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG, 719 i, i); 720 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 721 MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL, 722 i, i); 723 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 724 MLXSW_HWMON_ATTR_TYPE_TEMP_CRIT_ALARM, 725 i, i); 726 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 727 MLXSW_HWMON_ATTR_TYPE_TEMP_EMERGENCY_ALARM, 728 i, i); 729 } 730 731 return 0; 732} 733 734static int mlxsw_hwmon_gearbox_init(struct mlxsw_hwmon_dev *mlxsw_hwmon_dev) 735{ 736 struct mlxsw_hwmon *mlxsw_hwmon = mlxsw_hwmon_dev->hwmon; 737 enum mlxsw_reg_mgpir_device_type device_type; 738 int index, max_index, sensor_index; 739 char mgpir_pl[MLXSW_REG_MGPIR_LEN]; 740 char mtmp_pl[MLXSW_REG_MTMP_LEN]; 741 u8 gbox_num; 742 int err; 743 744 mlxsw_reg_mgpir_pack(mgpir_pl, mlxsw_hwmon_dev->slot_index); 745 err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mgpir), mgpir_pl); 746 if (err) 747 return err; 748 749 mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, &device_type, NULL, NULL, 750 NULL); 751 if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE || 752 !gbox_num) 753 return 0; 754 755 index = mlxsw_hwmon_dev->module_sensor_max; 756 max_index = mlxsw_hwmon_dev->module_sensor_max + gbox_num; 757 while (index < max_index) { 758 sensor_index = index % mlxsw_hwmon_dev->module_sensor_max + 759 MLXSW_REG_MTMP_GBOX_INDEX_MIN; 760 mlxsw_reg_mtmp_pack(mtmp_pl, mlxsw_hwmon_dev->slot_index, 761 sensor_index, true, true); 762 err = mlxsw_reg_write(mlxsw_hwmon->core, 763 MLXSW_REG(mtmp), mtmp_pl); 764 if (err) { 765 dev_err(mlxsw_hwmon->bus_info->dev, "Failed to setup temp sensor number %d\n", 766 sensor_index); 767 return err; 768 } 769 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 770 MLXSW_HWMON_ATTR_TYPE_TEMP, index, index); 771 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 772 MLXSW_HWMON_ATTR_TYPE_TEMP_MAX, index, 773 index); 774 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 775 MLXSW_HWMON_ATTR_TYPE_TEMP_RST, index, 776 index); 777 mlxsw_hwmon_attr_add(mlxsw_hwmon_dev, 778 MLXSW_HWMON_ATTR_TYPE_TEMP_GBOX_LABEL, 779 index, index); 780 index++; 781 } 782 783 return 0; 784} 785 786static void 787mlxsw_hwmon_got_active(struct mlxsw_core *mlxsw_core, u8 slot_index, 788 void *priv) 789{ 790 struct mlxsw_hwmon *hwmon = priv; 791 struct mlxsw_hwmon_dev *linecard; 792 struct device *dev; 793 int err; 794 795 dev = hwmon->bus_info->dev; 796 linecard = &hwmon->line_cards[slot_index]; 797 if (linecard->active) 798 return; 799 /* For the main board, module sensor indexes start from 1, sensor index 800 * 0 is used for the ASIC. Use the same numbering for line cards. 801 */ 802 linecard->sensor_count = 1; 803 linecard->slot_index = slot_index; 804 linecard->hwmon = hwmon; 805 err = mlxsw_hwmon_module_init(linecard); 806 if (err) { 807 dev_err(dev, "Failed to configure hwmon objects for line card modules in slot %d\n", 808 slot_index); 809 return; 810 } 811 812 err = mlxsw_hwmon_gearbox_init(linecard); 813 if (err) { 814 dev_err(dev, "Failed to configure hwmon objects for line card gearboxes in slot %d\n", 815 slot_index); 816 return; 817 } 818 819 linecard->groups[0] = &linecard->group; 820 linecard->group.attrs = linecard->attrs; 821 sprintf(linecard->name, "%s#%02u", "linecard", slot_index); 822 linecard->hwmon_dev = 823 hwmon_device_register_with_groups(dev, linecard->name, 824 linecard, linecard->groups); 825 if (IS_ERR(linecard->hwmon_dev)) { 826 dev_err(dev, "Failed to register hwmon objects for line card in slot %d\n", 827 slot_index); 828 return; 829 } 830 831 linecard->active = true; 832} 833 834static void 835mlxsw_hwmon_got_inactive(struct mlxsw_core *mlxsw_core, u8 slot_index, 836 void *priv) 837{ 838 struct mlxsw_hwmon *hwmon = priv; 839 struct mlxsw_hwmon_dev *linecard; 840 841 linecard = &hwmon->line_cards[slot_index]; 842 if (!linecard->active) 843 return; 844 linecard->active = false; 845 hwmon_device_unregister(linecard->hwmon_dev); 846 /* Reset attributes counter */ 847 linecard->attrs_count = 0; 848} 849 850static struct mlxsw_linecards_event_ops mlxsw_hwmon_event_ops = { 851 .got_active = mlxsw_hwmon_got_active, 852 .got_inactive = mlxsw_hwmon_got_inactive, 853}; 854 855int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core, 856 const struct mlxsw_bus_info *mlxsw_bus_info, 857 struct mlxsw_hwmon **p_hwmon) 858{ 859 char mgpir_pl[MLXSW_REG_MGPIR_LEN]; 860 struct mlxsw_hwmon *mlxsw_hwmon; 861 struct device *hwmon_dev; 862 u8 num_of_slots; 863 int err; 864 865 mlxsw_reg_mgpir_pack(mgpir_pl, 0); 866 err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mgpir), mgpir_pl); 867 if (err) 868 return err; 869 870 mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, NULL, 871 &num_of_slots); 872 873 mlxsw_hwmon = kzalloc(struct_size(mlxsw_hwmon, line_cards, 874 num_of_slots + 1), GFP_KERNEL); 875 if (!mlxsw_hwmon) 876 return -ENOMEM; 877 878 mlxsw_hwmon->core = mlxsw_core; 879 mlxsw_hwmon->bus_info = mlxsw_bus_info; 880 mlxsw_hwmon->line_cards[0].hwmon = mlxsw_hwmon; 881 mlxsw_hwmon->line_cards[0].slot_index = 0; 882 883 err = mlxsw_hwmon_temp_init(&mlxsw_hwmon->line_cards[0]); 884 if (err) 885 goto err_temp_init; 886 887 err = mlxsw_hwmon_fans_init(&mlxsw_hwmon->line_cards[0]); 888 if (err) 889 goto err_fans_init; 890 891 err = mlxsw_hwmon_module_init(&mlxsw_hwmon->line_cards[0]); 892 if (err) 893 goto err_temp_module_init; 894 895 err = mlxsw_hwmon_gearbox_init(&mlxsw_hwmon->line_cards[0]); 896 if (err) 897 goto err_temp_gearbox_init; 898 899 mlxsw_hwmon->line_cards[0].groups[0] = &mlxsw_hwmon->line_cards[0].group; 900 mlxsw_hwmon->line_cards[0].group.attrs = mlxsw_hwmon->line_cards[0].attrs; 901 902 hwmon_dev = hwmon_device_register_with_groups(mlxsw_bus_info->dev, 903 "mlxsw", 904 &mlxsw_hwmon->line_cards[0], 905 mlxsw_hwmon->line_cards[0].groups); 906 if (IS_ERR(hwmon_dev)) { 907 err = PTR_ERR(hwmon_dev); 908 goto err_hwmon_register; 909 } 910 911 err = mlxsw_linecards_event_ops_register(mlxsw_hwmon->core, 912 &mlxsw_hwmon_event_ops, 913 mlxsw_hwmon); 914 if (err) 915 goto err_linecards_event_ops_register; 916 917 mlxsw_hwmon->line_cards[0].hwmon_dev = hwmon_dev; 918 mlxsw_hwmon->line_cards[0].active = true; 919 *p_hwmon = mlxsw_hwmon; 920 return 0; 921 922err_linecards_event_ops_register: 923 hwmon_device_unregister(mlxsw_hwmon->line_cards[0].hwmon_dev); 924err_hwmon_register: 925err_temp_gearbox_init: 926err_temp_module_init: 927err_fans_init: 928err_temp_init: 929 kfree(mlxsw_hwmon); 930 return err; 931} 932 933void mlxsw_hwmon_fini(struct mlxsw_hwmon *mlxsw_hwmon) 934{ 935 mlxsw_hwmon->line_cards[0].active = false; 936 mlxsw_linecards_event_ops_unregister(mlxsw_hwmon->core, 937 &mlxsw_hwmon_event_ops, mlxsw_hwmon); 938 hwmon_device_unregister(mlxsw_hwmon->line_cards[0].hwmon_dev); 939 kfree(mlxsw_hwmon); 940}