@@ -272,6 +272,44 @@ static int __init thermal_register_governors(void)
272
272
return ret ;
273
273
}
274
274
275
+ static int __thermal_zone_device_set_mode (struct thermal_zone_device * tz ,
276
+ enum thermal_device_mode mode )
277
+ {
278
+ if (tz -> ops .change_mode ) {
279
+ int ret ;
280
+
281
+ ret = tz -> ops .change_mode (tz , mode );
282
+ if (ret )
283
+ return ret ;
284
+ }
285
+
286
+ tz -> mode = mode ;
287
+
288
+ return 0 ;
289
+ }
290
+
291
+ static void thermal_zone_broken_disable (struct thermal_zone_device * tz )
292
+ {
293
+ struct thermal_trip_desc * td ;
294
+
295
+ dev_err (& tz -> device , "Unable to get temperature, disabling!\n" );
296
+ /*
297
+ * This function only runs for enabled thermal zones, so no need to
298
+ * check for the current mode.
299
+ */
300
+ __thermal_zone_device_set_mode (tz , THERMAL_DEVICE_DISABLED );
301
+ thermal_notify_tz_disable (tz );
302
+
303
+ for_each_trip_desc (tz , td ) {
304
+ if (td -> trip .type == THERMAL_TRIP_CRITICAL &&
305
+ td -> trip .temperature > THERMAL_TEMP_INVALID ) {
306
+ dev_crit (& tz -> device ,
307
+ "Disabled thermal zone with critical trip point\n" );
308
+ return ;
309
+ }
310
+ }
311
+ }
312
+
275
313
/*
276
314
* Zone update section: main control loop applied to each zone while monitoring
277
315
* in polling mode. The monitoring is done using a workqueue.
@@ -292,6 +330,34 @@ static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
292
330
cancel_delayed_work (& tz -> poll_queue );
293
331
}
294
332
333
+ static void thermal_zone_recheck (struct thermal_zone_device * tz , int error )
334
+ {
335
+ if (error == - EAGAIN ) {
336
+ thermal_zone_device_set_polling (tz , THERMAL_RECHECK_DELAY );
337
+ return ;
338
+ }
339
+
340
+ /*
341
+ * Print the message once to reduce log noise. It will be followed by
342
+ * another one if the temperature cannot be determined after multiple
343
+ * attempts.
344
+ */
345
+ if (tz -> recheck_delay_jiffies == THERMAL_RECHECK_DELAY )
346
+ dev_info (& tz -> device , "Temperature check failed (%d)\n" , error );
347
+
348
+ thermal_zone_device_set_polling (tz , tz -> recheck_delay_jiffies );
349
+
350
+ tz -> recheck_delay_jiffies += max (tz -> recheck_delay_jiffies >> 1 , 1ULL );
351
+ if (tz -> recheck_delay_jiffies > THERMAL_MAX_RECHECK_DELAY ) {
352
+ thermal_zone_broken_disable (tz );
353
+ /*
354
+ * Restore the original recheck delay value to allow the thermal
355
+ * zone to try to recover when it is reenabled by user space.
356
+ */
357
+ tz -> recheck_delay_jiffies = THERMAL_RECHECK_DELAY ;
358
+ }
359
+ }
360
+
295
361
static void monitor_thermal_zone (struct thermal_zone_device * tz )
296
362
{
297
363
if (tz -> mode != THERMAL_DEVICE_ENABLED )
@@ -491,10 +557,7 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz,
491
557
492
558
ret = __thermal_zone_get_temp (tz , & temp );
493
559
if (ret ) {
494
- if (ret != - EAGAIN )
495
- dev_info (& tz -> device , "Temperature check failed (%d)\n" , ret );
496
-
497
- thermal_zone_device_set_polling (tz , msecs_to_jiffies (THERMAL_RECHECK_DELAY_MS ));
560
+ thermal_zone_recheck (tz , ret );
498
561
return ;
499
562
} else if (temp <= THERMAL_TEMP_INVALID ) {
500
563
/*
@@ -506,6 +569,8 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz,
506
569
goto monitor ;
507
570
}
508
571
572
+ tz -> recheck_delay_jiffies = THERMAL_RECHECK_DELAY ;
573
+
509
574
tz -> last_temperature = tz -> temperature ;
510
575
tz -> temperature = temp ;
511
576
@@ -540,22 +605,23 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz,
540
605
static int thermal_zone_device_set_mode (struct thermal_zone_device * tz ,
541
606
enum thermal_device_mode mode )
542
607
{
543
- int ret = 0 ;
608
+ int ret ;
544
609
545
610
mutex_lock (& tz -> lock );
546
611
547
612
/* do nothing if mode isn't changing */
548
613
if (mode == tz -> mode ) {
549
614
mutex_unlock (& tz -> lock );
550
615
551
- return ret ;
616
+ return 0 ;
552
617
}
553
618
554
- if (tz -> ops .change_mode )
555
- ret = tz -> ops .change_mode (tz , mode );
619
+ ret = __thermal_zone_device_set_mode (tz , mode );
620
+ if (ret ) {
621
+ mutex_unlock (& tz -> lock );
556
622
557
- if (! ret )
558
- tz -> mode = mode ;
623
+ return ret ;
624
+ }
559
625
560
626
__thermal_zone_device_update (tz , THERMAL_EVENT_UNSPECIFIED );
561
627
@@ -566,7 +632,7 @@ static int thermal_zone_device_set_mode(struct thermal_zone_device *tz,
566
632
else
567
633
thermal_notify_tz_disable (tz );
568
634
569
- return ret ;
635
+ return 0 ;
570
636
}
571
637
572
638
int thermal_zone_device_enable (struct thermal_zone_device * tz )
@@ -1445,6 +1511,7 @@ thermal_zone_device_register_with_trips(const char *type,
1445
1511
1446
1512
thermal_set_delay_jiffies (& tz -> passive_delay_jiffies , passive_delay );
1447
1513
thermal_set_delay_jiffies (& tz -> polling_delay_jiffies , polling_delay );
1514
+ tz -> recheck_delay_jiffies = THERMAL_RECHECK_DELAY ;
1448
1515
1449
1516
/* sys I/F */
1450
1517
/* Add nodes that are always present via .groups */
0 commit comments