Skip to content

Commit

Permalink
clocksource: add enable() and disable() callbacks
Browse files Browse the repository at this point in the history
Add enable() and disable() callbacks for clocksources.

This allows us to put unused clocksources in power save mode.  The
functions clocksource_enable() and clocksource_disable() wrap the
callbacks and are inserted in the timekeeping code to enable before use
and disable after switching to a new clocksource.

Signed-off-by: Magnus Damm <damm@igel.co.jp>
Acked-by: John Stultz <johnstul@us.ibm.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Magnus Damm authored and Linus Torvalds committed Apr 21, 2009
1 parent 8e19608 commit 4614e6a
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 3 deletions.
31 changes: 31 additions & 0 deletions include/linux/clocksource.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ extern u64 timecounter_cyc2time(struct timecounter *tc,
* The ideal clocksource. A must-use where
* available.
* @read: returns a cycle value, passes clocksource as argument
* @enable: optional function to enable the clocksource
* @disable: optional function to disable the clocksource
* @mask: bitmask for two's complement
* subtraction of non 64 bit counters
* @mult: cycle to nanosecond multiplier (adjusted by NTP)
Expand All @@ -163,6 +165,8 @@ struct clocksource {
struct list_head list;
int rating;
cycle_t (*read)(struct clocksource *cs);
int (*enable)(struct clocksource *cs);
void (*disable)(struct clocksource *cs);
cycle_t mask;
u32 mult;
u32 mult_orig;
Expand Down Expand Up @@ -274,6 +278,33 @@ static inline cycle_t clocksource_read(struct clocksource *cs)
return cs->read(cs);
}

/**
* clocksource_enable: - enable clocksource
* @cs: pointer to clocksource
*
* Enables the specified clocksource. The clocksource callback
* function should start up the hardware and setup mult and field
* members of struct clocksource to reflect hardware capabilities.
*/
static inline int clocksource_enable(struct clocksource *cs)
{
return cs->enable ? cs->enable(cs) : 0;
}

/**
* clocksource_disable: - disable clocksource
* @cs: pointer to clocksource
*
* Disables the specified clocksource. The clocksource callback
* function should power down the now unused hardware block to
* save power.
*/
static inline void clocksource_disable(struct clocksource *cs)
{
if (cs->disable)
cs->disable(cs);
}

/**
* cyc2ns - converts clocksource cycles to nanoseconds
* @cs: Pointer to clocksource
Expand Down
12 changes: 9 additions & 3 deletions kernel/time/timekeeping.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ EXPORT_SYMBOL(do_settimeofday);
*/
static void change_clocksource(void)
{
struct clocksource *new;
struct clocksource *new, *old;

new = clocksource_get_next();

Expand All @@ -191,11 +191,16 @@ static void change_clocksource(void)

clocksource_forward_now();

new->raw_time = clock->raw_time;
if (clocksource_enable(new))
return;

new->raw_time = clock->raw_time;
old = clock;
clock = new;
clocksource_disable(old);

clock->cycle_last = 0;
clock->cycle_last = clocksource_read(new);
clock->cycle_last = clocksource_read(clock);
clock->error = 0;
clock->xtime_nsec = 0;
clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
Expand Down Expand Up @@ -292,6 +297,7 @@ void __init timekeeping_init(void)
ntp_init();

clock = clocksource_get_next();
clocksource_enable(clock);
clocksource_calculate_interval(clock, NTP_INTERVAL_LENGTH);
clock->cycle_last = clocksource_read(clock);

Expand Down

0 comments on commit 4614e6a

Please sign in to comment.