aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2006-06-18 11:26:58 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-06-18 11:26:58 -0400
commitebc67da65fda03cbe5b4019d91229287fddd5c6e (patch)
tree7f1f77aa0525eecfca86f066d64938c62794e663 /arch/arm/kernel
parent36fe6a83b4a52276eebb929ff94896fa65d83401 (diff)
[ARM] 3554/1: ARM: Fix dyntick locking
Patch from Tony Lindgren This patch fixes some dyntick locking issues on ARM as pointed out by Russell King. Signed-off-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/irq.c4
-rw-r--r--arch/arm/kernel/time.c24
2 files changed, 19 insertions, 9 deletions
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 2d5896b36181..bcc19fbb32df 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -342,10 +342,10 @@ __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)
342 342
343#ifdef CONFIG_NO_IDLE_HZ 343#ifdef CONFIG_NO_IDLE_HZ
344 if (!(action->flags & SA_TIMER) && system_timer->dyn_tick != NULL) { 344 if (!(action->flags & SA_TIMER) && system_timer->dyn_tick != NULL) {
345 write_seqlock(&xtime_lock); 345 spin_lock(&system_timer->dyn_tick->lock);
346 if (system_timer->dyn_tick->state & DYN_TICK_ENABLED) 346 if (system_timer->dyn_tick->state & DYN_TICK_ENABLED)
347 system_timer->dyn_tick->handler(irq, 0, regs); 347 system_timer->dyn_tick->handler(irq, 0, regs);
348 write_sequnlock(&xtime_lock); 348 spin_unlock(&system_timer->dyn_tick->lock);
349 } 349 }
350#endif 350#endif
351 351
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index d6bd435a6857..9c12d4fefbd3 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -379,7 +379,7 @@ static int timer_dyn_tick_enable(void)
379 int ret = -ENODEV; 379 int ret = -ENODEV;
380 380
381 if (dyn_tick) { 381 if (dyn_tick) {
382 write_seqlock_irqsave(&xtime_lock, flags); 382 spin_lock_irqsave(&dyn_tick->lock, flags);
383 ret = 0; 383 ret = 0;
384 if (!(dyn_tick->state & DYN_TICK_ENABLED)) { 384 if (!(dyn_tick->state & DYN_TICK_ENABLED)) {
385 ret = dyn_tick->enable(); 385 ret = dyn_tick->enable();
@@ -387,7 +387,7 @@ static int timer_dyn_tick_enable(void)
387 if (ret == 0) 387 if (ret == 0)
388 dyn_tick->state |= DYN_TICK_ENABLED; 388 dyn_tick->state |= DYN_TICK_ENABLED;
389 } 389 }
390 write_sequnlock_irqrestore(&xtime_lock, flags); 390 spin_unlock_irqrestore(&dyn_tick->lock, flags);
391 } 391 }
392 392
393 return ret; 393 return ret;
@@ -400,7 +400,7 @@ static int timer_dyn_tick_disable(void)
400 int ret = -ENODEV; 400 int ret = -ENODEV;
401 401
402 if (dyn_tick) { 402 if (dyn_tick) {
403 write_seqlock_irqsave(&xtime_lock, flags); 403 spin_lock_irqsave(&dyn_tick->lock, flags);
404 ret = 0; 404 ret = 0;
405 if (dyn_tick->state & DYN_TICK_ENABLED) { 405 if (dyn_tick->state & DYN_TICK_ENABLED) {
406 ret = dyn_tick->disable(); 406 ret = dyn_tick->disable();
@@ -408,7 +408,7 @@ static int timer_dyn_tick_disable(void)
408 if (ret == 0) 408 if (ret == 0)
409 dyn_tick->state &= ~DYN_TICK_ENABLED; 409 dyn_tick->state &= ~DYN_TICK_ENABLED;
410 } 410 }
411 write_sequnlock_irqrestore(&xtime_lock, flags); 411 spin_unlock_irqrestore(&dyn_tick->lock, flags);
412 } 412 }
413 413
414 return ret; 414 return ret;
@@ -422,15 +422,20 @@ static int timer_dyn_tick_disable(void)
422void timer_dyn_reprogram(void) 422void timer_dyn_reprogram(void)
423{ 423{
424 struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick; 424 struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick;
425 unsigned long next, seq; 425 unsigned long next, seq, flags;
426 426
427 if (dyn_tick && (dyn_tick->state & DYN_TICK_ENABLED)) { 427 if (!dyn_tick)
428 return;
429
430 spin_lock_irqsave(&dyn_tick->lock, flags);
431 if (dyn_tick->state & DYN_TICK_ENABLED) {
428 next = next_timer_interrupt(); 432 next = next_timer_interrupt();
429 do { 433 do {
430 seq = read_seqbegin(&xtime_lock); 434 seq = read_seqbegin(&xtime_lock);
431 dyn_tick->reprogram(next_timer_interrupt() - jiffies); 435 dyn_tick->reprogram(next - jiffies);
432 } while (read_seqretry(&xtime_lock, seq)); 436 } while (read_seqretry(&xtime_lock, seq));
433 } 437 }
438 spin_unlock_irqrestore(&dyn_tick->lock, flags);
434} 439}
435 440
436static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf) 441static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf)
@@ -499,5 +504,10 @@ void __init time_init(void)
499 if (system_timer->offset == NULL) 504 if (system_timer->offset == NULL)
500 system_timer->offset = dummy_gettimeoffset; 505 system_timer->offset = dummy_gettimeoffset;
501 system_timer->init(); 506 system_timer->init();
507
508#ifdef CONFIG_NO_IDLE_HZ
509 if (system_timer->dyn_tick)
510 system_timer->dyn_tick->lock = SPIN_LOCK_UNLOCKED;
511#endif
502} 512}
503 513