Merge branches 'acpi_pad', 'acpica', 'apei-bugzilla-43282', 'battery', 'cpuidle-coupl...
[sfrench/cifs-2.6.git] / drivers / acpi / processor_idle.c
index f3decb30223fd1b376775310ae25dec63424f920..9837c9c4f00957422dd3722e9fe2e3f5de0aaf02 100644 (file)
@@ -224,6 +224,7 @@ static void lapic_timer_state_broadcast(struct acpi_processor *pr,
 /*
  * Suspend / resume control
  */
+static int acpi_idle_suspend;
 static u32 saved_bm_rld;
 
 static void acpi_idle_bm_rld_save(void)
@@ -242,13 +243,21 @@ static void acpi_idle_bm_rld_restore(void)
 
 int acpi_processor_suspend(struct acpi_device * device, pm_message_t state)
 {
+       if (acpi_idle_suspend == 1)
+               return 0;
+
        acpi_idle_bm_rld_save();
+       acpi_idle_suspend = 1;
        return 0;
 }
 
 int acpi_processor_resume(struct acpi_device * device)
 {
+       if (acpi_idle_suspend == 0)
+               return 0;
+
        acpi_idle_bm_rld_restore();
+       acpi_idle_suspend = 0;
        return 0;
 }
 
@@ -304,16 +313,16 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
        pr->power.states[ACPI_STATE_C3].address = pr->pblk + 5;
 
        /* determine latencies from FADT */
-       pr->power.states[ACPI_STATE_C2].latency = acpi_gbl_FADT.C2latency;
-       pr->power.states[ACPI_STATE_C3].latency = acpi_gbl_FADT.C3latency;
+       pr->power.states[ACPI_STATE_C2].latency = acpi_gbl_FADT.c2_latency;
+       pr->power.states[ACPI_STATE_C3].latency = acpi_gbl_FADT.c3_latency;
 
        /*
         * FADT specified C2 latency must be less than or equal to
         * 100 microseconds.
         */
-       if (acpi_gbl_FADT.C2latency > ACPI_PROCESSOR_MAX_C2_LATENCY) {
+       if (acpi_gbl_FADT.c2_latency > ACPI_PROCESSOR_MAX_C2_LATENCY) {
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                       "C2 latency too large [%d]\n", acpi_gbl_FADT.C2latency));
+                       "C2 latency too large [%d]\n", acpi_gbl_FADT.c2_latency));
                /* invalidate C2 */
                pr->power.states[ACPI_STATE_C2].address = 0;
        }
@@ -322,9 +331,9 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
         * FADT supplied C3 latency must be less than or equal to
         * 1000 microseconds.
         */
-       if (acpi_gbl_FADT.C3latency > ACPI_PROCESSOR_MAX_C3_LATENCY) {
+       if (acpi_gbl_FADT.c3_latency > ACPI_PROCESSOR_MAX_C3_LATENCY) {
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                       "C3 latency too large [%d]\n", acpi_gbl_FADT.C3latency));
+                       "C3 latency too large [%d]\n", acpi_gbl_FADT.c3_latency));
                /* invalidate C3 */
                pr->power.states[ACPI_STATE_C3].address = 0;
        }
@@ -754,6 +763,12 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
 
        local_irq_disable();
 
+       if (acpi_idle_suspend) {
+               local_irq_enable();
+               cpu_relax();
+               return -EBUSY;
+       }
+
        lapic_timer_state_broadcast(pr, cx, 1);
        kt1 = ktime_get_real();
        acpi_idle_do_entry(cx);
@@ -823,6 +838,12 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
 
        local_irq_disable();
 
+       if (acpi_idle_suspend) {
+               local_irq_enable();
+               cpu_relax();
+               return -EBUSY;
+       }
+
        if (cx->entry_method != ACPI_CSTATE_FFH) {
                current_thread_info()->status &= ~TS_POLLING;
                /*
@@ -907,14 +928,21 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
                                                drv, drv->safe_state_index);
                } else {
                        local_irq_disable();
-                       acpi_safe_halt();
+                       if (!acpi_idle_suspend)
+                               acpi_safe_halt();
                        local_irq_enable();
-                       return -EINVAL;
+                       return -EBUSY;
                }
        }
 
        local_irq_disable();
 
+       if (acpi_idle_suspend) {
+               local_irq_enable();
+               cpu_relax();
+               return -EBUSY;
+       }
+
        if (cx->entry_method != ACPI_CSTATE_FFH) {
                current_thread_info()->status &= ~TS_POLLING;
                /*