clocksource: add enable() and disable() callbacks
Subsystems (2)
PATCH 2/5 clocksource: add enable() and disable() callbacks
From: Magnus Damm <[email protected]>
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.
---
include/linux/clocksource.h | 31 +++++++++++++++++++++++++++++++ kernel/time/timekeeping.c | 12 +++++++++--- 2 files changed, 40 insertions(+), 3 deletions(-)
include/linux/clocksource.h +31 -0
@@ -44,6 +44,8 @@ struct clocksource;* available. * @read: returns a cycle value * @read2: 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)
@@ -64,6 +66,8 @@ struct clocksource {int rating;cycle_t (*read)(void);cycle_t (*read2)(struct clocksource *cs); +int (*enable)(struct clocksource *cs); +void (*disable)(struct clocksource *cs);cycle_t mask;u32 mult;u32 mult_orig;
@@ -176,6 +180,33 @@ static inline cycle_t clocksource_read(s }/** +* 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 * @cycles: Cycles
kernel/time/timekeeping.c +9 -3
@@ -177,7 +177,7 @@ EXPORT_SYMBOL(do_settimeofday);*/ static void change_clocksource (void ) { -struct clocksource *new; +struct clocksource *new, *old; new =clocksource_get_next ();
@@ -186,11 +186,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 );
@@ -287,6 +292,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);
Quoted 9 lines · Magnus Damm
From: Magnus Damm <[email protected]>
Add
enable()anddisable()callbacks for clocksources. This allows us to put unused clocksources in power save mode. The functionsclocksource_enable()andclocksource_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 <[email protected]>
This looks ok to me.
Quoted 98 lines
---
include/linux/clocksource.h | 31 +++++++++++++++++++++++++++++++ kernel/time/timekeeping.c | 12 +++++++++--- 2 files changed, 40 insertions(+), 3 deletions(-)include/linux/clocksource.h +31
-0@@ -44,6 +44,8 @@ struct clocksource;* available. * @read: returns a cycle value * @read2: 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) @@ -64,6 +66,8 @@ struct clocksource {int rating;cycle_t (*read)(void);cycle_t (*read2)(struct clocksource *cs); +int (*enable)(struct clocksource *cs); +void (*disable)(struct clocksource *cs);cycle_t mask;u32 mult;u32 mult_orig;@@ -176,6 +180,33 @@ static inline cycle_t clocksource_read(s }/** +* 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 * @cycles: Cycles kernel/time/timekeeping.c +9
-3@@ -177,7 +177,7 @@ EXPORT_SYMBOL(do_settimeofday);*/ static void change_clocksource (void ) { -struct clocksource *new; +struct clocksource *new, *old; new =clocksource_get_next ();@@ -186,11 +186,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 );@@ -287,6 +292,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);