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

thermal: hwmon: Make the check for critical temp valid consistent

On 05/21/2014 04:22 PM, Aaron Lu wrote:
> On 05/21/2014 01:57 PM, Kui Zhang wrote:
>> Hello,
>>
>> I get following error when rmmod thermal.
>>
>> rmmod thermal
>> Killed

While dealing with this problem, I found another problem that also
results in a kernel crash on thermal module removal:

From: Aaron Lu <aaron.lu@intel.com>
Date: Wed, 21 May 2014 16:05:38 +0800
Subject: [PATCH] thermal: hwmon: Make the check for critical temp valid consistent

We used the tz->ops->get_crit_temp && !tz->ops->get_crit_temp(tz, temp)
to decide if we need to create the temp_crit attribute file but we just
check if tz->ops->get_crit_temp exists to decide if we need to remove
that attribute file. Some ACPI thermal zone doesn't have a valid critical
trip point and that would result in removing a non-existent device file
on thermal module unload.

Cc: All applicable <stable@vger.kernel.org>
Signed-off-by: Aaron Lu <aaron.lu@intel.com>
Signed-off-by: Zhang Rui <rui.zhang@intel.com>

authored by

Aaron Lu and committed by
Zhang Rui
e8db5d67 f14d1c24

+18 -15
+18 -15
drivers/thermal/thermal_hwmon.c
··· 140 140 return NULL; 141 141 } 142 142 143 + static bool thermal_zone_crit_temp_valid(struct thermal_zone_device *tz) 144 + { 145 + unsigned long temp; 146 + return tz->ops->get_crit_temp && !tz->ops->get_crit_temp(tz, &temp); 147 + } 148 + 143 149 int thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) 144 150 { 145 151 struct thermal_hwmon_device *hwmon; ··· 195 189 if (result) 196 190 goto free_temp_mem; 197 191 198 - if (tz->ops->get_crit_temp) { 199 - unsigned long temperature; 200 - if (!tz->ops->get_crit_temp(tz, &temperature)) { 201 - snprintf(temp->temp_crit.name, 202 - sizeof(temp->temp_crit.name), 192 + if (thermal_zone_crit_temp_valid(tz)) { 193 + snprintf(temp->temp_crit.name, 194 + sizeof(temp->temp_crit.name), 203 195 "temp%d_crit", hwmon->count); 204 - temp->temp_crit.attr.attr.name = temp->temp_crit.name; 205 - temp->temp_crit.attr.attr.mode = 0444; 206 - temp->temp_crit.attr.show = temp_crit_show; 207 - sysfs_attr_init(&temp->temp_crit.attr.attr); 208 - result = device_create_file(hwmon->device, 209 - &temp->temp_crit.attr); 210 - if (result) 211 - goto unregister_input; 212 - } 196 + temp->temp_crit.attr.attr.name = temp->temp_crit.name; 197 + temp->temp_crit.attr.attr.mode = 0444; 198 + temp->temp_crit.attr.show = temp_crit_show; 199 + sysfs_attr_init(&temp->temp_crit.attr.attr); 200 + result = device_create_file(hwmon->device, 201 + &temp->temp_crit.attr); 202 + if (result) 203 + goto unregister_input; 213 204 } 214 205 215 206 mutex_lock(&thermal_hwmon_list_lock); ··· 253 250 } 254 251 255 252 device_remove_file(hwmon->device, &temp->temp_input.attr); 256 - if (tz->ops->get_crit_temp) 253 + if (thermal_zone_crit_temp_valid(tz)) 257 254 device_remove_file(hwmon->device, &temp->temp_crit.attr); 258 255 259 256 mutex_lock(&thermal_hwmon_list_lock);