x86: GEODE fix a race condition in the MFGPT timer tick
When we set the MFGPT timer tick, there is a chance that we'll immediately assert an event. If for some reason the IRQ routing for this clock has been setup for some other purpose, then we could end up firing an interrupt into the SMM handler or worse. This rearranges the timer tick init function to initalize the handler before we set up the MFGPT clock to make sure that even if we get an event, it will go to the handler. Furthermore, in the handler we need to make sure that we clear the event, even if the timer isn't running. Signed-off-by: Jordan Crouse <jordan.crouse@amd.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: Ingo Molnar <mingo@elte.hu> Tested-by: Arnd Hannemann <hannemann@i4.informatik.rwth-aachen.de>
This commit is contained in:
parent
889c94a14e
commit
667984d9e4
|
@ -278,12 +278,12 @@ static int mfgpt_next_event(unsigned long delta, struct clock_event_device *evt)
|
|||
|
||||
static irqreturn_t mfgpt_tick(int irq, void *dev_id)
|
||||
{
|
||||
/* Turn off the clock (and clear the event) */
|
||||
mfgpt_disable_timer(mfgpt_event_clock);
|
||||
|
||||
if (mfgpt_tick_mode == CLOCK_EVT_MODE_SHUTDOWN)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
/* Turn off the clock */
|
||||
mfgpt_disable_timer(mfgpt_event_clock);
|
||||
|
||||
/* Clear the counter */
|
||||
geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_COUNTER, 0);
|
||||
|
||||
|
@ -319,10 +319,6 @@ static int __init mfgpt_timer_setup(void)
|
|||
}
|
||||
|
||||
mfgpt_event_clock = timer;
|
||||
/* Set the clock scale and enable the event mode for CMP2 */
|
||||
val = MFGPT_SCALE | (3 << 8);
|
||||
|
||||
geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_SETUP, val);
|
||||
|
||||
/* Set up the IRQ on the MFGPT side */
|
||||
if (geode_mfgpt_setup_irq(mfgpt_event_clock, MFGPT_CMP2, irq)) {
|
||||
|
@ -339,6 +335,11 @@ static int __init mfgpt_timer_setup(void)
|
|||
goto err;
|
||||
}
|
||||
|
||||
/* Set the clock scale and enable the event mode for CMP2 */
|
||||
val = MFGPT_SCALE | (3 << 8);
|
||||
|
||||
geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_SETUP, val);
|
||||
|
||||
/* Set up the clock event */
|
||||
mfgpt_clockevent.mult = div_sc(MFGPT_HZ, NSEC_PER_SEC, 32);
|
||||
mfgpt_clockevent.min_delta_ns = clockevent_delta2ns(0xF,
|
||||
|
|
Loading…
Reference in New Issue