aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c14
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core_thermal.c208
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/reg.h12
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
71static ssize_t mlxsw_hwmon_temp_max_show(struct device *dev, 70static 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
95static ssize_t mlxsw_hwmon_temp_rst_store(struct device *dev, 93static 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
233static ssize_t mlxsw_hwmon_module_temp_fault_show(struct device *dev, 231static 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
104struct mlxsw_thermal { 105struct 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
116static inline u8 mlxsw_state_to_duty(int state) 121static 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
203static 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
198static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev, 231static 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
390static 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
354static struct thermal_zone_device_ops mlxsw_thermal_ops = { 406static 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
367static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev, 420static 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
540static struct thermal_zone_params mlxsw_thermal_module_params = {
541 .governor_name = "user_space",
542};
543
544static struct thermal_zone_device_ops mlxsw_thermal_module_ops = { 595static 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
609static 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
634static 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
557static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev, 648static 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
873static int
874mlxsw_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
893static void
894mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module *gearbox_tz)
895{
896 thermal_zone_device_unregister(gearbox_tz->tzdev);
897}
898
899static int
900mlxsw_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
939err_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
946static void
947mlxsw_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
782int mlxsw_thermal_init(struct mlxsw_core *core, 959int 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
1057err_unreg_modules_tzdev:
1058 mlxsw_thermal_modules_fini(thermal);
876err_unreg_tzdev: 1059err_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);
8050MLXSW_ITEM32(reg, mtmp, sensor_index, 0x00, 0, 12); 8050MLXSW_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
8124static inline void mlxsw_reg_mtmp_unpack(char *payload, unsigned int *p_temp, 8127static 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);