Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 3200
b: refs/heads/master
c: 8749af6
h: refs/heads/master
v: v3
  • Loading branch information
Russell King authored and Russell King committed Jun 25, 2005
1 parent 243006f commit 5c7f1e6
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 321ab6a5fab812658626aee6bce2617f8cfb3a55
refs/heads/master: 8749af68216e1ebf6460992fce548f400ecf63a4
15 changes: 15 additions & 0 deletions trunk/arch/arm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,21 @@ config PREEMPT
Say Y here if you are building a kernel for a desktop, embedded
or real-time system. Say N if you are unsure.

config NO_IDLE_HZ
bool "Dynamic tick timer"
help
Select this option if you want to disable continuous timer ticks
and have them programmed to occur as required. This option saves
power as the system can remain in idle state for longer.

By default dynamic tick is disabled during the boot, and can be
manually enabled with:

echo 1 > /sys/devices/system/timer/timer0/dyn_tick

Alternatively, if you want dynamic tick automatically enabled
during boot, pass "dyntick=enable" via the kernel command string.

config ARCH_DISCONTIGMEM_ENABLE
bool
default (ARCH_LH7A40X && !LH7A40X_CONTIGMEM)
Expand Down
14 changes: 14 additions & 0 deletions trunk/arch/arm/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
* Copyright (C) 1992 Linus Torvalds
* Modifications for ARM processor Copyright (C) 1995-2000 Russell King.
*
* Support for Dynamic Tick Timer Copyright (C) 2004-2005 Nokia Corporation.
* Dynamic Tick Timer written by Tony Lindgren <tony@atomide.com> and
* Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
Expand Down Expand Up @@ -37,6 +41,7 @@
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/mach/irq.h>
#include <asm/mach/time.h>

/*
* Maximum IRQ count. Currently, this is arbitary. However, it should
Expand Down Expand Up @@ -329,6 +334,15 @@ __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)

spin_unlock(&irq_controller_lock);

#ifdef CONFIG_NO_IDLE_HZ
if (!(action->flags & SA_TIMER) && system_timer->dyn_tick != NULL) {
write_seqlock(&xtime_lock);
if (system_timer->dyn_tick->state & DYN_TICK_ENABLED)
system_timer->dyn_tick->handler(irq, 0, regs);
write_sequnlock(&xtime_lock);
}
#endif

if (!(action->flags & SA_INTERRUPT))
local_irq_enable();

Expand Down
103 changes: 103 additions & 0 deletions trunk/arch/arm/kernel/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -381,13 +381,116 @@ static struct sysdev_class timer_sysclass = {
.resume = timer_resume,
};

#ifdef CONFIG_NO_IDLE_HZ
static int timer_dyn_tick_enable(void)
{
struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick;
unsigned long flags;
int ret = -ENODEV;

if (dyn_tick) {
write_seqlock_irqsave(&xtime_lock, flags);
ret = 0;
if (!(dyn_tick->state & DYN_TICK_ENABLED)) {
ret = dyn_tick->enable();

if (ret == 0)
dyn_tick->state |= DYN_TICK_ENABLED;
}
write_sequnlock_irqrestore(&xtime_lock, flags);
}

return ret;
}

static int timer_dyn_tick_disable(void)
{
struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick;
unsigned long flags;
int ret = -ENODEV;

if (dyn_tick) {
write_seqlock_irqsave(&xtime_lock, flags);
ret = 0;
if (dyn_tick->state & DYN_TICK_ENABLED) {
ret = dyn_tick->disable();

if (ret == 0)
dyn_tick->state &= ~DYN_TICK_ENABLED;
}
write_sequnlock_irqrestore(&xtime_lock, flags);
}

return ret;
}

void timer_dyn_reprogram(void)
{
struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick;
unsigned long flags;

write_seqlock_irqsave(&xtime_lock, flags);
if (dyn_tick->state & DYN_TICK_ENABLED)
dyn_tick->reprogram(next_timer_interrupt() - jiffies);
write_sequnlock_irqrestore(&xtime_lock, flags);
}

static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf)
{
return sprintf(buf, "%i\n",
(system_timer->dyn_tick->state & DYN_TICK_ENABLED) >> 1);
}

static ssize_t timer_set_dyn_tick(struct sys_device *dev, const char *buf,
size_t count)
{
unsigned int enable = simple_strtoul(buf, NULL, 2);

if (enable)
timer_dyn_tick_enable();
else
timer_dyn_tick_disable();

return count;
}
static SYSDEV_ATTR(dyn_tick, 0644, timer_show_dyn_tick, timer_set_dyn_tick);

/*
* dyntick=enable|disable
*/
static char dyntick_str[4] __initdata = "";

static int __init dyntick_setup(char *str)
{
if (str)
strlcpy(dyntick_str, str, sizeof(dyntick_str));
return 1;
}

__setup("dyntick=", dyntick_setup);
#endif

static int __init timer_init_sysfs(void)
{
int ret = sysdev_class_register(&timer_sysclass);
if (ret == 0) {
system_timer->dev.cls = &timer_sysclass;
ret = sysdev_register(&system_timer->dev);
}

#ifdef CONFIG_NO_IDLE_HZ
if (ret == 0 && system_timer->dyn_tick) {
ret = sysdev_create_file(&system_timer->dev, &attr_dyn_tick);

/*
* Turn on dynamic tick after calibrate delay
* for correct bogomips
*/
if (ret == 0 && dyntick_str[0] == 'e')
ret = timer_dyn_tick_enable();
}
#endif

return ret;
}

Expand Down
21 changes: 21 additions & 0 deletions trunk/include/asm-arm/mach/time.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,29 @@ struct sys_timer {
void (*suspend)(void);
void (*resume)(void);
unsigned long (*offset)(void);

#ifdef CONFIG_NO_IDLE_HZ
struct dyn_tick_timer *dyn_tick;
#endif
};

#ifdef CONFIG_NO_IDLE_HZ

#define DYN_TICK_SKIPPING (1 << 2)
#define DYN_TICK_ENABLED (1 << 1)
#define DYN_TICK_SUITABLE (1 << 0)

struct dyn_tick_timer {
unsigned int state; /* Current state */
int (*enable)(void); /* Enables dynamic tick */
int (*disable)(void); /* Disables dynamic tick */
void (*reprogram)(unsigned long); /* Reprograms the timer */
int (*handler)(int, void *, struct pt_regs *);
};

void timer_dyn_reprogram(void);
#endif

extern struct sys_timer *system_timer;
extern void timer_tick(struct pt_regs *);

Expand Down
1 change: 1 addition & 0 deletions trunk/include/asm-arm/signal.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ typedef unsigned long sigset_t;
#define SIGSTKSZ 8192

#ifdef __KERNEL__
#define SA_TIMER 0x40000000
#define SA_IRQNOMASK 0x08000000
#endif

Expand Down

0 comments on commit 5c7f1e6

Please sign in to comment.