diff options
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c | 14 | ||||
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 208 | ||||
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/reg.h | 12 |
3 files changed, 209 insertions, 25 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c index 056e3f55ae6c..5b00726c4346 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c | |||
| @@ -52,8 +52,7 @@ static ssize_t mlxsw_hwmon_temp_show(struct device *dev, | |||
| 52 | container_of(attr, struct mlxsw_hwmon_attr, dev_attr); | 52 | container_of(attr, struct mlxsw_hwmon_attr, dev_attr); |
| 53 | struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; | 53 | struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; |
| 54 | char mtmp_pl[MLXSW_REG_MTMP_LEN]; | 54 | char mtmp_pl[MLXSW_REG_MTMP_LEN]; |
| 55 | unsigned int temp; | 55 | int temp, index; |
| 56 | int index; | ||
| 57 | int err; | 56 | int err; |
| 58 | 57 | ||
| 59 | index = mlxsw_hwmon_get_attr_index(mlwsw_hwmon_attr->type_index, | 58 | index = mlxsw_hwmon_get_attr_index(mlwsw_hwmon_attr->type_index, |
| @@ -65,7 +64,7 @@ static ssize_t mlxsw_hwmon_temp_show(struct device *dev, | |||
| 65 | return err; | 64 | return err; |
| 66 | } | 65 | } |
| 67 | mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL); | 66 | mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL); |
| 68 | return sprintf(buf, "%u\n", temp); | 67 | return sprintf(buf, "%d\n", temp); |
| 69 | } | 68 | } |
| 70 | 69 | ||
| 71 | static ssize_t mlxsw_hwmon_temp_max_show(struct device *dev, | 70 | static ssize_t mlxsw_hwmon_temp_max_show(struct device *dev, |
| @@ -76,8 +75,7 @@ static ssize_t mlxsw_hwmon_temp_max_show(struct device *dev, | |||
| 76 | container_of(attr, struct mlxsw_hwmon_attr, dev_attr); | 75 | container_of(attr, struct mlxsw_hwmon_attr, dev_attr); |
| 77 | struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; | 76 | struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; |
| 78 | char mtmp_pl[MLXSW_REG_MTMP_LEN]; | 77 | char mtmp_pl[MLXSW_REG_MTMP_LEN]; |
| 79 | unsigned int temp_max; | 78 | int temp_max, index; |
| 80 | int index; | ||
| 81 | int err; | 79 | int err; |
| 82 | 80 | ||
| 83 | index = mlxsw_hwmon_get_attr_index(mlwsw_hwmon_attr->type_index, | 81 | index = mlxsw_hwmon_get_attr_index(mlwsw_hwmon_attr->type_index, |
| @@ -89,7 +87,7 @@ static ssize_t mlxsw_hwmon_temp_max_show(struct device *dev, | |||
| 89 | return err; | 87 | return err; |
| 90 | } | 88 | } |
| 91 | mlxsw_reg_mtmp_unpack(mtmp_pl, NULL, &temp_max, NULL); | 89 | mlxsw_reg_mtmp_unpack(mtmp_pl, NULL, &temp_max, NULL); |
| 92 | return sprintf(buf, "%u\n", temp_max); | 90 | return sprintf(buf, "%d\n", temp_max); |
| 93 | } | 91 | } |
| 94 | 92 | ||
| 95 | static ssize_t mlxsw_hwmon_temp_rst_store(struct device *dev, | 93 | static ssize_t mlxsw_hwmon_temp_rst_store(struct device *dev, |
| @@ -215,8 +213,8 @@ static ssize_t mlxsw_hwmon_module_temp_show(struct device *dev, | |||
| 215 | container_of(attr, struct mlxsw_hwmon_attr, dev_attr); | 213 | container_of(attr, struct mlxsw_hwmon_attr, dev_attr); |
| 216 | struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; | 214 | struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon; |
| 217 | char mtmp_pl[MLXSW_REG_MTMP_LEN]; | 215 | char mtmp_pl[MLXSW_REG_MTMP_LEN]; |
| 218 | unsigned int temp; | ||
| 219 | u8 module; | 216 | u8 module; |
| 217 | int temp; | ||
| 220 | int err; | 218 | int err; |
| 221 | 219 | ||
| 222 | module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; | 220 | module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count; |
| @@ -227,7 +225,7 @@ static ssize_t mlxsw_hwmon_module_temp_show(struct device *dev, | |||
| 227 | return err; | 225 | return err; |
| 228 | mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL); | 226 | mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL); |
| 229 | 227 | ||
| 230 | return sprintf(buf, "%u\n", temp); | 228 | return sprintf(buf, "%d\n", temp); |
| 231 | } | 229 | } |
| 232 | 230 | ||
| 233 | static ssize_t mlxsw_hwmon_module_temp_fault_show(struct device *dev, | 231 | static ssize_t mlxsw_hwmon_module_temp_fault_show(struct device *dev, |
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c index cfab0e330a47..35a1dc89c28a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #define MLXSW_THERMAL_HYSTERESIS_TEMP 5000 /* 5C */ | 23 | #define MLXSW_THERMAL_HYSTERESIS_TEMP 5000 /* 5C */ |
| 24 | #define MLXSW_THERMAL_MODULE_TEMP_SHIFT (MLXSW_THERMAL_HYSTERESIS_TEMP * 2) | 24 | #define MLXSW_THERMAL_MODULE_TEMP_SHIFT (MLXSW_THERMAL_HYSTERESIS_TEMP * 2) |
| 25 | #define MLXSW_THERMAL_ZONE_MAX_NAME 16 | 25 | #define MLXSW_THERMAL_ZONE_MAX_NAME 16 |
| 26 | #define MLXSW_THERMAL_TEMP_SCORE_MAX GENMASK(31, 0) | ||
| 26 | #define MLXSW_THERMAL_MAX_STATE 10 | 27 | #define MLXSW_THERMAL_MAX_STATE 10 |
| 27 | #define MLXSW_THERMAL_MAX_DUTY 255 | 28 | #define MLXSW_THERMAL_MAX_DUTY 255 |
| 28 | /* Minimum and maximum fan allowed speed in percent: from 20% to 100%. Values | 29 | /* Minimum and maximum fan allowed speed in percent: from 20% to 100%. Values |
| @@ -98,7 +99,7 @@ struct mlxsw_thermal_module { | |||
| 98 | struct thermal_zone_device *tzdev; | 99 | struct thermal_zone_device *tzdev; |
| 99 | struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; | 100 | struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; |
| 100 | enum thermal_device_mode mode; | 101 | enum thermal_device_mode mode; |
| 101 | int module; | 102 | int module; /* Module or gearbox number */ |
| 102 | }; | 103 | }; |
| 103 | 104 | ||
| 104 | struct mlxsw_thermal { | 105 | struct mlxsw_thermal { |
| @@ -111,6 +112,10 @@ struct mlxsw_thermal { | |||
| 111 | struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; | 112 | struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; |
| 112 | enum thermal_device_mode mode; | 113 | enum thermal_device_mode mode; |
| 113 | struct mlxsw_thermal_module *tz_module_arr; | 114 | struct mlxsw_thermal_module *tz_module_arr; |
| 115 | struct mlxsw_thermal_module *tz_gearbox_arr; | ||
| 116 | u8 tz_gearbox_num; | ||
| 117 | unsigned int tz_highest_score; | ||
| 118 | struct thermal_zone_device *tz_highest_dev; | ||
| 114 | }; | 119 | }; |
| 115 | 120 | ||
| 116 | static inline u8 mlxsw_state_to_duty(int state) | 121 | static inline u8 mlxsw_state_to_duty(int state) |
| @@ -195,6 +200,34 @@ mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core, | |||
| 195 | return 0; | 200 | return 0; |
| 196 | } | 201 | } |
| 197 | 202 | ||
| 203 | static void mlxsw_thermal_tz_score_update(struct mlxsw_thermal *thermal, | ||
| 204 | struct thermal_zone_device *tzdev, | ||
| 205 | struct mlxsw_thermal_trip *trips, | ||
| 206 | int temp) | ||
| 207 | { | ||
| 208 | struct mlxsw_thermal_trip *trip = trips; | ||
| 209 | unsigned int score, delta, i, shift = 1; | ||
| 210 | |||
| 211 | /* Calculate thermal zone score, if temperature is above the critical | ||
| 212 | * threshold score is set to MLXSW_THERMAL_TEMP_SCORE_MAX. | ||
| 213 | */ | ||
| 214 | score = MLXSW_THERMAL_TEMP_SCORE_MAX; | ||
| 215 | for (i = MLXSW_THERMAL_TEMP_TRIP_NORM; i < MLXSW_THERMAL_NUM_TRIPS; | ||
| 216 | i++, trip++) { | ||
| 217 | if (temp < trip->temp) { | ||
| 218 | delta = DIV_ROUND_CLOSEST(temp, trip->temp - temp); | ||
| 219 | score = delta * shift; | ||
| 220 | break; | ||
| 221 | } | ||
| 222 | shift *= 256; | ||
| 223 | } | ||
| 224 | |||
| 225 | if (score > thermal->tz_highest_score) { | ||
| 226 | thermal->tz_highest_score = score; | ||
| 227 | thermal->tz_highest_dev = tzdev; | ||
| 228 | } | ||
| 229 | } | ||
| 230 | |||
| 198 | static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev, | 231 | static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev, |
| 199 | struct thermal_cooling_device *cdev) | 232 | struct thermal_cooling_device *cdev) |
| 200 | { | 233 | { |
| @@ -279,7 +312,7 @@ static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev, | |||
| 279 | struct mlxsw_thermal *thermal = tzdev->devdata; | 312 | struct mlxsw_thermal *thermal = tzdev->devdata; |
| 280 | struct device *dev = thermal->bus_info->dev; | 313 | struct device *dev = thermal->bus_info->dev; |
| 281 | char mtmp_pl[MLXSW_REG_MTMP_LEN]; | 314 | char mtmp_pl[MLXSW_REG_MTMP_LEN]; |
| 282 | unsigned int temp; | 315 | int temp; |
| 283 | int err; | 316 | int err; |
| 284 | 317 | ||
| 285 | mlxsw_reg_mtmp_pack(mtmp_pl, 0, false, false); | 318 | mlxsw_reg_mtmp_pack(mtmp_pl, 0, false, false); |
| @@ -290,8 +323,11 @@ static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev, | |||
| 290 | return err; | 323 | return err; |
| 291 | } | 324 | } |
| 292 | mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL); | 325 | mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL); |
| 326 | if (temp > 0) | ||
| 327 | mlxsw_thermal_tz_score_update(thermal, tzdev, thermal->trips, | ||
| 328 | temp); | ||
| 293 | 329 | ||
| 294 | *p_temp = (int) temp; | 330 | *p_temp = temp; |
| 295 | return 0; | 331 | return 0; |
| 296 | } | 332 | } |
| 297 | 333 | ||
| @@ -351,6 +387,22 @@ static int mlxsw_thermal_set_trip_hyst(struct thermal_zone_device *tzdev, | |||
| 351 | return 0; | 387 | return 0; |
| 352 | } | 388 | } |
| 353 | 389 | ||
| 390 | static int mlxsw_thermal_trend_get(struct thermal_zone_device *tzdev, | ||
| 391 | int trip, enum thermal_trend *trend) | ||
| 392 | { | ||
| 393 | struct mlxsw_thermal_module *tz = tzdev->devdata; | ||
| 394 | struct mlxsw_thermal *thermal = tz->parent; | ||
| 395 | |||
| 396 | if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS) | ||
| 397 | return -EINVAL; | ||
| 398 | |||
| 399 | if (tzdev == thermal->tz_highest_dev) | ||
| 400 | return 1; | ||
| 401 | |||
| 402 | *trend = THERMAL_TREND_STABLE; | ||
| 403 | return 0; | ||
| 404 | } | ||
| 405 | |||
| 354 | static struct thermal_zone_device_ops mlxsw_thermal_ops = { | 406 | static struct thermal_zone_device_ops mlxsw_thermal_ops = { |
| 355 | .bind = mlxsw_thermal_bind, | 407 | .bind = mlxsw_thermal_bind, |
| 356 | .unbind = mlxsw_thermal_unbind, | 408 | .unbind = mlxsw_thermal_unbind, |
| @@ -362,6 +414,7 @@ static struct thermal_zone_device_ops mlxsw_thermal_ops = { | |||
| 362 | .set_trip_temp = mlxsw_thermal_set_trip_temp, | 414 | .set_trip_temp = mlxsw_thermal_set_trip_temp, |
| 363 | .get_trip_hyst = mlxsw_thermal_get_trip_hyst, | 415 | .get_trip_hyst = mlxsw_thermal_get_trip_hyst, |
| 364 | .set_trip_hyst = mlxsw_thermal_set_trip_hyst, | 416 | .set_trip_hyst = mlxsw_thermal_set_trip_hyst, |
| 417 | .get_trend = mlxsw_thermal_trend_get, | ||
| 365 | }; | 418 | }; |
| 366 | 419 | ||
| 367 | static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev, | 420 | static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev, |
| @@ -450,7 +503,7 @@ static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev, | |||
| 450 | struct mlxsw_thermal *thermal = tz->parent; | 503 | struct mlxsw_thermal *thermal = tz->parent; |
| 451 | struct device *dev = thermal->bus_info->dev; | 504 | struct device *dev = thermal->bus_info->dev; |
| 452 | char mtmp_pl[MLXSW_REG_MTMP_LEN]; | 505 | char mtmp_pl[MLXSW_REG_MTMP_LEN]; |
| 453 | unsigned int temp; | 506 | int temp; |
| 454 | int err; | 507 | int err; |
| 455 | 508 | ||
| 456 | /* Read module temperature. */ | 509 | /* Read module temperature. */ |
| @@ -466,13 +519,15 @@ static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev, | |||
| 466 | return 0; | 519 | return 0; |
| 467 | } | 520 | } |
| 468 | mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL); | 521 | mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL); |
| 469 | *p_temp = (int) temp; | 522 | *p_temp = temp; |
| 470 | 523 | ||
| 471 | if (!temp) | 524 | if (!temp) |
| 472 | return 0; | 525 | return 0; |
| 473 | 526 | ||
| 474 | /* Update trip points. */ | 527 | /* Update trip points. */ |
| 475 | mlxsw_thermal_module_trips_update(dev, thermal->core, tz); | 528 | err = mlxsw_thermal_module_trips_update(dev, thermal->core, tz); |
| 529 | if (!err && temp > 0) | ||
| 530 | mlxsw_thermal_tz_score_update(thermal, tzdev, tz->trips, temp); | ||
| 476 | 531 | ||
| 477 | return 0; | 532 | return 0; |
| 478 | } | 533 | } |
| @@ -537,10 +592,6 @@ mlxsw_thermal_module_trip_hyst_set(struct thermal_zone_device *tzdev, int trip, | |||
| 537 | return 0; | 592 | return 0; |
| 538 | } | 593 | } |
| 539 | 594 | ||
| 540 | static struct thermal_zone_params mlxsw_thermal_module_params = { | ||
| 541 | .governor_name = "user_space", | ||
| 542 | }; | ||
| 543 | |||
| 544 | static struct thermal_zone_device_ops mlxsw_thermal_module_ops = { | 595 | static struct thermal_zone_device_ops mlxsw_thermal_module_ops = { |
| 545 | .bind = mlxsw_thermal_module_bind, | 596 | .bind = mlxsw_thermal_module_bind, |
| 546 | .unbind = mlxsw_thermal_module_unbind, | 597 | .unbind = mlxsw_thermal_module_unbind, |
| @@ -552,6 +603,46 @@ static struct thermal_zone_device_ops mlxsw_thermal_module_ops = { | |||
| 552 | .set_trip_temp = mlxsw_thermal_module_trip_temp_set, | 603 | .set_trip_temp = mlxsw_thermal_module_trip_temp_set, |
| 553 | .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get, | 604 | .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get, |
| 554 | .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set, | 605 | .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set, |
| 606 | .get_trend = mlxsw_thermal_trend_get, | ||
| 607 | }; | ||
| 608 | |||
| 609 | static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev, | ||
| 610 | int *p_temp) | ||
| 611 | { | ||
| 612 | struct mlxsw_thermal_module *tz = tzdev->devdata; | ||
| 613 | struct mlxsw_thermal *thermal = tz->parent; | ||
| 614 | char mtmp_pl[MLXSW_REG_MTMP_LEN]; | ||
| 615 | u16 index; | ||
| 616 | int temp; | ||
| 617 | int err; | ||
| 618 | |||
| 619 | index = MLXSW_REG_MTMP_GBOX_INDEX_MIN + tz->module; | ||
| 620 | mlxsw_reg_mtmp_pack(mtmp_pl, index, false, false); | ||
| 621 | |||
| 622 | err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl); | ||
| 623 | if (err) | ||
| 624 | return err; | ||
| 625 | |||
| 626 | mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL); | ||
| 627 | if (temp > 0) | ||
| 628 | mlxsw_thermal_tz_score_update(thermal, tzdev, tz->trips, temp); | ||
| 629 | |||
| 630 | *p_temp = temp; | ||
| 631 | return 0; | ||
| 632 | } | ||
| 633 | |||
| 634 | static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = { | ||
| 635 | .bind = mlxsw_thermal_module_bind, | ||
| 636 | .unbind = mlxsw_thermal_module_unbind, | ||
| 637 | .get_mode = mlxsw_thermal_module_mode_get, | ||
| 638 | .set_mode = mlxsw_thermal_module_mode_set, | ||
| 639 | .get_temp = mlxsw_thermal_gearbox_temp_get, | ||
| 640 | .get_trip_type = mlxsw_thermal_module_trip_type_get, | ||
| 641 | .get_trip_temp = mlxsw_thermal_module_trip_temp_get, | ||
| 642 | .set_trip_temp = mlxsw_thermal_module_trip_temp_set, | ||
| 643 | .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get, | ||
| 644 | .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set, | ||
| 645 | .get_trend = mlxsw_thermal_trend_get, | ||
| 555 | }; | 646 | }; |
| 556 | 647 | ||
| 557 | static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev, | 648 | static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev, |
| @@ -667,13 +758,13 @@ mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz) | |||
| 667 | MLXSW_THERMAL_TRIP_MASK, | 758 | MLXSW_THERMAL_TRIP_MASK, |
| 668 | module_tz, | 759 | module_tz, |
| 669 | &mlxsw_thermal_module_ops, | 760 | &mlxsw_thermal_module_ops, |
| 670 | &mlxsw_thermal_module_params, | 761 | NULL, 0, 0); |
| 671 | 0, 0); | ||
| 672 | if (IS_ERR(module_tz->tzdev)) { | 762 | if (IS_ERR(module_tz->tzdev)) { |
| 673 | err = PTR_ERR(module_tz->tzdev); | 763 | err = PTR_ERR(module_tz->tzdev); |
| 674 | return err; | 764 | return err; |
| 675 | } | 765 | } |
| 676 | 766 | ||
| 767 | module_tz->mode = THERMAL_DEVICE_ENABLED; | ||
| 677 | return 0; | 768 | return 0; |
| 678 | } | 769 | } |
| 679 | 770 | ||
| @@ -779,6 +870,92 @@ mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal) | |||
| 779 | kfree(thermal->tz_module_arr); | 870 | kfree(thermal->tz_module_arr); |
| 780 | } | 871 | } |
| 781 | 872 | ||
| 873 | static int | ||
| 874 | mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz) | ||
| 875 | { | ||
| 876 | char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME]; | ||
| 877 | |||
| 878 | snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d", | ||
| 879 | gearbox_tz->module + 1); | ||
| 880 | gearbox_tz->tzdev = thermal_zone_device_register(tz_name, | ||
| 881 | MLXSW_THERMAL_NUM_TRIPS, | ||
| 882 | MLXSW_THERMAL_TRIP_MASK, | ||
| 883 | gearbox_tz, | ||
| 884 | &mlxsw_thermal_gearbox_ops, | ||
| 885 | NULL, 0, 0); | ||
| 886 | if (IS_ERR(gearbox_tz->tzdev)) | ||
| 887 | return PTR_ERR(gearbox_tz->tzdev); | ||
| 888 | |||
| 889 | gearbox_tz->mode = THERMAL_DEVICE_ENABLED; | ||
| 890 | return 0; | ||
| 891 | } | ||
| 892 | |||
| 893 | static void | ||
| 894 | mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module *gearbox_tz) | ||
| 895 | { | ||
| 896 | thermal_zone_device_unregister(gearbox_tz->tzdev); | ||
| 897 | } | ||
| 898 | |||
| 899 | static int | ||
| 900 | mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, | ||
| 901 | struct mlxsw_thermal *thermal) | ||
| 902 | { | ||
| 903 | struct mlxsw_thermal_module *gearbox_tz; | ||
| 904 | char mgpir_pl[MLXSW_REG_MGPIR_LEN]; | ||
| 905 | int i; | ||
| 906 | int err; | ||
| 907 | |||
| 908 | if (!mlxsw_core_res_query_enabled(core)) | ||
| 909 | return 0; | ||
| 910 | |||
| 911 | mlxsw_reg_mgpir_pack(mgpir_pl); | ||
| 912 | err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl); | ||
| 913 | if (err) | ||
| 914 | return err; | ||
| 915 | |||
| 916 | mlxsw_reg_mgpir_unpack(mgpir_pl, &thermal->tz_gearbox_num, NULL, NULL); | ||
| 917 | if (!thermal->tz_gearbox_num) | ||
| 918 | return 0; | ||
| 919 | |||
| 920 | thermal->tz_gearbox_arr = kcalloc(thermal->tz_gearbox_num, | ||
| 921 | sizeof(*thermal->tz_gearbox_arr), | ||
| 922 | GFP_KERNEL); | ||
| 923 | if (!thermal->tz_gearbox_arr) | ||
| 924 | return -ENOMEM; | ||
| 925 | |||
| 926 | for (i = 0; i < thermal->tz_gearbox_num; i++) { | ||
| 927 | gearbox_tz = &thermal->tz_gearbox_arr[i]; | ||
| 928 | memcpy(gearbox_tz->trips, default_thermal_trips, | ||
| 929 | sizeof(thermal->trips)); | ||
| 930 | gearbox_tz->module = i; | ||
| 931 | gearbox_tz->parent = thermal; | ||
| 932 | err = mlxsw_thermal_gearbox_tz_init(gearbox_tz); | ||
| 933 | if (err) | ||
| 934 | goto err_unreg_tz_gearbox; | ||
| 935 | } | ||
| 936 | |||
| 937 | return 0; | ||
| 938 | |||
| 939 | err_unreg_tz_gearbox: | ||
| 940 | for (i--; i >= 0; i--) | ||
| 941 | mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]); | ||
| 942 | kfree(thermal->tz_gearbox_arr); | ||
| 943 | return err; | ||
| 944 | } | ||
| 945 | |||
| 946 | static void | ||
| 947 | mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal) | ||
| 948 | { | ||
| 949 | int i; | ||
| 950 | |||
| 951 | if (!mlxsw_core_res_query_enabled(thermal->core)) | ||
| 952 | return; | ||
| 953 | |||
| 954 | for (i = thermal->tz_gearbox_num - 1; i >= 0; i--) | ||
| 955 | mlxsw_thermal_gearbox_tz_fini(&thermal->tz_gearbox_arr[i]); | ||
| 956 | kfree(thermal->tz_gearbox_arr); | ||
| 957 | } | ||
| 958 | |||
| 782 | int mlxsw_thermal_init(struct mlxsw_core *core, | 959 | int mlxsw_thermal_init(struct mlxsw_core *core, |
| 783 | const struct mlxsw_bus_info *bus_info, | 960 | const struct mlxsw_bus_info *bus_info, |
| 784 | struct mlxsw_thermal **p_thermal) | 961 | struct mlxsw_thermal **p_thermal) |
| @@ -869,10 +1046,16 @@ int mlxsw_thermal_init(struct mlxsw_core *core, | |||
| 869 | if (err) | 1046 | if (err) |
| 870 | goto err_unreg_tzdev; | 1047 | goto err_unreg_tzdev; |
| 871 | 1048 | ||
| 1049 | err = mlxsw_thermal_gearboxes_init(dev, core, thermal); | ||
| 1050 | if (err) | ||
| 1051 | goto err_unreg_modules_tzdev; | ||
| 1052 | |||
| 872 | thermal->mode = THERMAL_DEVICE_ENABLED; | 1053 | thermal->mode = THERMAL_DEVICE_ENABLED; |
| 873 | *p_thermal = thermal; | 1054 | *p_thermal = thermal; |
| 874 | return 0; | 1055 | return 0; |
| 875 | 1056 | ||
| 1057 | err_unreg_modules_tzdev: | ||
| 1058 | mlxsw_thermal_modules_fini(thermal); | ||
| 876 | err_unreg_tzdev: | 1059 | err_unreg_tzdev: |
| 877 | if (thermal->tzdev) { | 1060 | if (thermal->tzdev) { |
| 878 | thermal_zone_device_unregister(thermal->tzdev); | 1061 | thermal_zone_device_unregister(thermal->tzdev); |
| @@ -891,6 +1074,7 @@ void mlxsw_thermal_fini(struct mlxsw_thermal *thermal) | |||
| 891 | { | 1074 | { |
| 892 | int i; | 1075 | int i; |
| 893 | 1076 | ||
| 1077 | mlxsw_thermal_gearboxes_fini(thermal); | ||
| 894 | mlxsw_thermal_modules_fini(thermal); | 1078 | mlxsw_thermal_modules_fini(thermal); |
| 895 | if (thermal->tzdev) { | 1079 | if (thermal->tzdev) { |
| 896 | thermal_zone_device_unregister(thermal->tzdev); | 1080 | thermal_zone_device_unregister(thermal->tzdev); |
diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 452f645fa040..e5f6bfd8a35a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h | |||
| @@ -8050,7 +8050,10 @@ MLXSW_REG_DEFINE(mtmp, MLXSW_REG_MTMP_ID, MLXSW_REG_MTMP_LEN); | |||
| 8050 | MLXSW_ITEM32(reg, mtmp, sensor_index, 0x00, 0, 12); | 8050 | MLXSW_ITEM32(reg, mtmp, sensor_index, 0x00, 0, 12); |
| 8051 | 8051 | ||
| 8052 | /* Convert to milli degrees Celsius */ | 8052 | /* Convert to milli degrees Celsius */ |
| 8053 | #define MLXSW_REG_MTMP_TEMP_TO_MC(val) (val * 125) | 8053 | #define MLXSW_REG_MTMP_TEMP_TO_MC(val) ({ typeof(val) v_ = (val); \ |
| 8054 | ((v_) >= 0) ? ((v_) * 125) : \ | ||
| 8055 | ((s16)((GENMASK(15, 0) + (v_) + 1) \ | ||
| 8056 | * 125)); }) | ||
| 8054 | 8057 | ||
| 8055 | /* reg_mtmp_temperature | 8058 | /* reg_mtmp_temperature |
| 8056 | * Temperature reading from the sensor. Reading is in 0.125 Celsius | 8059 | * Temperature reading from the sensor. Reading is in 0.125 Celsius |
| @@ -8121,11 +8124,10 @@ static inline void mlxsw_reg_mtmp_pack(char *payload, u16 sensor_index, | |||
| 8121 | MLXSW_REG_MTMP_THRESH_HI); | 8124 | MLXSW_REG_MTMP_THRESH_HI); |
| 8122 | } | 8125 | } |
| 8123 | 8126 | ||
| 8124 | static inline void mlxsw_reg_mtmp_unpack(char *payload, unsigned int *p_temp, | 8127 | static inline void mlxsw_reg_mtmp_unpack(char *payload, int *p_temp, |
| 8125 | unsigned int *p_max_temp, | 8128 | int *p_max_temp, char *sensor_name) |
| 8126 | char *sensor_name) | ||
| 8127 | { | 8129 | { |
| 8128 | u16 temp; | 8130 | s16 temp; |
| 8129 | 8131 | ||
| 8130 | if (p_temp) { | 8132 | if (p_temp) { |
| 8131 | temp = mlxsw_reg_mtmp_temperature_get(payload); | 8133 | temp = mlxsw_reg_mtmp_temperature_get(payload); |
