diff options
Diffstat (limited to 'arch/arm/kernel/time.c')
-rw-r--r-- | arch/arm/kernel/time.c | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index c232f24f4a60..06054c9ba074 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c | |||
@@ -381,6 +381,95 @@ static struct sysdev_class timer_sysclass = { | |||
381 | .resume = timer_resume, | 381 | .resume = timer_resume, |
382 | }; | 382 | }; |
383 | 383 | ||
384 | #ifdef CONFIG_NO_IDLE_HZ | ||
385 | static int timer_dyn_tick_enable(void) | ||
386 | { | ||
387 | struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick; | ||
388 | unsigned long flags; | ||
389 | int ret = -ENODEV; | ||
390 | |||
391 | if (dyn_tick) { | ||
392 | write_seqlock_irqsave(&xtime_lock, flags); | ||
393 | ret = 0; | ||
394 | if (!(dyn_tick->state & DYN_TICK_ENABLED)) { | ||
395 | ret = dyn_tick->enable(); | ||
396 | |||
397 | if (ret == 0) | ||
398 | dyn_tick->state |= DYN_TICK_ENABLED; | ||
399 | } | ||
400 | write_sequnlock_irqrestore(&xtime_lock, flags); | ||
401 | } | ||
402 | |||
403 | return ret; | ||
404 | } | ||
405 | |||
406 | static int timer_dyn_tick_disable(void) | ||
407 | { | ||
408 | struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick; | ||
409 | unsigned long flags; | ||
410 | int ret = -ENODEV; | ||
411 | |||
412 | if (dyn_tick) { | ||
413 | write_seqlock_irqsave(&xtime_lock, flags); | ||
414 | ret = 0; | ||
415 | if (dyn_tick->state & DYN_TICK_ENABLED) { | ||
416 | ret = dyn_tick->disable(); | ||
417 | |||
418 | if (ret == 0) | ||
419 | dyn_tick->state &= ~DYN_TICK_ENABLED; | ||
420 | } | ||
421 | write_sequnlock_irqrestore(&xtime_lock, flags); | ||
422 | } | ||
423 | |||
424 | return ret; | ||
425 | } | ||
426 | |||
427 | void timer_dyn_reprogram(void) | ||
428 | { | ||
429 | struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick; | ||
430 | unsigned long flags; | ||
431 | |||
432 | write_seqlock_irqsave(&xtime_lock, flags); | ||
433 | if (dyn_tick->state & DYN_TICK_ENABLED) | ||
434 | dyn_tick->reprogram(next_timer_interrupt() - jiffies); | ||
435 | write_sequnlock_irqrestore(&xtime_lock, flags); | ||
436 | } | ||
437 | |||
438 | static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf) | ||
439 | { | ||
440 | return sprintf(buf, "%i\n", | ||
441 | (system_timer->dyn_tick->state & DYN_TICK_ENABLED) >> 1); | ||
442 | } | ||
443 | |||
444 | static ssize_t timer_set_dyn_tick(struct sys_device *dev, const char *buf, | ||
445 | size_t count) | ||
446 | { | ||
447 | unsigned int enable = simple_strtoul(buf, NULL, 2); | ||
448 | |||
449 | if (enable) | ||
450 | timer_dyn_tick_enable(); | ||
451 | else | ||
452 | timer_dyn_tick_disable(); | ||
453 | |||
454 | return count; | ||
455 | } | ||
456 | static SYSDEV_ATTR(dyn_tick, 0644, timer_show_dyn_tick, timer_set_dyn_tick); | ||
457 | |||
458 | /* | ||
459 | * dyntick=enable|disable | ||
460 | */ | ||
461 | static char dyntick_str[4] __initdata = ""; | ||
462 | |||
463 | static int __init dyntick_setup(char *str) | ||
464 | { | ||
465 | if (str) | ||
466 | strlcpy(dyntick_str, str, sizeof(dyntick_str)); | ||
467 | return 1; | ||
468 | } | ||
469 | |||
470 | __setup("dyntick=", dyntick_setup); | ||
471 | #endif | ||
472 | |||
384 | static int __init timer_init_sysfs(void) | 473 | static int __init timer_init_sysfs(void) |
385 | { | 474 | { |
386 | int ret = sysdev_class_register(&timer_sysclass); | 475 | int ret = sysdev_class_register(&timer_sysclass); |
@@ -388,6 +477,20 @@ static int __init timer_init_sysfs(void) | |||
388 | system_timer->dev.cls = &timer_sysclass; | 477 | system_timer->dev.cls = &timer_sysclass; |
389 | ret = sysdev_register(&system_timer->dev); | 478 | ret = sysdev_register(&system_timer->dev); |
390 | } | 479 | } |
480 | |||
481 | #ifdef CONFIG_NO_IDLE_HZ | ||
482 | if (ret == 0 && system_timer->dyn_tick) { | ||
483 | ret = sysdev_create_file(&system_timer->dev, &attr_dyn_tick); | ||
484 | |||
485 | /* | ||
486 | * Turn on dynamic tick after calibrate delay | ||
487 | * for correct bogomips | ||
488 | */ | ||
489 | if (ret == 0 && dyntick_str[0] == 'e') | ||
490 | ret = timer_dyn_tick_enable(); | ||
491 | } | ||
492 | #endif | ||
493 | |||
391 | return ret; | 494 | return ret; |
392 | } | 495 | } |
393 | 496 | ||