Commit e17bcb43 authored by Thomas Gleixner's avatar Thomas Gleixner Committed by Ingo Molnar

ACPI: move timer broadcast before busmaster disable

The timer broadcast code might access HPET, which should not be
accessed after the busmaster disable.

In acpi_idle_enter_simple() this change also prevents, that we modify
the busmaster state without going actually idle. This might leave the
ACPI bm state in a stale state, when we leave the function early in
the need_resched() check.
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Acked-by: default avatarVenkatesh Pallipadi <venkatesh.pallipadi@intel.com>
parent 167b1de3
...@@ -530,6 +530,11 @@ static void acpi_processor_idle(void) ...@@ -530,6 +530,11 @@ static void acpi_processor_idle(void)
break; break;
case ACPI_STATE_C3: case ACPI_STATE_C3:
/*
* Must be done before busmaster disable as we might
* need to access HPET !
*/
acpi_state_timer_broadcast(pr, cx, 1);
/* /*
* disable bus master * disable bus master
* bm_check implies we need ARB_DIS * bm_check implies we need ARB_DIS
...@@ -557,7 +562,6 @@ static void acpi_processor_idle(void) ...@@ -557,7 +562,6 @@ static void acpi_processor_idle(void)
/* Get start time (ticks) */ /* Get start time (ticks) */
t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
/* Invoke C3 */ /* Invoke C3 */
acpi_state_timer_broadcast(pr, cx, 1);
/* Tell the scheduler that we are going deep-idle: */ /* Tell the scheduler that we are going deep-idle: */
sched_clock_idle_sleep_event(); sched_clock_idle_sleep_event();
acpi_cstate_enter(cx); acpi_cstate_enter(cx);
...@@ -1401,9 +1405,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, ...@@ -1401,9 +1405,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
if (acpi_idle_suspend) if (acpi_idle_suspend)
return(acpi_idle_enter_c1(dev, state)); return(acpi_idle_enter_c1(dev, state));
if (pr->flags.bm_check)
acpi_idle_update_bm_rld(pr, cx);
local_irq_disable(); local_irq_disable();
current_thread_info()->status &= ~TS_POLLING; current_thread_info()->status &= ~TS_POLLING;
/* /*
...@@ -1418,13 +1419,21 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, ...@@ -1418,13 +1419,21 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
return 0; return 0;
} }
/*
* Must be done before busmaster disable as we might need to
* access HPET !
*/
acpi_state_timer_broadcast(pr, cx, 1);
if (pr->flags.bm_check)
acpi_idle_update_bm_rld(pr, cx);
if (cx->type == ACPI_STATE_C3) if (cx->type == ACPI_STATE_C3)
ACPI_FLUSH_CPU_CACHE(); ACPI_FLUSH_CPU_CACHE();
t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
/* Tell the scheduler that we are going deep-idle: */ /* Tell the scheduler that we are going deep-idle: */
sched_clock_idle_sleep_event(); sched_clock_idle_sleep_event();
acpi_state_timer_broadcast(pr, cx, 1);
acpi_idle_do_entry(cx); acpi_idle_do_entry(cx);
t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment