diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-22 22:05:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-22 22:05:26 -0400 |
commit | a582e5f59c7583a38af19ceaabcbc50b3c5339bb (patch) | |
tree | cf8c2230a4a7f2c56cbd9af29f6bd2b94fb9febd | |
parent | b7371e31257677a71e19c885ff6796480464f60d (diff) | |
parent | ace120dcf23b3bbba00d797a898481997381052f (diff) |
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.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, | |||
54 | * is some wrong values returned by cpuid for number of thresholds. | 54 | * is some wrong values returned by cpuid for number of thresholds. |
55 | */ | 55 | */ |
56 | #define MAX_NUMBER_OF_TRIPS 2 | 56 | #define MAX_NUMBER_OF_TRIPS 2 |
57 | /* Limit number of package temp zones */ | ||
58 | #define MAX_PKG_TEMP_ZONE_IDS 256 | ||
57 | 59 | ||
58 | struct phy_dev_entry { | 60 | struct phy_dev_entry { |
59 | struct list_head list; | 61 | struct list_head list; |
@@ -394,12 +396,16 @@ static int pkg_temp_thermal_device_add(unsigned int cpu) | |||
394 | char buffer[30]; | 396 | char buffer[30]; |
395 | int thres_count; | 397 | int thres_count; |
396 | u32 eax, ebx, ecx, edx; | 398 | u32 eax, ebx, ecx, edx; |
399 | u8 *temp; | ||
397 | 400 | ||
398 | cpuid(6, &eax, &ebx, &ecx, &edx); | 401 | cpuid(6, &eax, &ebx, &ecx, &edx); |
399 | thres_count = ebx & 0x07; | 402 | thres_count = ebx & 0x07; |
400 | if (!thres_count) | 403 | if (!thres_count) |
401 | return -ENODEV; | 404 | return -ENODEV; |
402 | 405 | ||
406 | if (topology_physical_package_id(cpu) > MAX_PKG_TEMP_ZONE_IDS) | ||
407 | return -ENODEV; | ||
408 | |||
403 | thres_count = clamp_val(thres_count, 0, MAX_NUMBER_OF_TRIPS); | 409 | thres_count = clamp_val(thres_count, 0, MAX_NUMBER_OF_TRIPS); |
404 | 410 | ||
405 | err = get_tj_max(cpu, &tj_max); | 411 | err = get_tj_max(cpu, &tj_max); |
@@ -417,13 +423,14 @@ static int pkg_temp_thermal_device_add(unsigned int cpu) | |||
417 | spin_lock(&pkg_work_lock); | 423 | spin_lock(&pkg_work_lock); |
418 | if (topology_physical_package_id(cpu) > max_phy_id) | 424 | if (topology_physical_package_id(cpu) > max_phy_id) |
419 | max_phy_id = topology_physical_package_id(cpu); | 425 | max_phy_id = topology_physical_package_id(cpu); |
420 | pkg_work_scheduled = krealloc(pkg_work_scheduled, | 426 | temp = krealloc(pkg_work_scheduled, |
421 | (max_phy_id+1) * sizeof(u8), GFP_ATOMIC); | 427 | (max_phy_id+1) * sizeof(u8), GFP_ATOMIC); |
422 | if (!pkg_work_scheduled) { | 428 | if (!temp) { |
423 | spin_unlock(&pkg_work_lock); | 429 | spin_unlock(&pkg_work_lock); |
424 | err = -ENOMEM; | 430 | err = -ENOMEM; |
425 | goto err_ret_free; | 431 | goto err_ret_free; |
426 | } | 432 | } |
433 | pkg_work_scheduled = temp; | ||
427 | pkg_work_scheduled[topology_physical_package_id(cpu)] = 0; | 434 | pkg_work_scheduled[topology_physical_package_id(cpu)] = 0; |
428 | spin_unlock(&pkg_work_lock); | 435 | spin_unlock(&pkg_work_lock); |
429 | 436 | ||
@@ -511,7 +518,7 @@ static int get_core_online(unsigned int cpu) | |||
511 | 518 | ||
512 | /* Check if there is already an instance for this package */ | 519 | /* Check if there is already an instance for this package */ |
513 | if (!phdev) { | 520 | if (!phdev) { |
514 | if (!cpu_has(c, X86_FEATURE_DTHERM) && | 521 | if (!cpu_has(c, X86_FEATURE_DTHERM) || |
515 | !cpu_has(c, X86_FEATURE_PTS)) | 522 | !cpu_has(c, X86_FEATURE_PTS)) |
516 | return -ENODEV; | 523 | return -ENODEV; |
517 | if (pkg_temp_thermal_device_add(cpu)) | 524 | if (pkg_temp_thermal_device_add(cpu)) |
@@ -562,7 +569,7 @@ static struct notifier_block pkg_temp_thermal_notifier __refdata = { | |||
562 | }; | 569 | }; |
563 | 570 | ||
564 | static const struct x86_cpu_id __initconst pkg_temp_thermal_ids[] = { | 571 | static const struct x86_cpu_id __initconst pkg_temp_thermal_ids[] = { |
565 | { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_DTHERM }, | 572 | { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_PTS }, |
566 | {} | 573 | {} |
567 | }; | 574 | }; |
568 | MODULE_DEVICE_TABLE(x86cpu, pkg_temp_thermal_ids); | 575 | MODULE_DEVICE_TABLE(x86cpu, pkg_temp_thermal_ids); |
@@ -592,7 +599,6 @@ static int __init pkg_temp_thermal_init(void) | |||
592 | return 0; | 599 | return 0; |
593 | 600 | ||
594 | err_ret: | 601 | err_ret: |
595 | get_online_cpus(); | ||
596 | for_each_online_cpu(i) | 602 | for_each_online_cpu(i) |
597 | put_core_offline(i); | 603 | put_core_offline(i); |
598 | put_online_cpus(); | 604 | put_online_cpus(); |