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
104105struct 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
116121static 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+
198231static 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+
354406static 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
367420static 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-
544595static 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
557648static 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+
782959int 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 );
8761059err_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