1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved
3 * Copyright (c) 2016 Ivan Vecera <cera@cera.cz>
4 */
5
6 #include <linux/kernel.h>
7 #include <linux/types.h>
8 #include <linux/device.h>
9 #include <linux/sysfs.h>
10 #include <linux/thermal.h>
11 #include <linux/err.h>
12 #include <linux/sfp.h>
13
14 #include "core.h"
15 #include "core_env.h"
16
17 #define MLXSW_THERMAL_POLL_INT 1000 /* ms */
18 #define MLXSW_THERMAL_SLOW_POLL_INT 20000 /* ms */
19 #define MLXSW_THERMAL_ASIC_TEMP_NORM 75000 /* 75C */
20 #define MLXSW_THERMAL_ASIC_TEMP_HIGH 85000 /* 85C */
21 #define MLXSW_THERMAL_ASIC_TEMP_HOT 105000 /* 105C */
22 #define MLXSW_THERMAL_MODULE_TEMP_NORM 55000 /* 55C */
23 #define MLXSW_THERMAL_MODULE_TEMP_HIGH 65000 /* 65C */
24 #define MLXSW_THERMAL_MODULE_TEMP_HOT 80000 /* 80C */
25 #define MLXSW_THERMAL_HYSTERESIS_TEMP 5000 /* 5C */
26 #define MLXSW_THERMAL_MODULE_TEMP_SHIFT (MLXSW_THERMAL_HYSTERESIS_TEMP * 2)
27 #define MLXSW_THERMAL_MAX_STATE 10
28 #define MLXSW_THERMAL_MIN_STATE 2
29 #define MLXSW_THERMAL_MAX_DUTY 255
30
31 /* External cooling devices, allowed for binding to mlxsw thermal zones. */
32 static char * const mlxsw_thermal_external_allowed_cdev[] = {
33 "mlxreg_fan",
34 };
35
36 struct mlxsw_cooling_states {
37 int min_state;
38 int max_state;
39 };
40
41 static const struct thermal_trip default_thermal_trips[] = {
42 { /* In range - 0-40% PWM */
43 .type = THERMAL_TRIP_ACTIVE,
44 .temperature = MLXSW_THERMAL_ASIC_TEMP_NORM,
45 .hysteresis = MLXSW_THERMAL_HYSTERESIS_TEMP,
46 },
47 {
48 /* In range - 40-100% PWM */
49 .type = THERMAL_TRIP_ACTIVE,
50 .temperature = MLXSW_THERMAL_ASIC_TEMP_HIGH,
51 .hysteresis = MLXSW_THERMAL_HYSTERESIS_TEMP,
52 },
53 { /* Warning */
54 .type = THERMAL_TRIP_HOT,
55 .temperature = MLXSW_THERMAL_ASIC_TEMP_HOT,
56 },
57 };
58
59 static const struct thermal_trip default_thermal_module_trips[] = {
60 { /* In range - 0-40% PWM */
61 .type = THERMAL_TRIP_ACTIVE,
62 .temperature = MLXSW_THERMAL_MODULE_TEMP_NORM,
63 .hysteresis = MLXSW_THERMAL_HYSTERESIS_TEMP,
64 },
65 {
66 /* In range - 40-100% PWM */
67 .type = THERMAL_TRIP_ACTIVE,
68 .temperature = MLXSW_THERMAL_MODULE_TEMP_HIGH,
69 .hysteresis = MLXSW_THERMAL_HYSTERESIS_TEMP,
70 },
71 { /* Warning */
72 .type = THERMAL_TRIP_HOT,
73 .temperature = MLXSW_THERMAL_MODULE_TEMP_HOT,
74 },
75 };
76
77 static const struct mlxsw_cooling_states default_cooling_states[] = {
78 {
79 .min_state = 0,
80 .max_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10,
81 },
82 {
83 .min_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10,
84 .max_state = MLXSW_THERMAL_MAX_STATE,
85 },
86 {
87 .min_state = MLXSW_THERMAL_MAX_STATE,
88 .max_state = MLXSW_THERMAL_MAX_STATE,
89 },
90 };
91
92 #define MLXSW_THERMAL_NUM_TRIPS ARRAY_SIZE(default_thermal_trips)
93
94 /* Make sure all trips are writable */
95 #define MLXSW_THERMAL_TRIP_MASK (BIT(MLXSW_THERMAL_NUM_TRIPS) - 1)
96
97 struct mlxsw_thermal;
98
99 struct mlxsw_thermal_module {
100 struct mlxsw_thermal *parent;
101 struct thermal_zone_device *tzdev;
102 struct thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
103 struct mlxsw_cooling_states cooling_states[MLXSW_THERMAL_NUM_TRIPS];
104 int module; /* Module or gearbox number */
105 u8 slot_index;
106 };
107
108 struct mlxsw_thermal_area {
109 struct mlxsw_thermal_module *tz_module_arr;
110 u8 tz_module_num;
111 struct mlxsw_thermal_module *tz_gearbox_arr;
112 u8 tz_gearbox_num;
113 u8 slot_index;
114 bool active;
115 };
116
117 struct mlxsw_thermal {
118 struct mlxsw_core *core;
119 const struct mlxsw_bus_info *bus_info;
120 struct thermal_zone_device *tzdev;
121 int polling_delay;
122 struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX];
123 struct thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
124 struct mlxsw_cooling_states cooling_states[MLXSW_THERMAL_NUM_TRIPS];
125 struct mlxsw_thermal_area line_cards[];
126 };
127
mlxsw_state_to_duty(int state)128 static inline u8 mlxsw_state_to_duty(int state)
129 {
130 return DIV_ROUND_CLOSEST(state * MLXSW_THERMAL_MAX_DUTY,
131 MLXSW_THERMAL_MAX_STATE);
132 }
133
mlxsw_duty_to_state(u8 duty)134 static inline int mlxsw_duty_to_state(u8 duty)
135 {
136 return DIV_ROUND_CLOSEST(duty * MLXSW_THERMAL_MAX_STATE,
137 MLXSW_THERMAL_MAX_DUTY);
138 }
139
mlxsw_get_cooling_device_idx(struct mlxsw_thermal * thermal,struct thermal_cooling_device * cdev)140 static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal,
141 struct thermal_cooling_device *cdev)
142 {
143 int i;
144
145 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
146 if (thermal->cdevs[i] == cdev)
147 return i;
148
149 /* Allow mlxsw thermal zone binding to an external cooling device */
150 for (i = 0; i < ARRAY_SIZE(mlxsw_thermal_external_allowed_cdev); i++) {
151 if (!strcmp(cdev->type, mlxsw_thermal_external_allowed_cdev[i]))
152 return 0;
153 }
154
155 return -ENODEV;
156 }
157
mlxsw_thermal_bind(struct thermal_zone_device * tzdev,struct thermal_cooling_device * cdev)158 static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev,
159 struct thermal_cooling_device *cdev)
160 {
161 struct mlxsw_thermal *thermal = thermal_zone_device_priv(tzdev);
162 struct device *dev = thermal->bus_info->dev;
163 int i, err;
164
165 /* If the cooling device is one of ours bind it */
166 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
167 return 0;
168
169 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
170 const struct mlxsw_cooling_states *state = &thermal->cooling_states[i];
171
172 err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
173 state->max_state,
174 state->min_state,
175 THERMAL_WEIGHT_DEFAULT);
176 if (err < 0) {
177 dev_err(dev, "Failed to bind cooling device to trip %d\n", i);
178 return err;
179 }
180 }
181 return 0;
182 }
183
mlxsw_thermal_unbind(struct thermal_zone_device * tzdev,struct thermal_cooling_device * cdev)184 static int mlxsw_thermal_unbind(struct thermal_zone_device *tzdev,
185 struct thermal_cooling_device *cdev)
186 {
187 struct mlxsw_thermal *thermal = thermal_zone_device_priv(tzdev);
188 struct device *dev = thermal->bus_info->dev;
189 int i;
190 int err;
191
192 /* If the cooling device is our one unbind it */
193 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
194 return 0;
195
196 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
197 err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
198 if (err < 0) {
199 dev_err(dev, "Failed to unbind cooling device\n");
200 return err;
201 }
202 }
203 return 0;
204 }
205
mlxsw_thermal_get_temp(struct thermal_zone_device * tzdev,int * p_temp)206 static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
207 int *p_temp)
208 {
209 struct mlxsw_thermal *thermal = thermal_zone_device_priv(tzdev);
210 struct device *dev = thermal->bus_info->dev;
211 char mtmp_pl[MLXSW_REG_MTMP_LEN];
212 int temp;
213 int err;
214
215 mlxsw_reg_mtmp_pack(mtmp_pl, 0, 0, false, false);
216
217 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
218 if (err) {
219 dev_err(dev, "Failed to query temp sensor\n");
220 return err;
221 }
222 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL, NULL, NULL);
223
224 *p_temp = temp;
225 return 0;
226 }
227
228 static struct thermal_zone_params mlxsw_thermal_params = {
229 .no_hwmon = true,
230 };
231
232 static struct thermal_zone_device_ops mlxsw_thermal_ops = {
233 .bind = mlxsw_thermal_bind,
234 .unbind = mlxsw_thermal_unbind,
235 .get_temp = mlxsw_thermal_get_temp,
236 };
237
mlxsw_thermal_module_bind(struct thermal_zone_device * tzdev,struct thermal_cooling_device * cdev)238 static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev,
239 struct thermal_cooling_device *cdev)
240 {
241 struct mlxsw_thermal_module *tz = thermal_zone_device_priv(tzdev);
242 struct mlxsw_thermal *thermal = tz->parent;
243 int i, j, err;
244
245 /* If the cooling device is one of ours bind it */
246 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
247 return 0;
248
249 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
250 const struct mlxsw_cooling_states *state = &tz->cooling_states[i];
251
252 err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
253 state->max_state,
254 state->min_state,
255 THERMAL_WEIGHT_DEFAULT);
256 if (err < 0)
257 goto err_thermal_zone_bind_cooling_device;
258 }
259 return 0;
260
261 err_thermal_zone_bind_cooling_device:
262 for (j = i - 1; j >= 0; j--)
263 thermal_zone_unbind_cooling_device(tzdev, j, cdev);
264 return err;
265 }
266
mlxsw_thermal_module_unbind(struct thermal_zone_device * tzdev,struct thermal_cooling_device * cdev)267 static int mlxsw_thermal_module_unbind(struct thermal_zone_device *tzdev,
268 struct thermal_cooling_device *cdev)
269 {
270 struct mlxsw_thermal_module *tz = thermal_zone_device_priv(tzdev);
271 struct mlxsw_thermal *thermal = tz->parent;
272 int i;
273 int err;
274
275 /* If the cooling device is one of ours unbind it */
276 if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
277 return 0;
278
279 for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
280 err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
281 WARN_ON(err);
282 }
283 return err;
284 }
285
mlxsw_thermal_module_temp_get(struct thermal_zone_device * tzdev,int * p_temp)286 static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,
287 int *p_temp)
288 {
289 struct mlxsw_thermal_module *tz = thermal_zone_device_priv(tzdev);
290 struct mlxsw_thermal *thermal = tz->parent;
291 char mtmp_pl[MLXSW_REG_MTMP_LEN];
292 u16 sensor_index;
293 int err;
294
295 sensor_index = MLXSW_REG_MTMP_MODULE_INDEX_MIN + tz->module;
296 mlxsw_reg_mtmp_pack(mtmp_pl, tz->slot_index, sensor_index,
297 false, false);
298 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
299 if (err)
300 return err;
301 mlxsw_reg_mtmp_unpack(mtmp_pl, p_temp, NULL, NULL, NULL, NULL);
302 return 0;
303 }
304
305 static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
306 .bind = mlxsw_thermal_module_bind,
307 .unbind = mlxsw_thermal_module_unbind,
308 .get_temp = mlxsw_thermal_module_temp_get,
309 };
310
mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device * tzdev,int * p_temp)311 static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev,
312 int *p_temp)
313 {
314 struct mlxsw_thermal_module *tz = thermal_zone_device_priv(tzdev);
315 struct mlxsw_thermal *thermal = tz->parent;
316 char mtmp_pl[MLXSW_REG_MTMP_LEN];
317 u16 index;
318 int temp;
319 int err;
320
321 index = MLXSW_REG_MTMP_GBOX_INDEX_MIN + tz->module;
322 mlxsw_reg_mtmp_pack(mtmp_pl, tz->slot_index, index, false, false);
323
324 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
325 if (err)
326 return err;
327
328 mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL, NULL, NULL);
329
330 *p_temp = temp;
331 return 0;
332 }
333
334 static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = {
335 .bind = mlxsw_thermal_module_bind,
336 .unbind = mlxsw_thermal_module_unbind,
337 .get_temp = mlxsw_thermal_gearbox_temp_get,
338 };
339
mlxsw_thermal_get_max_state(struct thermal_cooling_device * cdev,unsigned long * p_state)340 static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev,
341 unsigned long *p_state)
342 {
343 *p_state = MLXSW_THERMAL_MAX_STATE;
344 return 0;
345 }
346
mlxsw_thermal_get_cur_state(struct thermal_cooling_device * cdev,unsigned long * p_state)347 static int mlxsw_thermal_get_cur_state(struct thermal_cooling_device *cdev,
348 unsigned long *p_state)
349
350 {
351 struct mlxsw_thermal *thermal = cdev->devdata;
352 struct device *dev = thermal->bus_info->dev;
353 char mfsc_pl[MLXSW_REG_MFSC_LEN];
354 int err, idx;
355 u8 duty;
356
357 idx = mlxsw_get_cooling_device_idx(thermal, cdev);
358 if (idx < 0)
359 return idx;
360
361 mlxsw_reg_mfsc_pack(mfsc_pl, idx, 0);
362 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
363 if (err) {
364 dev_err(dev, "Failed to query PWM duty\n");
365 return err;
366 }
367
368 duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl);
369 *p_state = mlxsw_duty_to_state(duty);
370 return 0;
371 }
372
mlxsw_thermal_set_cur_state(struct thermal_cooling_device * cdev,unsigned long state)373 static int mlxsw_thermal_set_cur_state(struct thermal_cooling_device *cdev,
374 unsigned long state)
375
376 {
377 struct mlxsw_thermal *thermal = cdev->devdata;
378 struct device *dev = thermal->bus_info->dev;
379 char mfsc_pl[MLXSW_REG_MFSC_LEN];
380 int idx;
381 int err;
382
383 if (state > MLXSW_THERMAL_MAX_STATE)
384 return -EINVAL;
385
386 idx = mlxsw_get_cooling_device_idx(thermal, cdev);
387 if (idx < 0)
388 return idx;
389
390 /* Normalize the state to the valid speed range. */
391 state = max_t(unsigned long, MLXSW_THERMAL_MIN_STATE, state);
392 mlxsw_reg_mfsc_pack(mfsc_pl, idx, mlxsw_state_to_duty(state));
393 err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
394 if (err) {
395 dev_err(dev, "Failed to write PWM duty\n");
396 return err;
397 }
398 return 0;
399 }
400
401 static const struct thermal_cooling_device_ops mlxsw_cooling_ops = {
402 .get_max_state = mlxsw_thermal_get_max_state,
403 .get_cur_state = mlxsw_thermal_get_cur_state,
404 .set_cur_state = mlxsw_thermal_set_cur_state,
405 };
406
407 static int
mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module * module_tz)408 mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz)
409 {
410 char tz_name[THERMAL_NAME_LENGTH];
411 int err;
412
413 if (module_tz->slot_index)
414 snprintf(tz_name, sizeof(tz_name), "mlxsw-lc%d-module%d",
415 module_tz->slot_index, module_tz->module + 1);
416 else
417 snprintf(tz_name, sizeof(tz_name), "mlxsw-module%d",
418 module_tz->module + 1);
419 module_tz->tzdev = thermal_zone_device_register_with_trips(tz_name,
420 module_tz->trips,
421 MLXSW_THERMAL_NUM_TRIPS,
422 MLXSW_THERMAL_TRIP_MASK,
423 module_tz,
424 &mlxsw_thermal_module_ops,
425 &mlxsw_thermal_params,
426 0,
427 module_tz->parent->polling_delay);
428 if (IS_ERR(module_tz->tzdev)) {
429 err = PTR_ERR(module_tz->tzdev);
430 return err;
431 }
432
433 err = thermal_zone_device_enable(module_tz->tzdev);
434 if (err)
435 thermal_zone_device_unregister(module_tz->tzdev);
436
437 return err;
438 }
439
mlxsw_thermal_module_tz_fini(struct thermal_zone_device * tzdev)440 static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device *tzdev)
441 {
442 thermal_zone_device_unregister(tzdev);
443 }
444
445 static void
mlxsw_thermal_module_init(struct device * dev,struct mlxsw_core * core,struct mlxsw_thermal * thermal,struct mlxsw_thermal_area * area,u8 module)446 mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core,
447 struct mlxsw_thermal *thermal,
448 struct mlxsw_thermal_area *area, u8 module)
449 {
450 struct mlxsw_thermal_module *module_tz;
451
452 module_tz = &area->tz_module_arr[module];
453 /* Skip if parent is already set (case of port split). */
454 if (module_tz->parent)
455 return;
456 module_tz->module = module;
457 module_tz->slot_index = area->slot_index;
458 module_tz->parent = thermal;
459 BUILD_BUG_ON(ARRAY_SIZE(default_thermal_module_trips) !=
460 MLXSW_THERMAL_NUM_TRIPS);
461 memcpy(module_tz->trips, default_thermal_module_trips,
462 sizeof(thermal->trips));
463 memcpy(module_tz->cooling_states, default_cooling_states,
464 sizeof(thermal->cooling_states));
465 }
466
mlxsw_thermal_module_fini(struct mlxsw_thermal_module * module_tz)467 static void mlxsw_thermal_module_fini(struct mlxsw_thermal_module *module_tz)
468 {
469 if (module_tz && module_tz->tzdev) {
470 mlxsw_thermal_module_tz_fini(module_tz->tzdev);
471 module_tz->tzdev = NULL;
472 module_tz->parent = NULL;
473 }
474 }
475
476 static int
mlxsw_thermal_modules_init(struct device * dev,struct mlxsw_core * core,struct mlxsw_thermal * thermal,struct mlxsw_thermal_area * area)477 mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core,
478 struct mlxsw_thermal *thermal,
479 struct mlxsw_thermal_area *area)
480 {
481 struct mlxsw_thermal_module *module_tz;
482 char mgpir_pl[MLXSW_REG_MGPIR_LEN];
483 int i, err;
484
485 mlxsw_reg_mgpir_pack(mgpir_pl, area->slot_index);
486 err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
487 if (err)
488 return err;
489
490 mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL,
491 &area->tz_module_num, NULL);
492
493 /* For modular system module counter could be zero. */
494 if (!area->tz_module_num)
495 return 0;
496
497 area->tz_module_arr = kcalloc(area->tz_module_num,
498 sizeof(*area->tz_module_arr),
499 GFP_KERNEL);
500 if (!area->tz_module_arr)
501 return -ENOMEM;
502
503 for (i = 0; i < area->tz_module_num; i++)
504 mlxsw_thermal_module_init(dev, core, thermal, area, i);
505
506 for (i = 0; i < area->tz_module_num; i++) {
507 module_tz = &area->tz_module_arr[i];
508 if (!module_tz->parent)
509 continue;
510 err = mlxsw_thermal_module_tz_init(module_tz);
511 if (err)
512 goto err_thermal_module_tz_init;
513 }
514
515 return 0;
516
517 err_thermal_module_tz_init:
518 for (i = area->tz_module_num - 1; i >= 0; i--)
519 mlxsw_thermal_module_fini(&area->tz_module_arr[i]);
520 kfree(area->tz_module_arr);
521 return err;
522 }
523
524 static void
mlxsw_thermal_modules_fini(struct mlxsw_thermal * thermal,struct mlxsw_thermal_area * area)525 mlxsw_thermal_modules_fini(struct mlxsw_thermal *thermal,
526 struct mlxsw_thermal_area *area)
527 {
528 int i;
529
530 for (i = area->tz_module_num - 1; i >= 0; i--)
531 mlxsw_thermal_module_fini(&area->tz_module_arr[i]);
532 kfree(area->tz_module_arr);
533 }
534
535 static int
mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module * gearbox_tz)536 mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz)
537 {
538 char tz_name[THERMAL_NAME_LENGTH];
539 int ret;
540
541 if (gearbox_tz->slot_index)
542 snprintf(tz_name, sizeof(tz_name), "mlxsw-lc%d-gearbox%d",
543 gearbox_tz->slot_index, gearbox_tz->module + 1);
544 else
545 snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d",
546 gearbox_tz->module + 1);
547 gearbox_tz->tzdev = thermal_zone_device_register_with_trips(tz_name,
548 gearbox_tz->trips,
549 MLXSW_THERMAL_NUM_TRIPS,
550 MLXSW_THERMAL_TRIP_MASK,
551 gearbox_tz,
552 &mlxsw_thermal_gearbox_ops,
553 &mlxsw_thermal_params, 0,
554 gearbox_tz->parent->polling_delay);
555 if (IS_ERR(gearbox_tz->tzdev))
556 return PTR_ERR(gearbox_tz->tzdev);
557
558 ret = thermal_zone_device_enable(gearbox_tz->tzdev);
559 if (ret)
560 thermal_zone_device_unregister(gearbox_tz->tzdev);
561
562 return ret;
563 }
564
565 static void
mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module * gearbox_tz)566 mlxsw_thermal_gearbox_tz_fini(struct mlxsw_thermal_module *gearbox_tz)
567 {
568 thermal_zone_device_unregister(gearbox_tz->tzdev);
569 }
570
571 static int
mlxsw_thermal_gearboxes_init(struct device * dev,struct mlxsw_core * core,struct mlxsw_thermal * thermal,struct mlxsw_thermal_area * area)572 mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core,
573 struct mlxsw_thermal *thermal,
574 struct mlxsw_thermal_area *area)
575 {
576 enum mlxsw_reg_mgpir_device_type device_type;
577 struct mlxsw_thermal_module *gearbox_tz;
578 char mgpir_pl[MLXSW_REG_MGPIR_LEN];
579 u8 gbox_num;
580 int i;
581 int err;
582
583 mlxsw_reg_mgpir_pack(mgpir_pl, area->slot_index);
584 err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
585 if (err)
586 return err;
587
588 mlxsw_reg_mgpir_unpack(mgpir_pl, &gbox_num, &device_type, NULL,
589 NULL, NULL);
590 if (device_type != MLXSW_REG_MGPIR_DEVICE_TYPE_GEARBOX_DIE ||
591 !gbox_num)
592 return 0;
593
594 area->tz_gearbox_num = gbox_num;
595 area->tz_gearbox_arr = kcalloc(area->tz_gearbox_num,
596 sizeof(*area->tz_gearbox_arr),
597 GFP_KERNEL);
598 if (!area->tz_gearbox_arr)
599 return -ENOMEM;
600
601 for (i = 0; i < area->tz_gearbox_num; i++) {
602 gearbox_tz = &area->tz_gearbox_arr[i];
603 memcpy(gearbox_tz->trips, default_thermal_trips,
604 sizeof(thermal->trips));
605 memcpy(gearbox_tz->cooling_states, default_cooling_states,
606 sizeof(thermal->cooling_states));
607 gearbox_tz->module = i;
608 gearbox_tz->parent = thermal;
609 gearbox_tz->slot_index = area->slot_index;
610 err = mlxsw_thermal_gearbox_tz_init(gearbox_tz);
611 if (err)
612 goto err_thermal_gearbox_tz_init;
613 }
614
615 return 0;
616
617 err_thermal_gearbox_tz_init:
618 for (i--; i >= 0; i--)
619 mlxsw_thermal_gearbox_tz_fini(&area->tz_gearbox_arr[i]);
620 kfree(area->tz_gearbox_arr);
621 return err;
622 }
623
624 static void
mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal * thermal,struct mlxsw_thermal_area * area)625 mlxsw_thermal_gearboxes_fini(struct mlxsw_thermal *thermal,
626 struct mlxsw_thermal_area *area)
627 {
628 int i;
629
630 for (i = area->tz_gearbox_num - 1; i >= 0; i--)
631 mlxsw_thermal_gearbox_tz_fini(&area->tz_gearbox_arr[i]);
632 kfree(area->tz_gearbox_arr);
633 }
634
635 static void
mlxsw_thermal_got_active(struct mlxsw_core * mlxsw_core,u8 slot_index,void * priv)636 mlxsw_thermal_got_active(struct mlxsw_core *mlxsw_core, u8 slot_index,
637 void *priv)
638 {
639 struct mlxsw_thermal *thermal = priv;
640 struct mlxsw_thermal_area *linecard;
641 int err;
642
643 linecard = &thermal->line_cards[slot_index];
644
645 if (linecard->active)
646 return;
647
648 linecard->slot_index = slot_index;
649 err = mlxsw_thermal_modules_init(thermal->bus_info->dev, thermal->core,
650 thermal, linecard);
651 if (err) {
652 dev_err(thermal->bus_info->dev, "Failed to configure thermal objects for line card modules in slot %d\n",
653 slot_index);
654 return;
655 }
656
657 err = mlxsw_thermal_gearboxes_init(thermal->bus_info->dev,
658 thermal->core, thermal, linecard);
659 if (err) {
660 dev_err(thermal->bus_info->dev, "Failed to configure thermal objects for line card gearboxes in slot %d\n",
661 slot_index);
662 goto err_thermal_linecard_gearboxes_init;
663 }
664
665 linecard->active = true;
666
667 return;
668
669 err_thermal_linecard_gearboxes_init:
670 mlxsw_thermal_modules_fini(thermal, linecard);
671 }
672
673 static void
mlxsw_thermal_got_inactive(struct mlxsw_core * mlxsw_core,u8 slot_index,void * priv)674 mlxsw_thermal_got_inactive(struct mlxsw_core *mlxsw_core, u8 slot_index,
675 void *priv)
676 {
677 struct mlxsw_thermal *thermal = priv;
678 struct mlxsw_thermal_area *linecard;
679
680 linecard = &thermal->line_cards[slot_index];
681 if (!linecard->active)
682 return;
683 linecard->active = false;
684 mlxsw_thermal_gearboxes_fini(thermal, linecard);
685 mlxsw_thermal_modules_fini(thermal, linecard);
686 }
687
688 static struct mlxsw_linecards_event_ops mlxsw_thermal_event_ops = {
689 .got_active = mlxsw_thermal_got_active,
690 .got_inactive = mlxsw_thermal_got_inactive,
691 };
692
mlxsw_thermal_init(struct mlxsw_core * core,const struct mlxsw_bus_info * bus_info,struct mlxsw_thermal ** p_thermal)693 int mlxsw_thermal_init(struct mlxsw_core *core,
694 const struct mlxsw_bus_info *bus_info,
695 struct mlxsw_thermal **p_thermal)
696 {
697 char mfcr_pl[MLXSW_REG_MFCR_LEN] = { 0 };
698 enum mlxsw_reg_mfcr_pwm_frequency freq;
699 struct device *dev = bus_info->dev;
700 char mgpir_pl[MLXSW_REG_MGPIR_LEN];
701 struct mlxsw_thermal *thermal;
702 u8 pwm_active, num_of_slots;
703 u16 tacho_active;
704 int err, i;
705
706 mlxsw_reg_mgpir_pack(mgpir_pl, 0);
707 err = mlxsw_reg_query(core, MLXSW_REG(mgpir), mgpir_pl);
708 if (err)
709 return err;
710
711 mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, NULL,
712 &num_of_slots);
713
714 thermal = kzalloc(struct_size(thermal, line_cards, num_of_slots + 1),
715 GFP_KERNEL);
716 if (!thermal)
717 return -ENOMEM;
718
719 thermal->core = core;
720 thermal->bus_info = bus_info;
721 memcpy(thermal->trips, default_thermal_trips, sizeof(thermal->trips));
722 memcpy(thermal->cooling_states, default_cooling_states, sizeof(thermal->cooling_states));
723 thermal->line_cards[0].slot_index = 0;
724
725 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl);
726 if (err) {
727 dev_err(dev, "Failed to probe PWMs\n");
728 goto err_reg_query;
729 }
730 mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active);
731
732 for (i = 0; i < MLXSW_MFCR_TACHOS_MAX; i++) {
733 if (tacho_active & BIT(i)) {
734 char mfsl_pl[MLXSW_REG_MFSL_LEN];
735
736 mlxsw_reg_mfsl_pack(mfsl_pl, i, 0, 0);
737
738 /* We need to query the register to preserve maximum */
739 err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsl),
740 mfsl_pl);
741 if (err)
742 goto err_reg_query;
743
744 /* set the minimal RPMs to 0 */
745 mlxsw_reg_mfsl_tach_min_set(mfsl_pl, 0);
746 err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsl),
747 mfsl_pl);
748 if (err)
749 goto err_reg_write;
750 }
751 }
752 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
753 if (pwm_active & BIT(i)) {
754 struct thermal_cooling_device *cdev;
755
756 cdev = thermal_cooling_device_register("mlxsw_fan",
757 thermal,
758 &mlxsw_cooling_ops);
759 if (IS_ERR(cdev)) {
760 err = PTR_ERR(cdev);
761 dev_err(dev, "Failed to register cooling device\n");
762 goto err_thermal_cooling_device_register;
763 }
764 thermal->cdevs[i] = cdev;
765 }
766 }
767
768 thermal->polling_delay = bus_info->low_frequency ?
769 MLXSW_THERMAL_SLOW_POLL_INT :
770 MLXSW_THERMAL_POLL_INT;
771
772 thermal->tzdev = thermal_zone_device_register_with_trips("mlxsw",
773 thermal->trips,
774 MLXSW_THERMAL_NUM_TRIPS,
775 MLXSW_THERMAL_TRIP_MASK,
776 thermal,
777 &mlxsw_thermal_ops,
778 &mlxsw_thermal_params, 0,
779 thermal->polling_delay);
780 if (IS_ERR(thermal->tzdev)) {
781 err = PTR_ERR(thermal->tzdev);
782 dev_err(dev, "Failed to register thermal zone\n");
783 goto err_thermal_zone_device_register;
784 }
785
786 err = mlxsw_thermal_modules_init(dev, core, thermal,
787 &thermal->line_cards[0]);
788 if (err)
789 goto err_thermal_modules_init;
790
791 err = mlxsw_thermal_gearboxes_init(dev, core, thermal,
792 &thermal->line_cards[0]);
793 if (err)
794 goto err_thermal_gearboxes_init;
795
796 err = mlxsw_linecards_event_ops_register(core,
797 &mlxsw_thermal_event_ops,
798 thermal);
799 if (err)
800 goto err_linecards_event_ops_register;
801
802 err = thermal_zone_device_enable(thermal->tzdev);
803 if (err)
804 goto err_thermal_zone_device_enable;
805
806 thermal->line_cards[0].active = true;
807 *p_thermal = thermal;
808 return 0;
809
810 err_thermal_zone_device_enable:
811 mlxsw_linecards_event_ops_unregister(thermal->core,
812 &mlxsw_thermal_event_ops,
813 thermal);
814 err_linecards_event_ops_register:
815 mlxsw_thermal_gearboxes_fini(thermal, &thermal->line_cards[0]);
816 err_thermal_gearboxes_init:
817 mlxsw_thermal_modules_fini(thermal, &thermal->line_cards[0]);
818 err_thermal_modules_init:
819 if (thermal->tzdev) {
820 thermal_zone_device_unregister(thermal->tzdev);
821 thermal->tzdev = NULL;
822 }
823 err_thermal_zone_device_register:
824 err_thermal_cooling_device_register:
825 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
826 if (thermal->cdevs[i])
827 thermal_cooling_device_unregister(thermal->cdevs[i]);
828 err_reg_write:
829 err_reg_query:
830 kfree(thermal);
831 return err;
832 }
833
mlxsw_thermal_fini(struct mlxsw_thermal * thermal)834 void mlxsw_thermal_fini(struct mlxsw_thermal *thermal)
835 {
836 int i;
837
838 thermal->line_cards[0].active = false;
839 mlxsw_linecards_event_ops_unregister(thermal->core,
840 &mlxsw_thermal_event_ops,
841 thermal);
842 mlxsw_thermal_gearboxes_fini(thermal, &thermal->line_cards[0]);
843 mlxsw_thermal_modules_fini(thermal, &thermal->line_cards[0]);
844 if (thermal->tzdev) {
845 thermal_zone_device_unregister(thermal->tzdev);
846 thermal->tzdev = NULL;
847 }
848
849 for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
850 if (thermal->cdevs[i]) {
851 thermal_cooling_device_unregister(thermal->cdevs[i]);
852 thermal->cdevs[i] = NULL;
853 }
854 }
855
856 kfree(thermal);
857 }
858