aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2012-11-07 19:58:54 -0500
committerStephen Warren <swarren@nvidia.com>2012-12-24 11:36:07 -0500
commit7b1f62076bba10786d2118006ae68ac120cd6c56 (patch)
tree9af9f556fc331c77644c2e1c4eafdddad60019b1
parent547046f2f09f1837d39619afbc7a6e35673d7c98 (diff)
time: convert arch_gettimeoffset to a pointer
Currently, whenever CONFIG_ARCH_USES_GETTIMEOFFSET is enabled, each arch core provides a single implementation of arch_gettimeoffset(). In many cases, different sub-architectures, different machines, or different timer providers exist, and so the arch ends up implementing arch_gettimeoffset() as a call-through-pointer anyway. Examples are ARM, Cris, M68K, and it's arguable that the remaining architectures, M32R and Blackfin, should be doing this anyway. Modify arch_gettimeoffset so that it itself is a function pointer, which the arch initializes. This will allow later changes to move the initialization of this function into individual machine support or timer drivers. This is particularly useful for code in drivers/clocksource which should rely on an arch-independant mechanism to register their implementation of arch_gettimeoffset(). This patch also converts the Cris architecture to set arch_gettimeoffset directly to the final implementation in time_init(), because Cris already had separate time_init() functions per sub-architecture. M68K and ARM are converted to set arch_gettimeoffset to the final implementation in later patches, because they already have function pointers in place for this purpose. Cc: Russell King <linux@arm.linux.org.uk> Cc: Mike Frysinger <vapier@gentoo.org> Cc: Mikael Starvik <starvik@axis.com> Cc: Hirokazu Takata <takata@linux-m32r.org> Cc: Thomas Gleixner <tglx@linutronix.de> Acked-by: Geert Uytterhoeven <geert@linux-m68k.org> Acked-by: Jesper Nilsson <jesper.nilsson@axis.com> Acked-by: John Stultz <johnstul@us.ibm.com> Signed-off-by: Stephen Warren <swarren@nvidia.com>
-rw-r--r--arch/arm/kernel/time.c6
-rw-r--r--arch/blackfin/kernel/time.c6
-rw-r--r--arch/cris/arch-v10/kernel/time.c6
-rw-r--r--arch/cris/kernel/time.c11
-rw-r--r--arch/m32r/kernel/time.c4
-rw-r--r--arch/m68k/kernel/time.c16
-rw-r--r--include/linux/time.h4
-rw-r--r--kernel/time/timekeeping.c26
8 files changed, 48 insertions, 31 deletions
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 09be0c3c9069..b0190b41cb33 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -70,7 +70,7 @@ EXPORT_SYMBOL(profile_pc);
70#endif 70#endif
71 71
72#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET 72#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
73u32 arch_gettimeoffset(void) 73static u32 arm_gettimeoffset(void)
74{ 74{
75 if (system_timer->offset != NULL) 75 if (system_timer->offset != NULL)
76 return system_timer->offset() * 1000; 76 return system_timer->offset() * 1000;
@@ -164,6 +164,10 @@ device_initcall(timer_init_syscore_ops);
164 164
165void __init time_init(void) 165void __init time_init(void)
166{ 166{
167#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
168 arch_gettimeoffset = arm_gettimeoffset;
169#endif
170
167 system_timer = machine_desc->timer; 171 system_timer = machine_desc->timer;
168 system_timer->init(); 172 system_timer->init();
169 sched_clock_postinit(); 173 sched_clock_postinit();
diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c
index 2310b249675f..3126b920a4a5 100644
--- a/arch/blackfin/kernel/time.c
+++ b/arch/blackfin/kernel/time.c
@@ -85,7 +85,7 @@ time_sched_init(irqreturn_t(*timer_routine) (int, void *))
85/* 85/*
86 * Should return useconds since last timer tick 86 * Should return useconds since last timer tick
87 */ 87 */
88u32 arch_gettimeoffset(void) 88static u32 blackfin_gettimeoffset(void)
89{ 89{
90 unsigned long offset; 90 unsigned long offset;
91 unsigned long clocks_per_jiffy; 91 unsigned long clocks_per_jiffy;
@@ -141,6 +141,10 @@ void read_persistent_clock(struct timespec *ts)
141 141
142void __init time_init(void) 142void __init time_init(void)
143{ 143{
144#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
145 arch_gettimeoffset = blackfin_gettimeoffset;
146#endif
147
144#ifdef CONFIG_RTC_DRV_BFIN 148#ifdef CONFIG_RTC_DRV_BFIN
145 /* [#2663] hack to filter junk RTC values that would cause 149 /* [#2663] hack to filter junk RTC values that would cause
146 * userspace to have to deal with time values greater than 150 * userspace to have to deal with time values greater than
diff --git a/arch/cris/arch-v10/kernel/time.c b/arch/cris/arch-v10/kernel/time.c
index 162892f24a20..fce7c541d70d 100644
--- a/arch/cris/arch-v10/kernel/time.c
+++ b/arch/cris/arch-v10/kernel/time.c
@@ -55,9 +55,9 @@ unsigned long get_ns_in_jiffie(void)
55 return ns; 55 return ns;
56} 56}
57 57
58unsigned long do_slow_gettimeoffset(void) 58static u32 cris_v10_gettimeoffset(void)
59{ 59{
60 unsigned long count; 60 u32 count;
61 61
62 /* The timer interrupt comes from Etrax timer 0. In order to get 62 /* The timer interrupt comes from Etrax timer 0. In order to get
63 * better precision, we check the current value. It might have 63 * better precision, we check the current value. It might have
@@ -191,6 +191,8 @@ static struct irqaction irq2 = {
191void __init 191void __init
192time_init(void) 192time_init(void)
193{ 193{
194 arch_gettimeoffset = cris_v10_gettimeoffset;
195
194 /* probe for the RTC and read it if it exists 196 /* probe for the RTC and read it if it exists
195 * Before the RTC can be probed the loops_per_usec variable needs 197 * Before the RTC can be probed the loops_per_usec variable needs
196 * to be initialized to make usleep work. A better value for 198 * to be initialized to make usleep work. A better value for
diff --git a/arch/cris/kernel/time.c b/arch/cris/kernel/time.c
index b063c9217b5c..fe6acdabbc8d 100644
--- a/arch/cris/kernel/time.c
+++ b/arch/cris/kernel/time.c
@@ -39,17 +39,6 @@
39extern unsigned long loops_per_jiffy; /* init/main.c */ 39extern unsigned long loops_per_jiffy; /* init/main.c */
40unsigned long loops_per_usec; 40unsigned long loops_per_usec;
41 41
42
43#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
44extern unsigned long do_slow_gettimeoffset(void);
45static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
46
47u32 arch_gettimeoffset(void)
48{
49 return do_gettimeoffset();
50}
51#endif
52
53int set_rtc_mmss(unsigned long nowtime) 42int set_rtc_mmss(unsigned long nowtime)
54{ 43{
55 D(printk(KERN_DEBUG "set_rtc_mmss(%lu)\n", nowtime)); 44 D(printk(KERN_DEBUG "set_rtc_mmss(%lu)\n", nowtime));
diff --git a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c
index 84dd04048db9..1a15f81ea1bd 100644
--- a/arch/m32r/kernel/time.c
+++ b/arch/m32r/kernel/time.c
@@ -57,7 +57,7 @@ extern void smp_local_timer_interrupt(void);
57 57
58static unsigned long latch; 58static unsigned long latch;
59 59
60u32 arch_gettimeoffset(void) 60static u32 m32r_gettimeoffset(void)
61{ 61{
62 unsigned long elapsed_time = 0; /* [us] */ 62 unsigned long elapsed_time = 0; /* [us] */
63 63
@@ -165,6 +165,8 @@ void read_persistent_clock(struct timespec *ts)
165 165
166void __init time_init(void) 166void __init time_init(void)
167{ 167{
168 arch_gettimeoffset = m32r_gettimeoffset;
169
168#if defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_XNUX2) \ 170#if defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_XNUX2) \
169 || defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_M32700) \ 171 || defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_M32700) \
170 || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104) 172 || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104)
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
index 5d0bcaad2e55..c2994c8c30d5 100644
--- a/arch/m68k/kernel/time.c
+++ b/arch/m68k/kernel/time.c
@@ -80,14 +80,9 @@ void read_persistent_clock(struct timespec *ts)
80 } 80 }
81} 81}
82 82
83void __init time_init(void)
84{
85 mach_sched_init(timer_interrupt);
86}
87
88#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET 83#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
89 84
90u32 arch_gettimeoffset(void) 85static u32 m68k_gettimeoffset(void)
91{ 86{
92 return mach_gettimeoffset() * 1000; 87 return mach_gettimeoffset() * 1000;
93} 88}
@@ -106,3 +101,12 @@ static int __init rtc_init(void)
106module_init(rtc_init); 101module_init(rtc_init);
107 102
108#endif /* CONFIG_ARCH_USES_GETTIMEOFFSET */ 103#endif /* CONFIG_ARCH_USES_GETTIMEOFFSET */
104
105void __init time_init(void)
106{
107#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
108 arch_gettimeoffset = m68k_gettimeoffset;
109#endif
110
111 mach_sched_init(timer_interrupt);
112}
diff --git a/include/linux/time.h b/include/linux/time.h
index 4d358e9d10f1..05e32a72103c 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -142,9 +142,7 @@ void timekeeping_inject_sleeptime(struct timespec *delta);
142 * finer then tick granular time. 142 * finer then tick granular time.
143 */ 143 */
144#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET 144#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
145extern u32 arch_gettimeoffset(void); 145extern u32 (*arch_gettimeoffset)(void);
146#else
147static inline u32 arch_gettimeoffset(void) { return 0; }
148#endif 146#endif
149 147
150extern void do_gettimeofday(struct timeval *tv); 148extern void do_gettimeofday(struct timeval *tv);
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index cbc6acb0db3f..8ed934601587 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -135,6 +135,20 @@ static void tk_setup_internals(struct timekeeper *tk, struct clocksource *clock)
135} 135}
136 136
137/* Timekeeper helper functions. */ 137/* Timekeeper helper functions. */
138
139#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
140u32 (*arch_gettimeoffset)(void);
141
142u32 get_arch_timeoffset(void)
143{
144 if (likely(arch_gettimeoffset))
145 return arch_gettimeoffset();
146 return 0;
147}
148#else
149static inline u32 get_arch_timeoffset(void) { return 0; }
150#endif
151
138static inline s64 timekeeping_get_ns(struct timekeeper *tk) 152static inline s64 timekeeping_get_ns(struct timekeeper *tk)
139{ 153{
140 cycle_t cycle_now, cycle_delta; 154 cycle_t cycle_now, cycle_delta;
@@ -151,8 +165,8 @@ static inline s64 timekeeping_get_ns(struct timekeeper *tk)
151 nsec = cycle_delta * tk->mult + tk->xtime_nsec; 165 nsec = cycle_delta * tk->mult + tk->xtime_nsec;
152 nsec >>= tk->shift; 166 nsec >>= tk->shift;
153 167
154 /* If arch requires, add in gettimeoffset() */ 168 /* If arch requires, add in get_arch_timeoffset() */
155 return nsec + arch_gettimeoffset(); 169 return nsec + get_arch_timeoffset();
156} 170}
157 171
158static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk) 172static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk)
@@ -171,8 +185,8 @@ static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk)
171 /* convert delta to nanoseconds. */ 185 /* convert delta to nanoseconds. */
172 nsec = clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift); 186 nsec = clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift);
173 187
174 /* If arch requires, add in gettimeoffset() */ 188 /* If arch requires, add in get_arch_timeoffset() */
175 return nsec + arch_gettimeoffset(); 189 return nsec + get_arch_timeoffset();
176} 190}
177 191
178static RAW_NOTIFIER_HEAD(pvclock_gtod_chain); 192static RAW_NOTIFIER_HEAD(pvclock_gtod_chain);
@@ -254,8 +268,8 @@ static void timekeeping_forward_now(struct timekeeper *tk)
254 268
255 tk->xtime_nsec += cycle_delta * tk->mult; 269 tk->xtime_nsec += cycle_delta * tk->mult;
256 270
257 /* If arch requires, add in gettimeoffset() */ 271 /* If arch requires, add in get_arch_timeoffset() */
258 tk->xtime_nsec += (u64)arch_gettimeoffset() << tk->shift; 272 tk->xtime_nsec += (u64)get_arch_timeoffset() << tk->shift;
259 273
260 tk_normalize_xtime(tk); 274 tk_normalize_xtime(tk);
261 275