diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-22 19:05:26 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-22 19:05:26 -0700 |
commit | a582e5f59c7583a38af19ceaabcbc50b3c5339bb (patch) | |
tree | cf8c2230a4a7f2c56cbd9af29f6bd2b94fb9febd /drivers | |
parent | b7371e31257677a71e19c885ff6796480464f60d (diff) | |
parent | ace120dcf23b3bbba00d797a898481997381052f (diff) | |
download | linux-a582e5f59c7583a38af19ceaabcbc50b3c5339bb.tar.bz2 |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux
Pull thermal management fixes from Zhang Rui:
"These are fixes collected over the last week, they fixes several
problems caused by the x86_pkg_temp_thermal introduced in 3.11-rc1.
Specifics:
- the x86_pkg_temp_thermal driver causes crash on systems with no
package MSR support as there is a bug in the logic to check
presence of DTHERM and PTS feature together. Added a change so
that when there is no PTS support, module doesn't get loaded.
- fix krealloc() misuse in pkg_temp_thermal_device_add().
If krealloc() returns NULL, it doesn't free the original. Thus if
we want to exit because of the krealloc() failure, we must make
sure the original one is freed.
- The error code path of the x86 package temperature thermal driver's
initialization routine makes an unbalanced call to
get_online_cpus(), which causes subsequent CPU offline operations,
and consequently system suspend, to permanently block in
cpu_hotplug_begin() on systems where get_core_online() returns an
error code.
Remove the extra get_online_cpus() to fix the problem"
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux:
Thermal: Fix lockup of cpu_down()
Thermal: x86_pkg_temp: Limit number of pkg temp zones
Thermal: x86_pkg_temp: fix krealloc() misuse in in pkg_temp_thermal_device_add()
Thermal: x86 package temp thermal crash
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/thermal/x86_pkg_temp_thermal.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c index 5de56f671a9d..f36950e4134f 100644 --- a/drivers/thermal/x86_pkg_temp_thermal.c +++ b/drivers/thermal/x86_pkg_temp_thermal.c @@ -54,6 +54,8 @@ MODULE_PARM_DESC(notify_delay_ms, * is some wrong values returned by cpuid for number of thresholds. */ #define MAX_NUMBER_OF_TRIPS 2 +/* Limit number of package temp zones */ +#define MAX_PKG_TEMP_ZONE_IDS 256 struct phy_dev_entry { struct list_head list; @@ -394,12 +396,16 @@ static int pkg_temp_thermal_device_add(unsigned int cpu) char buffer[30]; int thres_count; u32 eax, ebx, ecx, edx; + u8 *temp; cpuid(6, &eax, &ebx, &ecx, &edx); thres_count = ebx & 0x07; if (!thres_count) return -ENODEV; + if (topology_physical_package_id(cpu) > MAX_PKG_TEMP_ZONE_IDS) + return -ENODEV; + thres_count = clamp_val(thres_count, 0, MAX_NUMBER_OF_TRIPS); err = get_tj_max(cpu, &tj_max); @@ -417,13 +423,14 @@ static int pkg_temp_thermal_device_add(unsigned int cpu) spin_lock(&pkg_work_lock); if (topology_physical_package_id(cpu) > max_phy_id) max_phy_id = topology_physical_package_id(cpu); - pkg_work_scheduled = krealloc(pkg_work_scheduled, - (max_phy_id+1) * sizeof(u8), GFP_ATOMIC); - if (!pkg_work_scheduled) { + temp = krealloc(pkg_work_scheduled, + (max_phy_id+1) * sizeof(u8), GFP_ATOMIC); + if (!temp) { spin_unlock(&pkg_work_lock); err = -ENOMEM; goto err_ret_free; } + pkg_work_scheduled = temp; pkg_work_scheduled[topology_physical_package_id(cpu)] = 0; spin_unlock(&pkg_work_lock); @@ -511,7 +518,7 @@ static int get_core_online(unsigned int cpu) /* Check if there is already an instance for this package */ if (!phdev) { - if (!cpu_has(c, X86_FEATURE_DTHERM) && + if (!cpu_has(c, X86_FEATURE_DTHERM) || !cpu_has(c, X86_FEATURE_PTS)) return -ENODEV; if (pkg_temp_thermal_device_add(cpu)) @@ -562,7 +569,7 @@ static struct notifier_block pkg_temp_thermal_notifier __refdata = { }; static const struct x86_cpu_id __initconst pkg_temp_thermal_ids[] = { - { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_DTHERM }, + { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_PTS }, {} }; MODULE_DEVICE_TABLE(x86cpu, pkg_temp_thermal_ids); @@ -592,7 +599,6 @@ static int __init pkg_temp_thermal_init(void) return 0; err_ret: - get_online_cpus(); for_each_online_cpu(i) put_core_offline(i); put_online_cpus(); |