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(); |
