Skip to content
This repository was archived by the owner on Nov 7, 2025. It is now read-only.

Commit 18f3896

Browse files
committed
Merge branch 'mlxsw-Thermal-and-hwmon-extensions'
Ido Schimmel says: ==================== mlxsw: Thermal and hwmon extensions This patchset from Vadim includes various enhancements to thermal and hwmon code in mlxsw. Patch #1 adds a thermal zone for each inter-connect device (gearbox). These devices are present in SN3800 systems and code to expose their temperature via hwmon was added in commit 2e265a8 ("mlxsw: core: Extend hwmon interface with inter-connect temperature attributes"). Currently, there are multiple thermal zones in mlxsw and only a few cooling devices. Patch #2 detects the hottest thermal zone and the cooling devices are switched to follow its trends. RFC was sent last month [1]. Patch #3 allows to read and report negative temperature of the sensors mlxsw exposes via hwmon and thermal subsystems. v2 (Andrew Lunn): * In patch #3, replace '%u' with '%d' in mlxsw_hwmon_module_temp_show() [1] https://patchwork.ozlabs.org/patch/1107161/ ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents c04b6ea + f485cc3 commit 18f3896

File tree

3 files changed

+209
-25
lines changed

3 files changed

+209
-25
lines changed

drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,7 @@ static ssize_t mlxsw_hwmon_temp_show(struct device *dev,
5252
container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
5353
struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
5454
char mtmp_pl[MLXSW_REG_MTMP_LEN];
55-
unsigned int temp;
56-
int index;
55+
int temp, index;
5756
int err;
5857

5958
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,
6564
return err;
6665
}
6766
mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
68-
return sprintf(buf, "%u\n", temp);
67+
return sprintf(buf, "%d\n", temp);
6968
}
7069

7170
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,
7675
container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
7776
struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
7877
char mtmp_pl[MLXSW_REG_MTMP_LEN];
79-
unsigned int temp_max;
80-
int index;
78+
int temp_max, index;
8179
int err;
8280

8381
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,
8987
return err;
9088
}
9189
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);
9391
}
9492

9593
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,
215213
container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
216214
struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
217215
char mtmp_pl[MLXSW_REG_MTMP_LEN];
218-
unsigned int temp;
219216
u8 module;
217+
int temp;
220218
int err;
221219

222220
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,
227225
return err;
228226
mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
229227

230-
return sprintf(buf, "%u\n", temp);
228+
return sprintf(buf, "%d\n", temp);
231229
}
232230

233231
static ssize_t mlxsw_hwmon_module_temp_fault_show(struct device *dev,

drivers/net/ethernet/mellanox/mlxsw/core_thermal.c

Lines changed: 196 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#define MLXSW_THERMAL_HYSTERESIS_TEMP 5000 /* 5C */
2424
#define MLXSW_THERMAL_MODULE_TEMP_SHIFT (MLXSW_THERMAL_HYSTERESIS_TEMP * 2)
2525
#define MLXSW_THERMAL_ZONE_MAX_NAME 16
26+
#define MLXSW_THERMAL_TEMP_SCORE_MAX GENMASK(31, 0)
2627
#define MLXSW_THERMAL_MAX_STATE 10
2728
#define MLXSW_THERMAL_MAX_DUTY 255
2829
/* Minimum and maximum fan allowed speed in percent: from 20% to 100%. Values
@@ -98,7 +99,7 @@ struct mlxsw_thermal_module {
9899
struct thermal_zone_device *tzdev;
99100
struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
100101
enum thermal_device_mode mode;
101-
int module;
102+
int module; /* Module or gearbox number */
102103
};
103104

104105
struct mlxsw_thermal {
@@ -111,6 +112,10 @@ struct mlxsw_thermal {
111112
struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
112113
enum thermal_device_mode mode;
113114
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;
114119
};
115120

116121
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,
195200
return 0;
196201
}
197202

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+
198231
static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev,
199232
struct thermal_cooling_device *cdev)
200233
{
@@ -279,7 +312,7 @@ static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
279312
struct mlxsw_thermal *thermal = tzdev->devdata;
280313
struct device *dev = thermal->bus_info->dev;
281314
char mtmp_pl[MLXSW_REG_MTMP_LEN];
282-
unsigned int temp;
315+
int temp;
283316
int err;
284317

285318
mlxsw_reg_mtmp_pack(mtmp_pl, 0, false, false);
@@ -290,8 +323,11 @@ static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
290323
return err;
291324
}
292325
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);
293329

294-
*p_temp = (int) temp;
330+
*p_temp = temp;
295331
return 0;
296332
}
297333

@@ -351,6 +387,22 @@ static int mlxsw_thermal_set_trip_hyst(struct thermal_zone_device *tzdev,
351387
return 0;
352388
}
353389

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+
354406
static struct thermal_zone_device_ops mlxsw_thermal_ops = {
355407
.bind = mlxsw_thermal_bind,
356408
.unbind = mlxsw_thermal_unbind,
@@ -362,6 +414,7 @@ static struct thermal_zone_device_ops mlxsw_thermal_ops = {
362414
.set_trip_temp = mlxsw_thermal_set_trip_temp,
363415
.get_trip_hyst = mlxsw_thermal_get_trip_hyst,
364416
.set_trip_hyst = mlxsw_thermal_set_trip_hyst,
417+
.get_trend = mlxsw_thermal_trend_get,
365418
};
366419

367420
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,
450503
struct mlxsw_thermal *thermal = tz->parent;
451504
struct device *dev = thermal->bus_info->dev;
452505
char mtmp_pl[MLXSW_REG_MTMP_LEN];
453-
unsigned int temp;
506+
int temp;
454507
int err;
455508

456509
/* Read module temperature. */
@@ -466,13 +519,15 @@ static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,
466519
return 0;
467520
}
468521
mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
469-
*p_temp = (int) temp;
522+
*p_temp = temp;
470523

471524
if (!temp)
472525
return 0;
473526

474527
/* 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);
476531

477532
return 0;
478533
}
@@ -537,10 +592,6 @@ mlxsw_thermal_module_trip_hyst_set(struct thermal_zone_device *tzdev, int trip,
537592
return 0;
538593
}
539594

540-
static struct thermal_zone_params mlxsw_thermal_module_params = {
541-
.governor_name = "user_space",
542-
};
543-
544595
static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
545596
.bind = mlxsw_thermal_module_bind,
546597
.unbind = mlxsw_thermal_module_unbind,
@@ -552,6 +603,46 @@ static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
552603
.set_trip_temp = mlxsw_thermal_module_trip_temp_set,
553604
.get_trip_hyst = mlxsw_thermal_module_trip_hyst_get,
554605
.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,
555646
};
556647

557648
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)
667758
MLXSW_THERMAL_TRIP_MASK,
668759
module_tz,
669760
&mlxsw_thermal_module_ops,
670-
&mlxsw_thermal_module_params,
671-
0, 0);
761+
NULL, 0, 0);
672762
if (IS_ERR(module_tz->tzdev)) {
673763
err = PTR_ERR(module_tz->tzdev);
674764
return err;
675765
}
676766

767+
module_tz->mode = THERMAL_DEVICE_ENABLED;
677768
return 0;
678769
}
679770

@@ -779,6 +870,92 @@ mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal)
779870
kfree(thermal->tz_module_arr);
780871
}
781872

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+
782959
int mlxsw_thermal_init(struct mlxsw_core *core,
783960
const struct mlxsw_bus_info *bus_info,
784961
struct mlxsw_thermal **p_thermal)
@@ -869,10 +1046,16 @@ int mlxsw_thermal_init(struct mlxsw_core *core,
8691046
if (err)
8701047
goto err_unreg_tzdev;
8711048

1049+
err = mlxsw_thermal_gearboxes_init(dev, core, thermal);
1050+
if (err)
1051+
goto err_unreg_modules_tzdev;
1052+
8721053
thermal->mode = THERMAL_DEVICE_ENABLED;
8731054
*p_thermal = thermal;
8741055
return 0;
8751056

1057+
err_unreg_modules_tzdev:
1058+
mlxsw_thermal_modules_fini(thermal);
8761059
err_unreg_tzdev:
8771060
if (thermal->tzdev) {
8781061
thermal_zone_device_unregister(thermal->tzdev);
@@ -891,6 +1074,7 @@ void mlxsw_thermal_fini(struct mlxsw_thermal *thermal)
8911074
{
8921075
int i;
8931076

1077+
mlxsw_thermal_gearboxes_fini(thermal);
8941078
mlxsw_thermal_modules_fini(thermal);
8951079
if (thermal->tzdev) {
8961080
thermal_zone_device_unregister(thermal->tzdev);

0 commit comments

Comments
 (0)