diff options
Diffstat (limited to 'arch/arm/kernel/time.c')
| -rw-r--r-- | arch/arm/kernel/time.c | 24 | 
1 files changed, 17 insertions, 7 deletions
| 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) | |||
| 422 | void timer_dyn_reprogram(void) | 422 | void 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 | ||
| 436 | static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf) | 441 | static 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 | ||
