diff options
Diffstat (limited to 'drivers/acpi/processor_idle.c')
| -rw-r--r-- | drivers/acpi/processor_idle.c | 50 |
1 files changed, 40 insertions, 10 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index f7ca8c55956b..10a2d913635a 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
| @@ -148,6 +148,9 @@ static void acpi_timer_check_state(int state, struct acpi_processor *pr, | |||
| 148 | if (cpu_has(&cpu_data(pr->id), X86_FEATURE_ARAT)) | 148 | if (cpu_has(&cpu_data(pr->id), X86_FEATURE_ARAT)) |
| 149 | return; | 149 | return; |
| 150 | 150 | ||
| 151 | if (boot_cpu_has(X86_FEATURE_AMDC1E)) | ||
| 152 | type = ACPI_STATE_C1; | ||
| 153 | |||
| 151 | /* | 154 | /* |
| 152 | * Check, if one of the previous states already marked the lapic | 155 | * Check, if one of the previous states already marked the lapic |
| 153 | * unstable | 156 | * unstable |
| @@ -202,21 +205,44 @@ static void acpi_state_timer_broadcast(struct acpi_processor *pr, | |||
| 202 | * Suspend / resume control | 205 | * Suspend / resume control |
| 203 | */ | 206 | */ |
| 204 | static int acpi_idle_suspend; | 207 | static int acpi_idle_suspend; |
| 208 | static u32 saved_bm_rld; | ||
| 209 | |||
| 210 | static void acpi_idle_bm_rld_save(void) | ||
| 211 | { | ||
| 212 | acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_RLD, &saved_bm_rld); | ||
| 213 | } | ||
| 214 | static void acpi_idle_bm_rld_restore(void) | ||
| 215 | { | ||
| 216 | u32 resumed_bm_rld; | ||
| 217 | |||
| 218 | acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_RLD, &resumed_bm_rld); | ||
| 219 | |||
| 220 | if (resumed_bm_rld != saved_bm_rld) | ||
| 221 | acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, saved_bm_rld); | ||
| 222 | } | ||
| 205 | 223 | ||
| 206 | int acpi_processor_suspend(struct acpi_device * device, pm_message_t state) | 224 | int acpi_processor_suspend(struct acpi_device * device, pm_message_t state) |
| 207 | { | 225 | { |
| 226 | if (acpi_idle_suspend == 1) | ||
| 227 | return 0; | ||
| 228 | |||
| 229 | acpi_idle_bm_rld_save(); | ||
| 208 | acpi_idle_suspend = 1; | 230 | acpi_idle_suspend = 1; |
| 209 | return 0; | 231 | return 0; |
| 210 | } | 232 | } |
| 211 | 233 | ||
| 212 | int acpi_processor_resume(struct acpi_device * device) | 234 | int acpi_processor_resume(struct acpi_device * device) |
| 213 | { | 235 | { |
| 236 | if (acpi_idle_suspend == 0) | ||
| 237 | return 0; | ||
| 238 | |||
| 239 | acpi_idle_bm_rld_restore(); | ||
| 214 | acpi_idle_suspend = 0; | 240 | acpi_idle_suspend = 0; |
| 215 | return 0; | 241 | return 0; |
| 216 | } | 242 | } |
| 217 | 243 | ||
| 218 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) | 244 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) |
| 219 | static int tsc_halts_in_c(int state) | 245 | static void tsc_check_state(int state) |
| 220 | { | 246 | { |
| 221 | switch (boot_cpu_data.x86_vendor) { | 247 | switch (boot_cpu_data.x86_vendor) { |
| 222 | case X86_VENDOR_AMD: | 248 | case X86_VENDOR_AMD: |
| @@ -226,13 +252,17 @@ static int tsc_halts_in_c(int state) | |||
| 226 | * C/P/S0/S1 states when this bit is set. | 252 | * C/P/S0/S1 states when this bit is set. |
| 227 | */ | 253 | */ |
| 228 | if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) | 254 | if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) |
| 229 | return 0; | 255 | return; |
| 230 | 256 | ||
| 231 | /*FALL THROUGH*/ | 257 | /*FALL THROUGH*/ |
| 232 | default: | 258 | default: |
| 233 | return state > ACPI_STATE_C1; | 259 | /* TSC could halt in idle, so notify users */ |
| 260 | if (state > ACPI_STATE_C1) | ||
| 261 | mark_tsc_unstable("TSC halts in idle"); | ||
| 234 | } | 262 | } |
| 235 | } | 263 | } |
| 264 | #else | ||
| 265 | static void tsc_check_state(int state) { return; } | ||
| 236 | #endif | 266 | #endif |
| 237 | 267 | ||
| 238 | static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) | 268 | static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) |
| @@ -578,17 +608,13 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) | |||
| 578 | 608 | ||
| 579 | pr->power.timer_broadcast_on_state = INT_MAX; | 609 | pr->power.timer_broadcast_on_state = INT_MAX; |
| 580 | 610 | ||
| 581 | for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) { | 611 | for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) { |
| 582 | struct acpi_processor_cx *cx = &pr->power.states[i]; | 612 | struct acpi_processor_cx *cx = &pr->power.states[i]; |
| 583 | 613 | ||
| 584 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) | ||
| 585 | /* TSC could halt in idle, so notify users */ | ||
| 586 | if (tsc_halts_in_c(cx->type)) | ||
| 587 | mark_tsc_unstable("TSC halts in idle");; | ||
| 588 | #endif | ||
| 589 | switch (cx->type) { | 614 | switch (cx->type) { |
| 590 | case ACPI_STATE_C1: | 615 | case ACPI_STATE_C1: |
| 591 | cx->valid = 1; | 616 | cx->valid = 1; |
| 617 | acpi_timer_check_state(i, pr, cx); | ||
| 592 | break; | 618 | break; |
| 593 | 619 | ||
| 594 | case ACPI_STATE_C2: | 620 | case ACPI_STATE_C2: |
| @@ -603,6 +629,8 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) | |||
| 603 | acpi_timer_check_state(i, pr, cx); | 629 | acpi_timer_check_state(i, pr, cx); |
| 604 | break; | 630 | break; |
| 605 | } | 631 | } |
| 632 | if (cx->valid) | ||
| 633 | tsc_check_state(cx->type); | ||
| 606 | 634 | ||
| 607 | if (cx->valid) | 635 | if (cx->valid) |
| 608 | working++; | 636 | working++; |
| @@ -806,11 +834,12 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, | |||
| 806 | 834 | ||
| 807 | /* Do not access any ACPI IO ports in suspend path */ | 835 | /* Do not access any ACPI IO ports in suspend path */ |
| 808 | if (acpi_idle_suspend) { | 836 | if (acpi_idle_suspend) { |
| 809 | acpi_safe_halt(); | ||
| 810 | local_irq_enable(); | 837 | local_irq_enable(); |
| 838 | cpu_relax(); | ||
| 811 | return 0; | 839 | return 0; |
| 812 | } | 840 | } |
| 813 | 841 | ||
| 842 | acpi_state_timer_broadcast(pr, cx, 1); | ||
| 814 | kt1 = ktime_get_real(); | 843 | kt1 = ktime_get_real(); |
| 815 | acpi_idle_do_entry(cx); | 844 | acpi_idle_do_entry(cx); |
| 816 | kt2 = ktime_get_real(); | 845 | kt2 = ktime_get_real(); |
| @@ -818,6 +847,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, | |||
| 818 | 847 | ||
| 819 | local_irq_enable(); | 848 | local_irq_enable(); |
| 820 | cx->usage++; | 849 | cx->usage++; |
| 850 | acpi_state_timer_broadcast(pr, cx, 0); | ||
| 821 | 851 | ||
| 822 | return idle_time; | 852 | return idle_time; |
| 823 | } | 853 | } |
