diff options
| author | Zhao Yakui <yakui.zhao@intel.com> | 2007-11-29 03:22:43 -0500 |
|---|---|---|
| committer | Len Brown <len.brown@intel.com> | 2007-12-01 23:27:15 -0500 |
| commit | 357dc4c3f13cb5c1e3b40a09cbe6ff1b0df2c7c3 (patch) | |
| tree | 794d39137bae2073423f93b3b14717824138290c | |
| parent | f79f06ab9f86d7203006d2ec8992ac80df36a34e (diff) | |
ACPI: Delete the IRQ operation in throttling controll via PTC
The IRQ operation(enable/disable) should be avoided when throttling is
controlled via PTC method. It is replaced by the migration of task.
This fixes an oops on T61 -- a regression due to
f79f06ab9f86 b/c FixedHW support tried to read remote MSR with interrupts disabled.
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
| -rw-r--r-- | drivers/acpi/processor_throttling.c | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index c26c61fb36c3..6742d7bc4777 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
| 30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
| 31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
| 32 | #include <linux/sched.h> | ||
| 32 | #include <linux/cpufreq.h> | 33 | #include <linux/cpufreq.h> |
| 33 | #include <linux/proc_fs.h> | 34 | #include <linux/proc_fs.h> |
| 34 | #include <linux/seq_file.h> | 35 | #include <linux/seq_file.h> |
| @@ -413,7 +414,7 @@ static int acpi_throttling_rdmsr(struct acpi_processor *pr, | |||
| 413 | } else { | 414 | } else { |
| 414 | msr_low = 0; | 415 | msr_low = 0; |
| 415 | msr_high = 0; | 416 | msr_high = 0; |
| 416 | rdmsr_on_cpu(cpu, MSR_IA32_THERM_CONTROL, | 417 | rdmsr_safe(MSR_IA32_THERM_CONTROL, |
| 417 | (u32 *)&msr_low , (u32 *) &msr_high); | 418 | (u32 *)&msr_low , (u32 *) &msr_high); |
| 418 | msr = (msr_high << 32) | msr_low; | 419 | msr = (msr_high << 32) | msr_low; |
| 419 | *value = (acpi_integer) msr; | 420 | *value = (acpi_integer) msr; |
| @@ -438,7 +439,7 @@ static int acpi_throttling_wrmsr(struct acpi_processor *pr, acpi_integer value) | |||
| 438 | "HARDWARE addr space,NOT supported yet\n"); | 439 | "HARDWARE addr space,NOT supported yet\n"); |
| 439 | } else { | 440 | } else { |
| 440 | msr = value; | 441 | msr = value; |
| 441 | wrmsr_on_cpu(cpu, MSR_IA32_THERM_CONTROL, | 442 | wrmsr_safe(MSR_IA32_THERM_CONTROL, |
| 442 | msr & 0xffffffff, msr >> 32); | 443 | msr & 0xffffffff, msr >> 32); |
| 443 | ret = 0; | 444 | ret = 0; |
| 444 | } | 445 | } |
| @@ -572,21 +573,32 @@ static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr) | |||
| 572 | return -ENODEV; | 573 | return -ENODEV; |
| 573 | 574 | ||
| 574 | pr->throttling.state = 0; | 575 | pr->throttling.state = 0; |
| 575 | local_irq_disable(); | 576 | |
| 576 | value = 0; | 577 | value = 0; |
| 577 | ret = acpi_read_throttling_status(pr, &value); | 578 | ret = acpi_read_throttling_status(pr, &value); |
| 578 | if (ret >= 0) { | 579 | if (ret >= 0) { |
| 579 | state = acpi_get_throttling_state(pr, value); | 580 | state = acpi_get_throttling_state(pr, value); |
| 580 | pr->throttling.state = state; | 581 | pr->throttling.state = state; |
| 581 | } | 582 | } |
| 582 | local_irq_enable(); | ||
| 583 | 583 | ||
| 584 | return 0; | 584 | return 0; |
| 585 | } | 585 | } |
| 586 | 586 | ||
| 587 | static int acpi_processor_get_throttling(struct acpi_processor *pr) | 587 | static int acpi_processor_get_throttling(struct acpi_processor *pr) |
| 588 | { | 588 | { |
| 589 | return pr->throttling.acpi_processor_get_throttling(pr); | 589 | cpumask_t saved_mask; |
| 590 | int ret; | ||
| 591 | |||
| 592 | /* | ||
| 593 | * Migrate task to the cpu pointed by pr. | ||
| 594 | */ | ||
| 595 | saved_mask = current->cpus_allowed; | ||
| 596 | set_cpus_allowed(current, cpumask_of_cpu(pr->id)); | ||
| 597 | ret = pr->throttling.acpi_processor_get_throttling(pr); | ||
| 598 | /* restore the previous state */ | ||
| 599 | set_cpus_allowed(current, saved_mask); | ||
| 600 | |||
| 601 | return ret; | ||
| 590 | } | 602 | } |
| 591 | 603 | ||
| 592 | static int acpi_processor_get_fadt_info(struct acpi_processor *pr) | 604 | static int acpi_processor_get_fadt_info(struct acpi_processor *pr) |
| @@ -717,21 +729,29 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr, | |||
| 717 | if (state < pr->throttling_platform_limit) | 729 | if (state < pr->throttling_platform_limit) |
| 718 | return -EPERM; | 730 | return -EPERM; |
| 719 | 731 | ||
| 720 | local_irq_disable(); | ||
| 721 | value = 0; | 732 | value = 0; |
| 722 | ret = acpi_get_throttling_value(pr, state, &value); | 733 | ret = acpi_get_throttling_value(pr, state, &value); |
| 723 | if (ret >= 0) { | 734 | if (ret >= 0) { |
| 724 | acpi_write_throttling_state(pr, value); | 735 | acpi_write_throttling_state(pr, value); |
| 725 | pr->throttling.state = state; | 736 | pr->throttling.state = state; |
| 726 | } | 737 | } |
| 727 | local_irq_enable(); | ||
| 728 | 738 | ||
| 729 | return 0; | 739 | return 0; |
| 730 | } | 740 | } |
| 731 | 741 | ||
| 732 | int acpi_processor_set_throttling(struct acpi_processor *pr, int state) | 742 | int acpi_processor_set_throttling(struct acpi_processor *pr, int state) |
| 733 | { | 743 | { |
| 734 | return pr->throttling.acpi_processor_set_throttling(pr, state); | 744 | cpumask_t saved_mask; |
| 745 | int ret; | ||
| 746 | /* | ||
| 747 | * Migrate task to the cpu pointed by pr. | ||
| 748 | */ | ||
| 749 | saved_mask = current->cpus_allowed; | ||
| 750 | set_cpus_allowed(current, cpumask_of_cpu(pr->id)); | ||
| 751 | ret = pr->throttling.acpi_processor_set_throttling(pr, state); | ||
| 752 | /* restore the previous state */ | ||
| 753 | set_cpus_allowed(current, saved_mask); | ||
| 754 | return ret; | ||
| 735 | } | 755 | } |
| 736 | 756 | ||
| 737 | int acpi_processor_get_throttling_info(struct acpi_processor *pr) | 757 | int acpi_processor_get_throttling_info(struct acpi_processor *pr) |
