diff options
Diffstat (limited to 'arch/mips/mips-boards/generic/time.c')
-rw-r--r-- | arch/mips/mips-boards/generic/time.c | 51 |
1 files changed, 46 insertions, 5 deletions
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c index 3a6f1428b2cb..72a12d931cba 100644 --- a/arch/mips/mips-boards/generic/time.c +++ b/arch/mips/mips-boards/generic/time.c | |||
@@ -61,6 +61,15 @@ static unsigned int display_count = 0; | |||
61 | static unsigned int timer_tick_count=0; | 61 | static unsigned int timer_tick_count=0; |
62 | static int mips_cpu_timer_irq; | 62 | static int mips_cpu_timer_irq; |
63 | 63 | ||
64 | static inline void scroll_display_message(void) | ||
65 | { | ||
66 | if ((timer_tick_count++ % HZ) == 0) { | ||
67 | mips_display_message(&display_string[display_count++]); | ||
68 | if (display_count == MAX_DISPLAY_COUNT) | ||
69 | display_count = 0; | ||
70 | } | ||
71 | } | ||
72 | |||
64 | static void mips_timer_dispatch (struct pt_regs *regs) | 73 | static void mips_timer_dispatch (struct pt_regs *regs) |
65 | { | 74 | { |
66 | do_IRQ (mips_cpu_timer_irq, regs); | 75 | do_IRQ (mips_cpu_timer_irq, regs); |
@@ -68,17 +77,42 @@ static void mips_timer_dispatch (struct pt_regs *regs) | |||
68 | 77 | ||
69 | irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 78 | irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
70 | { | 79 | { |
80 | #ifdef CONFIG_SMP | ||
81 | int cpu = smp_processor_id(); | ||
82 | |||
83 | if (cpu == 0) { | ||
84 | /* | ||
85 | * CPU 0 handles the global timer interrupt job and process accounting | ||
86 | * resets count/compare registers to trigger next timer int. | ||
87 | */ | ||
88 | (void) timer_interrupt(irq, dev_id, regs); | ||
89 | scroll_display_message(); | ||
90 | } | ||
91 | else { | ||
92 | /* Everyone else needs to reset the timer int here as | ||
93 | ll_local_timer_interrupt doesn't */ | ||
94 | /* | ||
95 | * FIXME: need to cope with counter underflow. | ||
96 | * More support needs to be added to kernel/time for | ||
97 | * counter/timer interrupts on multiple CPU's | ||
98 | */ | ||
99 | write_c0_compare (read_c0_count() + (mips_hpt_frequency/HZ)); | ||
100 | /* | ||
101 | * other CPUs should do profiling and process accounting | ||
102 | */ | ||
103 | local_timer_interrupt (irq, dev_id, regs); | ||
104 | } | ||
105 | |||
106 | return IRQ_HANDLED; | ||
107 | #else | ||
71 | irqreturn_t r; | 108 | irqreturn_t r; |
72 | 109 | ||
73 | r = timer_interrupt(irq, dev_id, regs); | 110 | r = timer_interrupt(irq, dev_id, regs); |
74 | 111 | ||
75 | if ((timer_tick_count++ % HZ) == 0) { | 112 | scroll_display_message(); |
76 | mips_display_message(&display_string[display_count++]); | ||
77 | if (display_count == MAX_DISPLAY_COUNT) | ||
78 | display_count = 0; | ||
79 | } | ||
80 | 113 | ||
81 | return r; | 114 | return r; |
115 | #endif | ||
82 | } | 116 | } |
83 | 117 | ||
84 | /* | 118 | /* |
@@ -176,6 +210,13 @@ void __init mips_timer_setup(struct irqaction *irq) | |||
176 | irq->handler = mips_timer_interrupt; /* we use our own handler */ | 210 | irq->handler = mips_timer_interrupt; /* we use our own handler */ |
177 | setup_irq(mips_cpu_timer_irq, irq); | 211 | setup_irq(mips_cpu_timer_irq, irq); |
178 | 212 | ||
213 | #ifdef CONFIG_SMP | ||
214 | /* irq_desc(riptor) is a global resource, when the interrupt overlaps | ||
215 | on seperate cpu's the first one tries to handle the second interrupt. | ||
216 | The effect is that the int remains disabled on the second cpu. | ||
217 | Mark the interrupt with IRQ_PER_CPU to avoid any confusion */ | ||
218 | irq_desc[mips_cpu_timer_irq].status |= IRQ_PER_CPU; | ||
219 | #endif | ||
179 | 220 | ||
180 | /* to generate the first timer interrupt */ | 221 | /* to generate the first timer interrupt */ |
181 | write_c0_compare (read_c0_count() + mips_hpt_frequency/HZ); | 222 | write_c0_compare (read_c0_count() + mips_hpt_frequency/HZ); |