aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc/kernel
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2007-01-03 13:25:37 -0500
committerKyle McMartin <kyle@athena.road.mcmartin.ca>2007-02-17 01:02:47 -0500
commit324c7e6545539d2f7736be930d4833deb32b1b95 (patch)
tree44673470df765ac7832c247ce49e58ed5885a293 /arch/parisc/kernel
parent12df29b64c782133afea8cacc6acdad68a6b7d17 (diff)
[PARISC] disable cr16 clocksource when multiple CPUs are online
Signed-off-by: Helge Deller <deller@gmx.de> Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
Diffstat (limited to 'arch/parisc/kernel')
-rw-r--r--arch/parisc/kernel/time.c24
1 files changed, 19 insertions, 5 deletions
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index e47e27cea42e..c33b6e0f7c47 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -99,7 +99,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id)
99 * cycles after the IT fires. But it's arbitrary how much time passes 99 * cycles after the IT fires. But it's arbitrary how much time passes
100 * before we call it "late". I've picked one second. 100 * before we call it "late". I've picked one second.
101 */ 101 */
102 if (ticks_elapsed > HZ) { 102 if (unlikely(ticks_elapsed > HZ)) {
103 /* Scenario 3: very long delay? bad in any case */ 103 /* Scenario 3: very long delay? bad in any case */
104 printk (KERN_CRIT "timer_interrupt(CPU %d): delayed!" 104 printk (KERN_CRIT "timer_interrupt(CPU %d): delayed!"
105 " cycles %lX rem %lX " 105 " cycles %lX rem %lX "
@@ -180,6 +180,8 @@ static cycle_t read_cr16(void)
180 return get_cycles(); 180 return get_cycles();
181} 181}
182 182
183static int cr16_update_callback(void);
184
183static struct clocksource clocksource_cr16 = { 185static struct clocksource clocksource_cr16 = {
184 .name = "cr16", 186 .name = "cr16",
185 .rating = 300, 187 .rating = 300,
@@ -187,9 +189,25 @@ static struct clocksource clocksource_cr16 = {
187 .mask = CLOCKSOURCE_MASK(BITS_PER_LONG), 189 .mask = CLOCKSOURCE_MASK(BITS_PER_LONG),
188 .mult = 0, /* to be set */ 190 .mult = 0, /* to be set */
189 .shift = 22, 191 .shift = 22,
192 .update_callback = cr16_update_callback,
190 .is_continuous = 1, 193 .is_continuous = 1,
191}; 194};
192 195
196static int cr16_update_callback(void)
197{
198 int change = 0;
199
200 /* since the cr16 cycle counters are not syncronized across CPUs,
201 we'll check if we should switch to a safe clocksource: */
202 if (clocksource_cr16.rating != 0 && num_online_cpus() > 1) {
203 clocksource_cr16.rating = 0;
204 clocksource_reselect();
205 change = 1;
206 }
207
208 return change;
209}
210
193 211
194/* 212/*
195 * XXX: We can do better than this. 213 * XXX: We can do better than this.
@@ -225,10 +243,6 @@ void __init time_init(void)
225 current_cr16_khz = PAGE0->mem_10msec/10; /* kHz */ 243 current_cr16_khz = PAGE0->mem_10msec/10; /* kHz */
226 clocksource_cr16.mult = clocksource_khz2mult(current_cr16_khz, 244 clocksource_cr16.mult = clocksource_khz2mult(current_cr16_khz,
227 clocksource_cr16.shift); 245 clocksource_cr16.shift);
228 /* lower the rating if we already know its unstable: */
229 if (num_online_cpus()>1)
230 clocksource_cr16.rating = 200;
231
232 clocksource_register(&clocksource_cr16); 246 clocksource_register(&clocksource_cr16);
233 247
234 if (pdc_tod_read(&tod_data) == 0) { 248 if (pdc_tod_read(&tod_data) == 0) {