aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/time.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2007-02-16 04:28:04 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-16 11:13:59 -0500
commite9e2cdb412412326c4827fc78ba27f410d837e6e (patch)
treecd4ca03e6bdc3691619024492fb9414427b2f813 /arch/i386/kernel/time.c
parent79bf2bb335b85db25d27421c798595a2fa2a0e82 (diff)
[PATCH] clockevents: i386 drivers
Add clockevent drivers for i386: lapic (local) and PIT/HPET (global). Update the timer IRQ to call into the PIT/HPET driver's event handler and the lapic-timer IRQ to call into the lapic clockevent driver. The assignement of timer functionality is delegated to the core framework code and replaces the compile and runtime evalution in do_timer_interrupt_hook() Use the clockevents broadcast support and implement the lapic_broadcast function for ACPI. No changes to existing functionality. [ kdump fix from Vivek Goyal <vgoyal@in.ibm.com> ] [ fixes based on review feedback from Arjan van de Ven <arjan@infradead.org> ] Cleanups-from: Adrian Bunk <bunk@stusta.de> Build-fixes-from: Andrew Morton <akpm@osdl.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@elte.hu> Cc: john stultz <johnstul@us.ibm.com> Cc: Roman Zippel <zippel@linux-m68k.org> Cc: Andi Kleen <ak@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/i386/kernel/time.c')
-rw-r--r--arch/i386/kernel/time.c70
1 files changed, 3 insertions, 67 deletions
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index 044c17572ee..a5350059557 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -159,15 +159,6 @@ EXPORT_SYMBOL(profile_pc);
159 */ 159 */
160irqreturn_t timer_interrupt(int irq, void *dev_id) 160irqreturn_t timer_interrupt(int irq, void *dev_id)
161{ 161{
162 /*
163 * Here we are in the timer irq handler. We just have irqs locally
164 * disabled but we don't know if the timer_bh is running on the other
165 * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
166 * the irq version of write_lock because as just said we have irq
167 * locally disabled. -arca
168 */
169 write_seqlock(&xtime_lock);
170
171#ifdef CONFIG_X86_IO_APIC 162#ifdef CONFIG_X86_IO_APIC
172 if (timer_ack) { 163 if (timer_ack) {
173 /* 164 /*
@@ -186,7 +177,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id)
186 177
187 do_timer_interrupt_hook(); 178 do_timer_interrupt_hook();
188 179
189
190 if (MCA_bus) { 180 if (MCA_bus) {
191 /* The PS/2 uses level-triggered interrupts. You can't 181 /* The PS/2 uses level-triggered interrupts. You can't
192 turn them off, nor would you want to (any attempt to 182 turn them off, nor would you want to (any attempt to
@@ -201,13 +191,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id)
201 outb_p( irq_v|0x80, 0x61 ); /* reset the IRQ */ 191 outb_p( irq_v|0x80, 0x61 ); /* reset the IRQ */
202 } 192 }
203 193
204 write_sequnlock(&xtime_lock);
205
206#ifdef CONFIG_X86_LOCAL_APIC
207 if (using_apic_timer)
208 smp_send_timer_broadcast_ipi();
209#endif
210
211 return IRQ_HANDLED; 194 return IRQ_HANDLED;
212} 195}
213 196
@@ -277,63 +260,16 @@ void notify_arch_cmos_timer(void)
277 mod_timer(&sync_cmos_timer, jiffies + 1); 260 mod_timer(&sync_cmos_timer, jiffies + 1);
278} 261}
279 262
280static int timer_resume(struct sys_device *dev)
281{
282#ifdef CONFIG_HPET_TIMER
283 if (is_hpet_enabled())
284 hpet_reenable();
285#endif
286 setup_pit_timer();
287 touch_softlockup_watchdog();
288 return 0;
289}
290
291static struct sysdev_class timer_sysclass = {
292 .resume = timer_resume,
293 set_kset_name("timer"),
294};
295
296
297/* XXX this driverfs stuff should probably go elsewhere later -john */
298static struct sys_device device_timer = {
299 .id = 0,
300 .cls = &timer_sysclass,
301};
302
303static int time_init_device(void)
304{
305 int error = sysdev_class_register(&timer_sysclass);
306 if (!error)
307 error = sysdev_register(&device_timer);
308 return error;
309}
310
311device_initcall(time_init_device);
312
313#ifdef CONFIG_HPET_TIMER
314extern void (*late_time_init)(void); 263extern void (*late_time_init)(void);
315/* Duplicate of time_init() below, with hpet_enable part added */ 264/* Duplicate of time_init() below, with hpet_enable part added */
316static void __init hpet_time_init(void) 265static void __init hpet_time_init(void)
317{ 266{
318 if ((hpet_enable() >= 0) && hpet_use_timer) { 267 if (!hpet_enable())
319 printk("Using HPET for base-timer\n"); 268 setup_pit_timer();
320 }
321
322 do_time_init(); 269 do_time_init();
323} 270}
324#endif
325 271
326void __init time_init(void) 272void __init time_init(void)
327{ 273{
328#ifdef CONFIG_HPET_TIMER 274 late_time_init = hpet_time_init;
329 if (is_hpet_capable()) {
330 /*
331 * HPET initialization needs to do memory-mapped io. So, let
332 * us do a late initialization after mem_init().
333 */
334 late_time_init = hpet_time_init;
335 return;
336 }
337#endif
338 do_time_init();
339} 275}