Skip to content

Commit

Permalink
ACPI: move timer broadcast before busmaster disable
Browse files Browse the repository at this point in the history
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: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Acked-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
  • Loading branch information
Thomas Gleixner authored and Ingo Molnar committed Dec 7, 2007
1 parent 167b1de commit e17bcb4
Showing 1 changed file with 14 additions and 5 deletions.
19 changes: 14 additions & 5 deletions drivers/acpi/processor_idle.c
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,11 @@ static void acpi_processor_idle(void)
break;

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
* bm_check implies we need ARB_DIS
Expand Down Expand Up @@ -557,7 +562,6 @@ static void acpi_processor_idle(void)
/* Get start time (ticks) */
t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
/* Invoke C3 */
acpi_state_timer_broadcast(pr, cx, 1);
/* Tell the scheduler that we are going deep-idle: */
sched_clock_idle_sleep_event();
acpi_cstate_enter(cx);
Expand Down Expand Up @@ -1401,9 +1405,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
if (acpi_idle_suspend)
return(acpi_idle_enter_c1(dev, state));

if (pr->flags.bm_check)
acpi_idle_update_bm_rld(pr, cx);

local_irq_disable();
current_thread_info()->status &= ~TS_POLLING;
/*
Expand All @@ -1418,13 +1419,21 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
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)
ACPI_FLUSH_CPU_CACHE();

t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
/* Tell the scheduler that we are going deep-idle: */
sched_clock_idle_sleep_event();
acpi_state_timer_broadcast(pr, cx, 1);
acpi_idle_do_entry(cx);
t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);

Expand Down

0 comments on commit e17bcb4

Please sign in to comment.