summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds2013-07-23 04:05:26 +0200
committerLinus Torvalds2013-07-23 04:05:26 +0200
commita582e5f59c7583a38af19ceaabcbc50b3c5339bb (patch)
treecf8c2230a4a7f2c56cbd9af29f6bd2b94fb9febd
parentMerge tag 'gpio-for-v3.11-2' of git://git.kernel.org/pub/scm/linux/kernel/git... (diff)
parentThermal: Fix lockup of cpu_down() (diff)
downloadkernel-qcow2-linux-a582e5f59c7583a38af19ceaabcbc50b3c5339bb.tar.gz
kernel-qcow2-linux-a582e5f59c7583a38af19ceaabcbc50b3c5339bb.tar.xz
kernel-qcow2-linux-a582e5f59c7583a38af19ceaabcbc50b3c5339bb.zip
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
-rw-r--r--drivers/thermal/x86_pkg_temp_thermal.c18
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();