Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Thermal: Ignore invalid trip points

In some cases, platform thermal driver may report invalid trip points,
thermal core should not take any action for these trip points.

This fixed a regression that bogus trip point starts to screw up thermal
control on some Lenovo laptops, after
commit bb431ba26c5cd0a17c941ca6c3a195a3a6d5d461
Author: Zhang Rui <rui.zhang@intel.com>
Date: Fri Oct 30 16:31:47 2015 +0800

Thermal: initialize thermal zone device correctly

After thermal zone device registered, as we have not read any
temperature before, thus tz->temperature should not be 0,
which actually means 0C, and thermal trend is not available.
In this case, we need specially handling for the first
thermal_zone_device_update().

Both thermal core framework and step_wise governor is
enhanced to handle this. And since the step_wise governor
is the only one that uses trends, so it's the only thermal
governor that needs to be updated.

Tested-by: Manuel Krause <manuelkrause@netscape.net>
Tested-by: szegad <szegadlo@poczta.onet.pl>
Tested-by: prash <prash.n.rao@gmail.com>
Tested-by: amish <ammdispose-arch@yahoo.com>
Tested-by: Matthias <morpheusxyz123@yahoo.de>
Reviewed-by: Javi Merino <javi.merino@arm.com>
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Signed-off-by: Chen Yu <yu.c.chen@intel.com>

CC: <stable@vger.kernel.org> #3.18+
Link: https://bugzilla.redhat.com/show_bug.cgi?id=1317190
Link: https://bugzilla.kernel.org/show_bug.cgi?id=114551
Signed-off-by: Zhang Rui <rui.zhang@intel.com>

Zhang Rui 81ad4276 b82ddd48

+14 -1
+12 -1
drivers/thermal/thermal_core.c
··· 454 454 { 455 455 enum thermal_trip_type type; 456 456 457 + /* Ignore disabled trip points */ 458 + if (test_bit(trip, &tz->trips_disabled)) 459 + return; 460 + 457 461 tz->ops->get_trip_type(tz, trip, &type); 458 462 459 463 if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT) ··· 1804 1800 { 1805 1801 struct thermal_zone_device *tz; 1806 1802 enum thermal_trip_type trip_type; 1803 + int trip_temp; 1807 1804 int result; 1808 1805 int count; 1809 1806 int passive = 0; ··· 1876 1871 goto unregister; 1877 1872 1878 1873 for (count = 0; count < trips; count++) { 1879 - tz->ops->get_trip_type(tz, count, &trip_type); 1874 + if (tz->ops->get_trip_type(tz, count, &trip_type)) 1875 + set_bit(count, &tz->trips_disabled); 1880 1876 if (trip_type == THERMAL_TRIP_PASSIVE) 1881 1877 passive = 1; 1878 + if (tz->ops->get_trip_temp(tz, count, &trip_temp)) 1879 + set_bit(count, &tz->trips_disabled); 1880 + /* Check for bogus trip points */ 1881 + if (trip_temp == 0) 1882 + set_bit(count, &tz->trips_disabled); 1882 1883 } 1883 1884 1884 1885 if (!passive) {
+2
include/linux/thermal.h
··· 156 156 * @trip_hyst_attrs: attributes for trip points for sysfs: trip hysteresis 157 157 * @devdata: private pointer for device private data 158 158 * @trips: number of trip points the thermal zone supports 159 + * @trips_disabled; bitmap for disabled trips 159 160 * @passive_delay: number of milliseconds to wait between polls when 160 161 * performing passive cooling. 161 162 * @polling_delay: number of milliseconds to wait between polls when ··· 192 191 struct thermal_attr *trip_hyst_attrs; 193 192 void *devdata; 194 193 int trips; 194 + unsigned long trips_disabled; /* bitmap for disabled trips */ 195 195 int passive_delay; 196 196 int polling_delay; 197 197 int temperature;