__init and i386 timers
PATCH 1/1 __init and i386 timers
The i386 timers use a struct timer_opts that has a field init pointing at a __init function. The rest of the struct is not __init.
Nothing is wrong, but if we want to avoid having references to init stuff in non-init sections, some reshuffling is needed.
The below replaces
struct timer_opts {
int (*init)(char *override);
... more ...
};by the two structs
struct timer_opts {
... more ...
};struct init_time_opts {
int (*init)(char *override);
struct timer_opts *opts;
};where the second is __initdata.
Andries
arch/i386/kernel/timers/timer.c +8 -8
@@ -12,18 +12,18 @@*/ #endif /* list of timers, ordered by preference, NULL terminated */ -static struct timer_opts * timers[] = { +static struct init_timer_opts *__initdata timers[] = { #ifdef CONFIG_X86_CYCLONE_TIMER - &timer_cyclone, + &timer_cyclone_init, #endif #ifdef CONFIG_HPET_TIMER - &timer_hpet, + &timer_hpet_init, #endif #ifdef CONFIG_X86_PM_TIMER - &timer_pmtmr, + &timer_pmtmr_init, #endif - &timer_tsc, - &timer_pit, + &timer_tsc_init, + &timer_pit_init,NULL , };
@@ -49,7 +49,7 @@ void clock_fallback(void)/* iterates through the list of timers, returning the first * one that initializes successfully. */ -struct timer_opts *select_timer (void ) +struct timer_opts *__init select_timer (void ) {int i =0 ;
@@ -57,7 +57,7 @@ struct timer_opts* select_timer(void)while (timers[i]) {if (timers[i]->init)if (timers[i]->init (clock_override) ==0 ) -return timers[i]; +return timers[i]->opts; ++i; }
arch/i386/kernel/timers/timer_cyclone.c +6 -2
@@ -245,11 +245,15 @@ static void delay_cyclone(unsigned long/************************************************************/ /* cyclone timer_opts struct */ -struct timer_opts timer_cyclone = { +static struct timer_opts timer_cyclone = { .name ="cyclone" , - .init = init_cyclone, .mark_offset = mark_offset_cyclone, .get_offset = get_offset_cyclone, .monotonic_clock = monotonic_clock_cyclone, .delay = delay_cyclone, }; + +struct init_timer_opts __initdata timer_cyclone_init = { + .init = init_cyclone, + .opts = &timer_cyclone, +};
arch/i386/kernel/timers/timer_hpet.c +6 -2
@@ -177,11 +177,15 @@ static int __init init_hpet(char* overri/************************************************************/ /* tsc timer_opts struct */ -struct timer_opts timer_hpet = { +static struct timer_opts timer_hpet = { .name ="hpet" , - .init = init_hpet, .mark_offset = mark_offset_hpet, .get_offset = get_offset_hpet, .monotonic_clock = monotonic_clock_hpet, .delay = delay_hpet, }; + +struct init_timer_opts __initdata timer_hpet_init = { + .init = init_hpet, + .opts = &timer_hpet, +};
arch/i386/kernel/timers/timer_none.c +0 -6
@@ -1,11 +1,6 @@#include <linux/init.h> #include <asm/timer.h> -static int __init init_none (char * override) -{ -return 0 ; -} -static void mark_offset_none (void ) {/* nothing needed */
@@ -37,7 +32,6 @@ static void delay_none(unsigned long loo/* none timer_opts struct */ struct timer_opts timer_none = { .name ="none" , - .init = init_none, .mark_offset = mark_offset_none, .get_offset = get_offset_none, .monotonic_clock = monotonic_clock_none,
arch/i386/kernel/timers/timer_pit.c +8 -4
@@ -152,14 +152,18 @@ static unsigned long get_offset_pit(void/* tsc timer_opts struct */ struct timer_opts timer_pit = { - .name ="pit" , - .init = init_pit, - .mark_offset = mark_offset_pit, - .get_offset = get_offset_pit, + .name ="pit" , + .mark_offset = mark_offset_pit, + .get_offset = get_offset_pit, .monotonic_clock = monotonic_clock_pit, .delay = delay_pit, }; +struct init_timer_opts __initdata timer_pit_init = { + .init = init_pit, + .opts = &timer_pit, +}; +void setup_pit_timer (void ) {extern spinlock_t i8253_lock;
arch/i386/kernel/timers/timer_pm.c +5 -2
@@ -240,15 +240,18 @@ static unsigned long get_offset_pmtmr(vo/* acpi timer_opts struct */ -struct timer_opts timer_pmtmr = { +static struct timer_opts timer_pmtmr = { .name ="pmtmr" , - .init = init_pmtmr, .mark_offset = mark_offset_pmtmr, .get_offset = get_offset_pmtmr, .monotonic_clock = monotonic_clock_pmtmr, .delay = delay_pmtmr, }; +struct init_timer_opts __initdata timer_pmtmr_init = { + .init = init_pmtmr, + .opts = &timer_pmtmr, +};MODULE_LICENSE ("GPL" );MODULE_AUTHOR ("Dominik Brodowski <[email protected]>" );
arch/i386/kernel/timers/timer_tsc.c +11 -7
@@ -28,7 +28,7 @@#ifdef CONFIG_HPET_TIMER static unsigned long hpet_usec_quotient;static unsigned long hpet_last; -struct timer_opts timer_tsc; +static struct timer_opts timer_tsc;#endif static inline void cpufreq_delayed_get (void );
@@ -546,11 +546,15 @@ __setup("notsc", tsc_setup);/************************************************************/ /* tsc timer_opts struct */ -struct timer_opts timer_tsc = { - .name ="tsc" , - .init = init_tsc, - .mark_offset = mark_offset_tsc, - .get_offset = get_offset_tsc, - .monotonic_clock = monotonic_clock_tsc, +static struct timer_opts timer_tsc = { + .name ="tsc" , + .mark_offset = mark_offset_tsc, + .get_offset = get_offset_tsc, + .monotonic_clock = monotonic_clock_tsc, .delay = delay_tsc, }; + +struct init_timer_opts __initdata timer_tsc_init = { + .init = init_tsc, + .opts = &timer_tsc, +};
include/asm-i386/timer.h +13 -7
@@ -1,5 +1,6 @@#ifndef _ASMi386_TIMER_H#define _ASMi386_TIMER_H +#include <linux/init.h> /** * struct timer_ops - used to define a timer source
@@ -15,18 +16,22 @@* timer. * @delay: delays this many clock cycles. */ -struct timer_opts { +struct timer_opts {char * name; -int (*init)(char *override);void (*mark_offset)(void );unsigned long (*get_offset)(void );unsigned long long (*monotonic_clock)(void );void (*delay)(unsigned long ); }; +struct init_timer_opts { +int (*init)(char *override); +struct timer_opts *opts; +}; +#define TICK_SIZE (tick_nsec / 1000) -extern struct timer_opts *select_timer (void ); +extern struct timer_opts *__init select_timer (void );extern void clock_fallback (void );void setup_pit_timer (void );
@@ -40,19 +45,20 @@ extern int timer_ack;/* list of externed timers */ extern struct timer_opts timer_none;extern struct timer_opts timer_pit; -extern struct timer_opts timer_tsc; +extern struct init_timer_opts timer_pit_init; +extern struct init_timer_opts timer_tsc_init;#ifdef CONFIG_X86_CYCLONE_TIMER -extern struct timer_opts timer_cyclone; +extern struct init_timer_opts timer_cyclone_init;#endif extern unsigned long calibrate_tsc (void );extern void init_cpu_khz (void );#ifdef CONFIG_HPET_TIMER -extern struct timer_opts timer_hpet; +extern struct init_timer_opts timer_hpet_init;extern unsigned long calibrate_tsc_hpet (unsigned long *tsc_hpet_quotient_ptr);#endif #ifdef CONFIG_X86_PM_TIMER -extern struct timer_opts timer_pmtmr; +extern struct init_timer_opts timer_pmtmr_init;#endif #endif
Quoted 5 lines · Andries Brouwer
The i386 timers use a struct
timer_optsthat has a field init pointing at a__initfunction. The rest of the struct is not__init.Nothing is wrong, but if we want to avoid having references to init stuff in non-init sections, some reshuffling is needed.
Ugh. I understand the goal, but the resulting code indirection turns my stomach a bit.
Although do take my criticism lightly, as right off I don't have a better suggestion other then to just yank the __init attribute from the initialization functions. I'm just not sure the savings is worth the added staple-gunned complexity. Might there be a better way?
thanks
-john
Quoted 7 lines · john stultz
Quoted 5 lines · Andries Brouwer
The i386 timers use a struct
timer_optsthat has a field init pointing at a__initfunction. The rest of the struct is not__init.Nothing is wrong, but if we want to avoid having references to init stuff in non-init sections, some reshuffling is needed.
Quoted 7 lines
Ugh. I understand the goal, but the resulting code indirection turns my stomach a bit.
Although do take my criticism lightly, as right off I don't have a better suggestion other then to just yank the
__initattribute from the initialization functions. I'm just not sure the savings is worth the added staple-gunned complexity. Might there be a better way?
I'd second. We already have too much complexity in the time related code.
Tim