7
7
#include <linux/sysfs.h>
8
8
#include <linux/hwmon.h>
9
9
#include <linux/err.h>
10
+ #include <linux/sfp.h>
10
11
11
12
#include "core.h"
13
+ #include "core_env.h"
12
14
13
15
#define MLXSW_HWMON_TEMP_SENSOR_MAX_COUNT 127
14
16
#define MLXSW_HWMON_ATTR_COUNT (MLXSW_HWMON_TEMP_SENSOR_MAX_COUNT * 4 + \
@@ -30,6 +32,7 @@ struct mlxsw_hwmon {
30
32
struct attribute * attrs [MLXSW_HWMON_ATTR_COUNT + 1 ];
31
33
struct mlxsw_hwmon_attr hwmon_attrs [MLXSW_HWMON_ATTR_COUNT ];
32
34
unsigned int attrs_count ;
35
+ u8 sensor_count ;
33
36
};
34
37
35
38
static ssize_t mlxsw_hwmon_temp_show (struct device * dev ,
@@ -188,13 +191,147 @@ static ssize_t mlxsw_hwmon_pwm_store(struct device *dev,
188
191
return len ;
189
192
}
190
193
194
+ static ssize_t mlxsw_hwmon_module_temp_show (struct device * dev ,
195
+ struct device_attribute * attr ,
196
+ char * buf )
197
+ {
198
+ struct mlxsw_hwmon_attr * mlwsw_hwmon_attr =
199
+ container_of (attr , struct mlxsw_hwmon_attr , dev_attr );
200
+ struct mlxsw_hwmon * mlxsw_hwmon = mlwsw_hwmon_attr -> hwmon ;
201
+ char mtbr_pl [MLXSW_REG_MTBR_LEN ] = {0 };
202
+ u16 temp ;
203
+ u8 module ;
204
+ int err ;
205
+
206
+ module = mlwsw_hwmon_attr -> type_index - mlxsw_hwmon -> sensor_count ;
207
+ mlxsw_reg_mtbr_pack (mtbr_pl , MLXSW_REG_MTBR_BASE_MODULE_INDEX + module ,
208
+ 1 );
209
+ err = mlxsw_reg_query (mlxsw_hwmon -> core , MLXSW_REG (mtbr ), mtbr_pl );
210
+ if (err ) {
211
+ dev_err (dev , "Failed to query module temprature sensor\n" );
212
+ return err ;
213
+ }
214
+
215
+ mlxsw_reg_mtbr_temp_unpack (mtbr_pl , 0 , & temp , NULL );
216
+ /* Update status and temperature cache. */
217
+ switch (temp ) {
218
+ case MLXSW_REG_MTBR_NO_CONN : /* fall-through */
219
+ case MLXSW_REG_MTBR_NO_TEMP_SENS : /* fall-through */
220
+ case MLXSW_REG_MTBR_INDEX_NA :
221
+ temp = 0 ;
222
+ break ;
223
+ case MLXSW_REG_MTBR_BAD_SENS_INFO :
224
+ /* Untrusted cable is connected. Reading temperature from its
225
+ * sensor is faulty.
226
+ */
227
+ temp = 0 ;
228
+ break ;
229
+ default :
230
+ temp = MLXSW_REG_MTMP_TEMP_TO_MC (temp );
231
+ break ;
232
+ }
233
+
234
+ return sprintf (buf , "%u\n" , temp );
235
+ }
236
+
237
+ static ssize_t mlxsw_hwmon_module_temp_fault_show (struct device * dev ,
238
+ struct device_attribute * attr ,
239
+ char * buf )
240
+ {
241
+ struct mlxsw_hwmon_attr * mlwsw_hwmon_attr =
242
+ container_of (attr , struct mlxsw_hwmon_attr , dev_attr );
243
+ struct mlxsw_hwmon * mlxsw_hwmon = mlwsw_hwmon_attr -> hwmon ;
244
+ char mtbr_pl [MLXSW_REG_MTBR_LEN ] = {0 };
245
+ u8 module , fault ;
246
+ u16 temp ;
247
+ int err ;
248
+
249
+ module = mlwsw_hwmon_attr -> type_index - mlxsw_hwmon -> sensor_count ;
250
+ mlxsw_reg_mtbr_pack (mtbr_pl , MLXSW_REG_MTBR_BASE_MODULE_INDEX + module ,
251
+ 1 );
252
+ err = mlxsw_reg_query (mlxsw_hwmon -> core , MLXSW_REG (mtbr ), mtbr_pl );
253
+ if (err ) {
254
+ dev_err (dev , "Failed to query module temprature sensor\n" );
255
+ return err ;
256
+ }
257
+
258
+ mlxsw_reg_mtbr_temp_unpack (mtbr_pl , 0 , & temp , NULL );
259
+
260
+ /* Update status and temperature cache. */
261
+ switch (temp ) {
262
+ case MLXSW_REG_MTBR_BAD_SENS_INFO :
263
+ /* Untrusted cable is connected. Reading temperature from its
264
+ * sensor is faulty.
265
+ */
266
+ fault = 1 ;
267
+ break ;
268
+ case MLXSW_REG_MTBR_NO_CONN : /* fall-through */
269
+ case MLXSW_REG_MTBR_NO_TEMP_SENS : /* fall-through */
270
+ case MLXSW_REG_MTBR_INDEX_NA :
271
+ default :
272
+ fault = 0 ;
273
+ break ;
274
+ }
275
+
276
+ return sprintf (buf , "%u\n" , fault );
277
+ }
278
+
279
+ static ssize_t
280
+ mlxsw_hwmon_module_temp_critical_show (struct device * dev ,
281
+ struct device_attribute * attr , char * buf )
282
+ {
283
+ struct mlxsw_hwmon_attr * mlwsw_hwmon_attr =
284
+ container_of (attr , struct mlxsw_hwmon_attr , dev_attr );
285
+ struct mlxsw_hwmon * mlxsw_hwmon = mlwsw_hwmon_attr -> hwmon ;
286
+ int temp ;
287
+ u8 module ;
288
+ int err ;
289
+
290
+ module = mlwsw_hwmon_attr -> type_index - mlxsw_hwmon -> sensor_count ;
291
+ err = mlxsw_env_module_temp_thresholds_get (mlxsw_hwmon -> core , module ,
292
+ SFP_TEMP_HIGH_WARN , & temp );
293
+ if (err ) {
294
+ dev_err (dev , "Failed to query module temprature thresholds\n" );
295
+ return err ;
296
+ }
297
+
298
+ return sprintf (buf , "%u\n" , temp );
299
+ }
300
+
301
+ static ssize_t
302
+ mlxsw_hwmon_module_temp_emergency_show (struct device * dev ,
303
+ struct device_attribute * attr ,
304
+ char * buf )
305
+ {
306
+ struct mlxsw_hwmon_attr * mlwsw_hwmon_attr =
307
+ container_of (attr , struct mlxsw_hwmon_attr , dev_attr );
308
+ struct mlxsw_hwmon * mlxsw_hwmon = mlwsw_hwmon_attr -> hwmon ;
309
+ u8 module ;
310
+ int temp ;
311
+ int err ;
312
+
313
+ module = mlwsw_hwmon_attr -> type_index - mlxsw_hwmon -> sensor_count ;
314
+ err = mlxsw_env_module_temp_thresholds_get (mlxsw_hwmon -> core , module ,
315
+ SFP_TEMP_HIGH_ALARM , & temp );
316
+ if (err ) {
317
+ dev_err (dev , "Failed to query module temprature thresholds\n" );
318
+ return err ;
319
+ }
320
+
321
+ return sprintf (buf , "%u\n" , temp );
322
+ }
323
+
191
324
enum mlxsw_hwmon_attr_type {
192
325
MLXSW_HWMON_ATTR_TYPE_TEMP ,
193
326
MLXSW_HWMON_ATTR_TYPE_TEMP_MAX ,
194
327
MLXSW_HWMON_ATTR_TYPE_TEMP_RST ,
195
328
MLXSW_HWMON_ATTR_TYPE_FAN_RPM ,
196
329
MLXSW_HWMON_ATTR_TYPE_FAN_FAULT ,
197
330
MLXSW_HWMON_ATTR_TYPE_PWM ,
331
+ MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE ,
332
+ MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT ,
333
+ MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT ,
334
+ MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG ,
198
335
};
199
336
200
337
static void mlxsw_hwmon_attr_add (struct mlxsw_hwmon * mlxsw_hwmon ,
@@ -244,6 +381,33 @@ static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon,
244
381
snprintf (mlxsw_hwmon_attr -> name , sizeof (mlxsw_hwmon_attr -> name ),
245
382
"pwm%u" , num + 1 );
246
383
break ;
384
+ case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE :
385
+ mlxsw_hwmon_attr -> dev_attr .show = mlxsw_hwmon_module_temp_show ;
386
+ mlxsw_hwmon_attr -> dev_attr .attr .mode = 0444 ;
387
+ snprintf (mlxsw_hwmon_attr -> name , sizeof (mlxsw_hwmon_attr -> name ),
388
+ "temp%u_input" , num + 1 );
389
+ break ;
390
+ case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT :
391
+ mlxsw_hwmon_attr -> dev_attr .show =
392
+ mlxsw_hwmon_module_temp_fault_show ;
393
+ mlxsw_hwmon_attr -> dev_attr .attr .mode = 0444 ;
394
+ snprintf (mlxsw_hwmon_attr -> name , sizeof (mlxsw_hwmon_attr -> name ),
395
+ "temp%u_fault" , num + 1 );
396
+ break ;
397
+ case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT :
398
+ mlxsw_hwmon_attr -> dev_attr .show =
399
+ mlxsw_hwmon_module_temp_critical_show ;
400
+ mlxsw_hwmon_attr -> dev_attr .attr .mode = 0444 ;
401
+ snprintf (mlxsw_hwmon_attr -> name , sizeof (mlxsw_hwmon_attr -> name ),
402
+ "temp%u_crit" , num + 1 );
403
+ break ;
404
+ case MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG :
405
+ mlxsw_hwmon_attr -> dev_attr .show =
406
+ mlxsw_hwmon_module_temp_emergency_show ;
407
+ mlxsw_hwmon_attr -> dev_attr .attr .mode = 0444 ;
408
+ snprintf (mlxsw_hwmon_attr -> name , sizeof (mlxsw_hwmon_attr -> name ),
409
+ "temp%u_emergency" , num + 1 );
410
+ break ;
247
411
default :
248
412
WARN_ON (1 );
249
413
}
@@ -261,7 +425,6 @@ static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon *mlxsw_hwmon)
261
425
{
262
426
char mtcap_pl [MLXSW_REG_MTCAP_LEN ] = {0 };
263
427
char mtmp_pl [MLXSW_REG_MTMP_LEN ];
264
- u8 sensor_count ;
265
428
int i ;
266
429
int err ;
267
430
@@ -270,8 +433,8 @@ static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon *mlxsw_hwmon)
270
433
dev_err (mlxsw_hwmon -> bus_info -> dev , "Failed to get number of temp sensors\n" );
271
434
return err ;
272
435
}
273
- sensor_count = mlxsw_reg_mtcap_sensor_count_get (mtcap_pl );
274
- for (i = 0 ; i < sensor_count ; i ++ ) {
436
+ mlxsw_hwmon -> sensor_count = mlxsw_reg_mtcap_sensor_count_get (mtcap_pl );
437
+ for (i = 0 ; i < mlxsw_hwmon -> sensor_count ; i ++ ) {
275
438
mlxsw_reg_mtmp_pack (mtmp_pl , i , true, true);
276
439
err = mlxsw_reg_write (mlxsw_hwmon -> core ,
277
440
MLXSW_REG (mtmp ), mtmp_pl );
@@ -327,6 +490,50 @@ static int mlxsw_hwmon_fans_init(struct mlxsw_hwmon *mlxsw_hwmon)
327
490
return 0 ;
328
491
}
329
492
493
+ static int mlxsw_hwmon_module_init (struct mlxsw_hwmon * mlxsw_hwmon )
494
+ {
495
+ unsigned int module_count = mlxsw_core_max_ports (mlxsw_hwmon -> core );
496
+ char pmlp_pl [MLXSW_REG_PMLP_LEN ] = {0 };
497
+ int i , index ;
498
+ u8 width ;
499
+ int err ;
500
+
501
+ /* Add extra attributes for module temperature. Sensor index is
502
+ * assigned to sensor_count value, while all indexed before
503
+ * sensor_count are already utilized by the sensors connected through
504
+ * mtmp register by mlxsw_hwmon_temp_init().
505
+ */
506
+ index = mlxsw_hwmon -> sensor_count ;
507
+ for (i = 1 ; i < module_count ; i ++ ) {
508
+ mlxsw_reg_pmlp_pack (pmlp_pl , i );
509
+ err = mlxsw_reg_query (mlxsw_hwmon -> core , MLXSW_REG (pmlp ),
510
+ pmlp_pl );
511
+ if (err ) {
512
+ dev_err (mlxsw_hwmon -> bus_info -> dev , "Failed to read module index %d\n" ,
513
+ i );
514
+ return err ;
515
+ }
516
+ width = mlxsw_reg_pmlp_width_get (pmlp_pl );
517
+ if (!width )
518
+ continue ;
519
+ mlxsw_hwmon_attr_add (mlxsw_hwmon ,
520
+ MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE , index ,
521
+ index );
522
+ mlxsw_hwmon_attr_add (mlxsw_hwmon ,
523
+ MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_FAULT ,
524
+ index , index );
525
+ mlxsw_hwmon_attr_add (mlxsw_hwmon ,
526
+ MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_CRIT ,
527
+ index , index );
528
+ mlxsw_hwmon_attr_add (mlxsw_hwmon ,
529
+ MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG ,
530
+ index , index );
531
+ index ++ ;
532
+ }
533
+
534
+ return 0 ;
535
+ }
536
+
330
537
int mlxsw_hwmon_init (struct mlxsw_core * mlxsw_core ,
331
538
const struct mlxsw_bus_info * mlxsw_bus_info ,
332
539
struct mlxsw_hwmon * * p_hwmon )
@@ -349,6 +556,10 @@ int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core,
349
556
if (err )
350
557
goto err_fans_init ;
351
558
559
+ err = mlxsw_hwmon_module_init (mlxsw_hwmon );
560
+ if (err )
561
+ goto err_temp_module_init ;
562
+
352
563
mlxsw_hwmon -> groups [0 ] = & mlxsw_hwmon -> group ;
353
564
mlxsw_hwmon -> group .attrs = mlxsw_hwmon -> attrs ;
354
565
@@ -365,6 +576,7 @@ int mlxsw_hwmon_init(struct mlxsw_core *mlxsw_core,
365
576
return 0 ;
366
577
367
578
err_hwmon_register :
579
+ err_temp_module_init :
368
580
err_fans_init :
369
581
err_temp_init :
370
582
kfree (mlxsw_hwmon );
0 commit comments