Commit 9969beed authored by Russell King's avatar Russell King

[ARM] Add seqlocking to timers.

Sometimes, it's useful to have locking.  Especially when we're
talking about time keeping.

It would appear that shemminger's patch of 5th February 2003
completely missed updating _ANY_ ARM timer implementations and,
because linux-arch didn't exist at the time, there appears to
have been no notification to any architecture developer that
maybe, just maybe, some work was required.

One wonders how many other changes are in the kernel which
architecture maintainers have missed.
parent fb3b720c
...@@ -68,8 +68,9 @@ void __init ioctime_init(void) ...@@ -68,8 +68,9 @@ void __init ioctime_init(void)
static irqreturn_t static irqreturn_t
ioc_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ioc_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
write_seqlock(&xtime_lock);
timer_tick(regs); timer_tick(regs);
write_sequnlock(&xtime_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -49,7 +49,9 @@ static unsigned long clps711x_gettimeoffset(void) ...@@ -49,7 +49,9 @@ static unsigned long clps711x_gettimeoffset(void)
static irqreturn_t static irqreturn_t
p720t_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) p720t_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
write_seqlock(&xtime_lock);
timer_tick(regs); timer_tick(regs);
write_sequnlock(&xtime_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -272,6 +272,8 @@ extern unsigned long ioc_timer_gettimeoffset(void); ...@@ -272,6 +272,8 @@ extern unsigned long ioc_timer_gettimeoffset(void);
static irqreturn_t static irqreturn_t
clps7500_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) clps7500_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
write_seqlock(&xtime_lock);
timer_tick(regs); timer_tick(regs);
/* Why not using do_leds interface?? */ /* Why not using do_leds interface?? */
...@@ -284,6 +286,9 @@ clps7500_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -284,6 +286,9 @@ clps7500_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
*((volatile unsigned int *)LED_ADDRESS) = state; *((volatile unsigned int *)LED_ADDRESS) = state;
} }
} }
write_sequnlock(&xtime_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -151,6 +151,8 @@ ebsa110_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -151,6 +151,8 @@ ebsa110_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
u32 count; u32 count;
write_seqlock(&xtime_lock);
/* latch and read timer 1 */ /* latch and read timer 1 */
__raw_writeb(0x40, PIT_CTRL); __raw_writeb(0x40, PIT_CTRL);
count = __raw_readb(PIT_T1); count = __raw_readb(PIT_T1);
...@@ -163,6 +165,8 @@ ebsa110_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -163,6 +165,8 @@ ebsa110_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
timer_tick(regs); timer_tick(regs);
write_sequnlock(&xtime_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -43,11 +43,13 @@ __initcall(epxa10db_rtc_init); ...@@ -43,11 +43,13 @@ __initcall(epxa10db_rtc_init);
static irqreturn_t static irqreturn_t
epxa10db_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) epxa10db_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
write_seqlock(&xtime_lock);
// ...clear the interrupt // ...clear the interrupt
*TIMER0_CR(IO_ADDRESS(EXC_TIMER00_BASE))|=TIMER0_CR_CI_MSK; *TIMER0_CR(IO_ADDRESS(EXC_TIMER00_BASE))|=TIMER0_CR_CI_MSK;
timer_tick(regs); timer_tick(regs);
write_sequnlock(&xtime_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -29,10 +29,14 @@ static unsigned long timer1_gettimeoffset (void) ...@@ -29,10 +29,14 @@ static unsigned long timer1_gettimeoffset (void)
static irqreturn_t static irqreturn_t
timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs) timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
write_seqlock(&xtime_lock);
*CSR_TIMER1_CLR = 0; *CSR_TIMER1_CLR = 0;
timer_tick(regs); timer_tick(regs);
write_sequnlock(&xtime_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -63,8 +63,9 @@ static unsigned long isa_gettimeoffset(void) ...@@ -63,8 +63,9 @@ static unsigned long isa_gettimeoffset(void)
static irqreturn_t static irqreturn_t
isa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) isa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
write_seqlock(&xtime_lock);
timer_tick(regs); timer_tick(regs);
write_sequnlock(&xtime_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -32,8 +32,13 @@ extern void __init h720x_init_irq (void); ...@@ -32,8 +32,13 @@ extern void __init h720x_init_irq (void);
static irqreturn_t static irqreturn_t
h7201_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) h7201_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
write_seqlock(&xtime_lock);
CPU_REG (TIMER_VIRT, TIMER_TOPSTAT); CPU_REG (TIMER_VIRT, TIMER_TOPSTAT);
timer_tick(regs); timer_tick(regs);
write_sequnlock(&xtime_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -64,7 +64,9 @@ h7202_timerx_demux_handler(unsigned int irq_unused, struct irqdesc *desc, ...@@ -64,7 +64,9 @@ h7202_timerx_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
mask = CPU_REG (TIMER_VIRT, TIMER_TOPSTAT); mask = CPU_REG (TIMER_VIRT, TIMER_TOPSTAT);
if ( mask & TSTAT_T0INT ) { if ( mask & TSTAT_T0INT ) {
write_seqlock(&xtime_lock);
timer_tick(regs); timer_tick(regs);
write_sequnlock(&xtime_lock);
if( mask == TSTAT_T0INT ) if( mask == TSTAT_T0INT )
return; return;
} }
......
...@@ -59,11 +59,15 @@ imx_gettimeoffset(void) ...@@ -59,11 +59,15 @@ imx_gettimeoffset(void)
static irqreturn_t static irqreturn_t
imx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) imx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
write_seqlock(&xtime_lock);
/* clear the interrupt */ /* clear the interrupt */
if (IMX_TSTAT(TIMER_BASE)) if (IMX_TSTAT(TIMER_BASE))
IMX_TSTAT(TIMER_BASE) = 0; IMX_TSTAT(TIMER_BASE) = 0;
timer_tick(regs); timer_tick(regs);
write_sequnlock(&xtime_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -214,11 +214,15 @@ integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -214,11 +214,15 @@ integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE; volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE;
write_seqlock(&xtime_lock);
// ...clear the interrupt // ...clear the interrupt
timer1->TimerClear = 1; timer1->TimerClear = 1;
timer_tick(regs); timer_tick(regs);
write_sequnlock(&xtime_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -182,11 +182,15 @@ unsigned long ixp2000_gettimeoffset (void) ...@@ -182,11 +182,15 @@ unsigned long ixp2000_gettimeoffset (void)
static int ixp2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static int ixp2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
write_seqlock(&xtime_lock);
/* clear timer 1 */ /* clear timer 1 */
ixp2000_reg_write(IXP2000_T1_CLR, 1); ixp2000_reg_write(IXP2000_T1_CLR, 1);
timer_tick(regs); timer_tick(regs);
write_sequnlock(&xtime_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -221,6 +221,8 @@ static unsigned long ixp4xx_gettimeoffset(void) ...@@ -221,6 +221,8 @@ static unsigned long ixp4xx_gettimeoffset(void)
static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
write_seqlock(&xtime_lock);
/* Clear Pending Interrupt by writing '1' to it */ /* Clear Pending Interrupt by writing '1' to it */
*IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND; *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND;
...@@ -232,6 +234,8 @@ static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id, struct pt_regs ...@@ -232,6 +234,8 @@ static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id, struct pt_regs
last_jiffy_time += LATCH; last_jiffy_time += LATCH;
} while((*IXP4XX_OSTS - last_jiffy_time) > LATCH); } while((*IXP4XX_OSTS - last_jiffy_time) > LATCH);
write_sequnlock(&xtime_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -41,9 +41,13 @@ ...@@ -41,9 +41,13 @@
static irqreturn_t static irqreturn_t
lh7a40x_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) lh7a40x_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
write_seqlock(&xtime_lock);
TIMER_EOI = 0; TIMER_EOI = 0;
timer_tick(regs); timer_tick(regs);
write_sequnlock(&xtime_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -177,6 +177,8 @@ omap_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -177,6 +177,8 @@ omap_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
unsigned long now, ilatency; unsigned long now, ilatency;
write_seqlock(&xtime_lock);
/* /*
* Mark the time at which the timer interrupt ocurred using * Mark the time at which the timer interrupt ocurred using
* timer1. We need to remove interrupt latency, which we can * timer1. We need to remove interrupt latency, which we can
...@@ -190,6 +192,8 @@ omap_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -190,6 +192,8 @@ omap_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
timer_tick(regs); timer_tick(regs);
write_sequnlock(&xtime_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -75,6 +75,8 @@ pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -75,6 +75,8 @@ pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
int next_match; int next_match;
write_seqlock(&xtime_lock);
/* Loop until we get ahead of the free running timer. /* Loop until we get ahead of the free running timer.
* This ensures an exact clock tick count and time accuracy. * This ensures an exact clock tick count and time accuracy.
* IRQs are disabled inside the loop to ensure coherence between * IRQs are disabled inside the loop to ensure coherence between
...@@ -96,6 +98,8 @@ pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -96,6 +98,8 @@ pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
next_match = (OSMR0 += LATCH); next_match = (OSMR0 += LATCH);
} while( (signed long)(next_match - OSCR) <= 8 ); } while( (signed long)(next_match - OSCR) <= 8 );
write_sequnlock(&xtime_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -88,8 +88,9 @@ static unsigned long s3c2410_gettimeoffset (void) ...@@ -88,8 +88,9 @@ static unsigned long s3c2410_gettimeoffset (void)
static irqreturn_t static irqreturn_t
s3c2410_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) s3c2410_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
write_seqlock(&xtime_lock);
timer_tick(regs); timer_tick(regs);
write_sequnlock(&xtime_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -84,12 +84,16 @@ sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -84,12 +84,16 @@ sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
unsigned int next_match; unsigned int next_match;
write_seqlock(&xtime_lock);
do { do {
timer_tick(regs); timer_tick(regs);
OSSR = OSSR_M0; /* Clear match on timer 0 */ OSSR = OSSR_M0; /* Clear match on timer 0 */
next_match = (OSMR0 += LATCH); next_match = (OSMR0 += LATCH);
} while ((signed long)(next_match - OSCR) <= 0); } while ((signed long)(next_match - OSCR) <= 0);
write_sequnlock(&xtime_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -35,8 +35,9 @@ static void __init shark_map_io(void) ...@@ -35,8 +35,9 @@ static void __init shark_map_io(void)
static irqreturn_t static irqreturn_t
shark_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) shark_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
write_seqlock(&xtime_lock);
timer_tick(regs); timer_tick(regs);
write_sequnlock(&xtime_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -808,11 +808,15 @@ static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id, struct pt_re ...@@ -808,11 +808,15 @@ static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id, struct pt_re
{ {
volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE; volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE;
write_seqlock(&xtime_lock);
// ...clear the interrupt // ...clear the interrupt
timer0->TimerClear = 1; timer0->TimerClear = 1;
timer_tick(regs); timer_tick(regs);
write_sequnlock(&xtime_lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
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