diff options
Diffstat (limited to 'drivers/acpi/processor_idle.c')
| -rw-r--r-- | drivers/acpi/processor_idle.c | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index f7ca8c55956b..72069ba5f1ed 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
| @@ -202,21 +202,44 @@ static void acpi_state_timer_broadcast(struct acpi_processor *pr, | |||
| 202 | * Suspend / resume control | 202 | * Suspend / resume control |
| 203 | */ | 203 | */ |
| 204 | static int acpi_idle_suspend; | 204 | static int acpi_idle_suspend; |
| 205 | static u32 saved_bm_rld; | ||
| 206 | |||
| 207 | static void acpi_idle_bm_rld_save(void) | ||
| 208 | { | ||
| 209 | acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_RLD, &saved_bm_rld); | ||
| 210 | } | ||
| 211 | static void acpi_idle_bm_rld_restore(void) | ||
| 212 | { | ||
| 213 | u32 resumed_bm_rld; | ||
| 214 | |||
| 215 | acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_RLD, &resumed_bm_rld); | ||
| 216 | |||
| 217 | if (resumed_bm_rld != saved_bm_rld) | ||
| 218 | acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, saved_bm_rld); | ||
| 219 | } | ||
| 205 | 220 | ||
| 206 | int acpi_processor_suspend(struct acpi_device * device, pm_message_t state) | 221 | int acpi_processor_suspend(struct acpi_device * device, pm_message_t state) |
| 207 | { | 222 | { |
| 223 | if (acpi_idle_suspend == 1) | ||
| 224 | return 0; | ||
| 225 | |||
| 226 | acpi_idle_bm_rld_save(); | ||
| 208 | acpi_idle_suspend = 1; | 227 | acpi_idle_suspend = 1; |
| 209 | return 0; | 228 | return 0; |
| 210 | } | 229 | } |
| 211 | 230 | ||
| 212 | int acpi_processor_resume(struct acpi_device * device) | 231 | int acpi_processor_resume(struct acpi_device * device) |
| 213 | { | 232 | { |
| 233 | if (acpi_idle_suspend == 0) | ||
| 234 | return 0; | ||
| 235 | |||
| 236 | acpi_idle_bm_rld_restore(); | ||
| 214 | acpi_idle_suspend = 0; | 237 | acpi_idle_suspend = 0; |
| 215 | return 0; | 238 | return 0; |
| 216 | } | 239 | } |
| 217 | 240 | ||
| 218 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) | 241 | #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) |
| 219 | static int tsc_halts_in_c(int state) | 242 | static void tsc_check_state(int state) |
| 220 | { | 243 | { |
| 221 | switch (boot_cpu_data.x86_vendor) { | 244 | switch (boot_cpu_data.x86_vendor) { |
| 222 | case X86_VENDOR_AMD: | 245 | case X86_VENDOR_AMD: |
| @@ -226,13 +249,17 @@ static int tsc_halts_in_c(int state) | |||
| 226 | * C/P/S0/S1 states when this bit is set. | 249 | * C/P/S0/S1 states when this bit is set. |
| 227 | */ | 250 | */ |
| 228 | if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) | 251 | if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) |
| 229 | return 0; | 252 | return; |
| 230 | 253 | ||
| 231 | /*FALL THROUGH*/ | 254 | /*FALL THROUGH*/ |
| 232 | default: | 255 | default: |
| 233 | return state > ACPI_STATE_C1; | 256 | /* TSC could halt in idle, so notify users */ |
| 257 | if (state > ACPI_STATE_C1) | ||
| 258 | mark_tsc_unstable("TSC halts in idle"); | ||
| 234 | } | 259 | } |
| 235 | } | 260 | } |
| 261 | #else | ||
| 262 | static void tsc_check_state(int state) { return; } | ||
| 236 | #endif | 263 | #endif |
| 237 | 264 | ||
| 238 | static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) | 265 | static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) |
| @@ -578,14 +605,9 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) | |||
| 578 | 605 | ||
| 579 | pr->power.timer_broadcast_on_state = INT_MAX; | 606 | pr->power.timer_broadcast_on_state = INT_MAX; |
| 580 | 607 | ||
| 581 | for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) { | 608 | for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) { |
| 582 | struct acpi_processor_cx *cx = &pr->power.states[i]; | 609 | struct acpi_processor_cx *cx = &pr->power.states[i]; |
| 583 | 610 | ||
| 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) { | 611 | switch (cx->type) { |
| 590 | case ACPI_STATE_C1: | 612 | case ACPI_STATE_C1: |
| 591 | cx->valid = 1; | 613 | cx->valid = 1; |
| @@ -603,6 +625,8 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) | |||
| 603 | acpi_timer_check_state(i, pr, cx); | 625 | acpi_timer_check_state(i, pr, cx); |
| 604 | break; | 626 | break; |
| 605 | } | 627 | } |
| 628 | if (cx->valid) | ||
| 629 | tsc_check_state(cx->type); | ||
| 606 | 630 | ||
| 607 | if (cx->valid) | 631 | if (cx->valid) |
| 608 | working++; | 632 | working++; |
