diff options
Diffstat (limited to 'drivers/acpi/processor_idle.c')
-rw-r--r-- | drivers/acpi/processor_idle.c | 44 |
1 files changed, 36 insertions, 8 deletions
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index f3decb30223f..9837c9c4f009 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -224,6 +224,7 @@ static void lapic_timer_state_broadcast(struct acpi_processor *pr, | |||
224 | /* | 224 | /* |
225 | * Suspend / resume control | 225 | * Suspend / resume control |
226 | */ | 226 | */ |
227 | static int acpi_idle_suspend; | ||
227 | static u32 saved_bm_rld; | 228 | static u32 saved_bm_rld; |
228 | 229 | ||
229 | static void acpi_idle_bm_rld_save(void) | 230 | static void acpi_idle_bm_rld_save(void) |
@@ -242,13 +243,21 @@ static void acpi_idle_bm_rld_restore(void) | |||
242 | 243 | ||
243 | int acpi_processor_suspend(struct acpi_device * device, pm_message_t state) | 244 | int acpi_processor_suspend(struct acpi_device * device, pm_message_t state) |
244 | { | 245 | { |
246 | if (acpi_idle_suspend == 1) | ||
247 | return 0; | ||
248 | |||
245 | acpi_idle_bm_rld_save(); | 249 | acpi_idle_bm_rld_save(); |
250 | acpi_idle_suspend = 1; | ||
246 | return 0; | 251 | return 0; |
247 | } | 252 | } |
248 | 253 | ||
249 | int acpi_processor_resume(struct acpi_device * device) | 254 | int acpi_processor_resume(struct acpi_device * device) |
250 | { | 255 | { |
256 | if (acpi_idle_suspend == 0) | ||
257 | return 0; | ||
258 | |||
251 | acpi_idle_bm_rld_restore(); | 259 | acpi_idle_bm_rld_restore(); |
260 | acpi_idle_suspend = 0; | ||
252 | return 0; | 261 | return 0; |
253 | } | 262 | } |
254 | 263 | ||
@@ -304,16 +313,16 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) | |||
304 | pr->power.states[ACPI_STATE_C3].address = pr->pblk + 5; | 313 | pr->power.states[ACPI_STATE_C3].address = pr->pblk + 5; |
305 | 314 | ||
306 | /* determine latencies from FADT */ | 315 | /* determine latencies from FADT */ |
307 | pr->power.states[ACPI_STATE_C2].latency = acpi_gbl_FADT.C2latency; | 316 | pr->power.states[ACPI_STATE_C2].latency = acpi_gbl_FADT.c2_latency; |
308 | pr->power.states[ACPI_STATE_C3].latency = acpi_gbl_FADT.C3latency; | 317 | pr->power.states[ACPI_STATE_C3].latency = acpi_gbl_FADT.c3_latency; |
309 | 318 | ||
310 | /* | 319 | /* |
311 | * FADT specified C2 latency must be less than or equal to | 320 | * FADT specified C2 latency must be less than or equal to |
312 | * 100 microseconds. | 321 | * 100 microseconds. |
313 | */ | 322 | */ |
314 | if (acpi_gbl_FADT.C2latency > ACPI_PROCESSOR_MAX_C2_LATENCY) { | 323 | if (acpi_gbl_FADT.c2_latency > ACPI_PROCESSOR_MAX_C2_LATENCY) { |
315 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 324 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
316 | "C2 latency too large [%d]\n", acpi_gbl_FADT.C2latency)); | 325 | "C2 latency too large [%d]\n", acpi_gbl_FADT.c2_latency)); |
317 | /* invalidate C2 */ | 326 | /* invalidate C2 */ |
318 | pr->power.states[ACPI_STATE_C2].address = 0; | 327 | pr->power.states[ACPI_STATE_C2].address = 0; |
319 | } | 328 | } |
@@ -322,9 +331,9 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) | |||
322 | * FADT supplied C3 latency must be less than or equal to | 331 | * FADT supplied C3 latency must be less than or equal to |
323 | * 1000 microseconds. | 332 | * 1000 microseconds. |
324 | */ | 333 | */ |
325 | if (acpi_gbl_FADT.C3latency > ACPI_PROCESSOR_MAX_C3_LATENCY) { | 334 | if (acpi_gbl_FADT.c3_latency > ACPI_PROCESSOR_MAX_C3_LATENCY) { |
326 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 335 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
327 | "C3 latency too large [%d]\n", acpi_gbl_FADT.C3latency)); | 336 | "C3 latency too large [%d]\n", acpi_gbl_FADT.c3_latency)); |
328 | /* invalidate C3 */ | 337 | /* invalidate C3 */ |
329 | pr->power.states[ACPI_STATE_C3].address = 0; | 338 | pr->power.states[ACPI_STATE_C3].address = 0; |
330 | } | 339 | } |
@@ -754,6 +763,12 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, | |||
754 | 763 | ||
755 | local_irq_disable(); | 764 | local_irq_disable(); |
756 | 765 | ||
766 | if (acpi_idle_suspend) { | ||
767 | local_irq_enable(); | ||
768 | cpu_relax(); | ||
769 | return -EBUSY; | ||
770 | } | ||
771 | |||
757 | lapic_timer_state_broadcast(pr, cx, 1); | 772 | lapic_timer_state_broadcast(pr, cx, 1); |
758 | kt1 = ktime_get_real(); | 773 | kt1 = ktime_get_real(); |
759 | acpi_idle_do_entry(cx); | 774 | acpi_idle_do_entry(cx); |
@@ -823,6 +838,12 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
823 | 838 | ||
824 | local_irq_disable(); | 839 | local_irq_disable(); |
825 | 840 | ||
841 | if (acpi_idle_suspend) { | ||
842 | local_irq_enable(); | ||
843 | cpu_relax(); | ||
844 | return -EBUSY; | ||
845 | } | ||
846 | |||
826 | if (cx->entry_method != ACPI_CSTATE_FFH) { | 847 | if (cx->entry_method != ACPI_CSTATE_FFH) { |
827 | current_thread_info()->status &= ~TS_POLLING; | 848 | current_thread_info()->status &= ~TS_POLLING; |
828 | /* | 849 | /* |
@@ -907,14 +928,21 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
907 | drv, drv->safe_state_index); | 928 | drv, drv->safe_state_index); |
908 | } else { | 929 | } else { |
909 | local_irq_disable(); | 930 | local_irq_disable(); |
910 | acpi_safe_halt(); | 931 | if (!acpi_idle_suspend) |
932 | acpi_safe_halt(); | ||
911 | local_irq_enable(); | 933 | local_irq_enable(); |
912 | return -EINVAL; | 934 | return -EBUSY; |
913 | } | 935 | } |
914 | } | 936 | } |
915 | 937 | ||
916 | local_irq_disable(); | 938 | local_irq_disable(); |
917 | 939 | ||
940 | if (acpi_idle_suspend) { | ||
941 | local_irq_enable(); | ||
942 | cpu_relax(); | ||
943 | return -EBUSY; | ||
944 | } | ||
945 | |||
918 | if (cx->entry_method != ACPI_CSTATE_FFH) { | 946 | if (cx->entry_method != ACPI_CSTATE_FFH) { |
919 | current_thread_info()->status &= ~TS_POLLING; | 947 | current_thread_info()->status &= ~TS_POLLING; |
920 | /* | 948 | /* |