|
@@ -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;
|
|
|
}
|
|
|
|
|
@@ -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;
|
|
|
/*
|