diff options
author | Helge Deller <deller@gmx.de> | 2007-01-03 13:25:37 -0500 |
---|---|---|
committer | Kyle McMartin <kyle@athena.road.mcmartin.ca> | 2007-02-17 01:02:47 -0500 |
commit | 324c7e6545539d2f7736be930d4833deb32b1b95 (patch) | |
tree | 44673470df765ac7832c247ce49e58ed5885a293 /arch/parisc | |
parent | 12df29b64c782133afea8cacc6acdad68a6b7d17 (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')
-rw-r--r-- | arch/parisc/kernel/time.c | 24 |
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 | ||
183 | static int cr16_update_callback(void); | ||
184 | |||
183 | static struct clocksource clocksource_cr16 = { | 185 | static 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 | ||
196 | static 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) { |