diff options
Diffstat (limited to 'arch/sparc64/kernel/time.c')
-rw-r--r-- | arch/sparc64/kernel/time.c | 43 |
1 files changed, 18 insertions, 25 deletions
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index d457079118dc..48e1217c1e42 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/profile.h> | 31 | #include <linux/profile.h> |
32 | #include <linux/miscdevice.h> | 32 | #include <linux/miscdevice.h> |
33 | #include <linux/rtc.h> | 33 | #include <linux/rtc.h> |
34 | #include <linux/kernel_stat.h> | ||
34 | 35 | ||
35 | #include <asm/oplib.h> | 36 | #include <asm/oplib.h> |
36 | #include <asm/mostek.h> | 37 | #include <asm/mostek.h> |
@@ -423,12 +424,6 @@ static struct sparc64_tick_ops hbtick_operations __read_mostly = { | |||
423 | .softint_mask = 1UL << 0, | 424 | .softint_mask = 1UL << 0, |
424 | }; | 425 | }; |
425 | 426 | ||
426 | /* timer_interrupt() needs to keep up the real-time clock, | ||
427 | * as well as call the "do_timer()" routine every clocktick | ||
428 | * | ||
429 | * NOTE: On SUN5 systems the ticker interrupt comes in using 2 | ||
430 | * interrupts, one at level14 and one with softint bit 0. | ||
431 | */ | ||
432 | unsigned long timer_tick_offset __read_mostly; | 427 | unsigned long timer_tick_offset __read_mostly; |
433 | 428 | ||
434 | static unsigned long timer_ticks_per_nsec_quotient __read_mostly; | 429 | static unsigned long timer_ticks_per_nsec_quotient __read_mostly; |
@@ -487,18 +482,27 @@ void notify_arch_cmos_timer(void) | |||
487 | mod_timer(&sync_cmos_timer, jiffies + 1); | 482 | mod_timer(&sync_cmos_timer, jiffies + 1); |
488 | } | 483 | } |
489 | 484 | ||
490 | irqreturn_t timer_interrupt(int irq, void *dev_id) | 485 | void timer_interrupt(int irq, struct pt_regs *regs) |
491 | { | 486 | { |
487 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
492 | unsigned long ticks, compare, pstate; | 488 | unsigned long ticks, compare, pstate; |
489 | unsigned long tick_mask = tick_ops->softint_mask; | ||
490 | |||
491 | clear_softint(tick_mask); | ||
492 | |||
493 | irq_enter(); | ||
493 | 494 | ||
494 | write_seqlock(&xtime_lock); | 495 | kstat_this_cpu.irqs[0]++; |
495 | 496 | ||
496 | do { | 497 | do { |
497 | #ifndef CONFIG_SMP | ||
498 | profile_tick(CPU_PROFILING); | 498 | profile_tick(CPU_PROFILING); |
499 | update_process_times(user_mode(get_irq_regs())); | 499 | update_process_times(user_mode(get_irq_regs())); |
500 | #endif | 500 | |
501 | do_timer(1); | 501 | if (smp_processor_id() == boot_cpu_id) { |
502 | write_seqlock(&xtime_lock); | ||
503 | do_timer(1); | ||
504 | write_sequnlock(&xtime_lock); | ||
505 | } | ||
502 | 506 | ||
503 | /* Guarantee that the following sequences execute | 507 | /* Guarantee that the following sequences execute |
504 | * uninterrupted. | 508 | * uninterrupted. |
@@ -515,24 +519,13 @@ irqreturn_t timer_interrupt(int irq, void *dev_id) | |||
515 | __asm__ __volatile__("wrpr %0, 0x0, %%pstate" | 519 | __asm__ __volatile__("wrpr %0, 0x0, %%pstate" |
516 | : /* no outputs */ | 520 | : /* no outputs */ |
517 | : "r" (pstate)); | 521 | : "r" (pstate)); |
518 | } while (time_after_eq(ticks, compare)); | 522 | } while (unlikely(time_after_eq(ticks, compare))); |
519 | 523 | ||
520 | write_sequnlock(&xtime_lock); | 524 | irq_exit(); |
521 | 525 | ||
522 | return IRQ_HANDLED; | 526 | set_irq_regs(old_regs); |
523 | } | 527 | } |
524 | 528 | ||
525 | #ifdef CONFIG_SMP | ||
526 | void timer_tick_interrupt(struct pt_regs *regs) | ||
527 | { | ||
528 | write_seqlock(&xtime_lock); | ||
529 | |||
530 | do_timer(1); | ||
531 | |||
532 | write_sequnlock(&xtime_lock); | ||
533 | } | ||
534 | #endif | ||
535 | |||
536 | /* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */ | 529 | /* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */ |
537 | static void __init kick_start_clock(void) | 530 | static void __init kick_start_clock(void) |
538 | { | 531 | { |