Skip to contentSkip to conversation

__init and i386 timers

PATCH In review Andries Brouwer 3 participants 3 messages Nov 13, 2004 – Nov 16, 2004

lore
Share & tools
lore
#0 lore raw

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
diff -uprN -X /linux/dontdiff a/arch/i386/kernel/timers/timer.c b/arch/i386/kernel/timers/timer.c
@@ -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
diff -uprN -X /linux/dontdiff a/arch/i386/kernel/timers/timer_cyclone.c b/arch/i386/kernel/timers/timer_cyclone.c
@@ -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
diff -uprN -X /linux/dontdiff a/arch/i386/kernel/timers/timer_hpet.c b/arch/i386/kernel/timers/timer_hpet.c
@@ -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
diff -uprN -X /linux/dontdiff a/arch/i386/kernel/timers/timer_none.c b/arch/i386/kernel/timers/timer_none.c
@@ -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
diff -uprN -X /linux/dontdiff a/arch/i386/kernel/timers/timer_pit.c b/arch/i386/kernel/timers/timer_pit.c
@@ -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
diff -uprN -X /linux/dontdiff a/arch/i386/kernel/timers/timer_pm.c b/arch/i386/kernel/timers/timer_pm.c
@@ -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
diff -uprN -X /linux/dontdiff a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c
@@ -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
diff -uprN -X /linux/dontdiff a/include/asm-i386/timer.h b/include/asm-i386/timer.h
@@ -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
#1 lore raw
Quoted 5 lines · Andries Brouwer

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.

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

#2 lore raw
Quoted 7 lines · john stultz
Quoted 5 lines · Andries Brouwer

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.

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 __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?

I'd second. We already have too much complexity in the time related code.

Tim