aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-09-19 19:16:50 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-09-19 19:16:50 -0400
commit902f2ac9da7975a5a04fc835860f2a7096c481d3 (patch)
tree9197a23f5a94ed7e0987e40e8191a3652df10263
parent06d4a22be3af824cfcbf53ac84d95bd700a949c2 (diff)
parent2344abbcbdb82140050e8be29d3d55e4f6fe860b (diff)
Merge branch 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: clockevents: make device shutdown robust clocksource, acpi_pm.c: fix check for monotonicity clockevents: remove WARN_ON which was used to gather information
-rw-r--r--drivers/clocksource/acpi_pm.c21
-rw-r--r--kernel/time/clockevents.c12
-rw-r--r--kernel/time/tick-broadcast.c9
-rw-r--r--kernel/time/tick-common.c4
-rw-r--r--kernel/time/tick-internal.h2
5 files changed, 29 insertions, 19 deletions
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c
index 4eee533f3f4a..71d2ac4e3f46 100644
--- a/drivers/clocksource/acpi_pm.c
+++ b/drivers/clocksource/acpi_pm.c
@@ -178,11 +178,13 @@ static int verify_pmtmr_rate(void)
178 178
179/* Number of monotonicity checks to perform during initialization */ 179/* Number of monotonicity checks to perform during initialization */
180#define ACPI_PM_MONOTONICITY_CHECKS 10 180#define ACPI_PM_MONOTONICITY_CHECKS 10
181/* Number of reads we try to get two different values */
182#define ACPI_PM_READ_CHECKS 10000
181 183
182static int __init init_acpi_pm_clocksource(void) 184static int __init init_acpi_pm_clocksource(void)
183{ 185{
184 cycle_t value1, value2; 186 cycle_t value1, value2;
185 unsigned int i, j, good = 0; 187 unsigned int i, j = 0;
186 188
187 if (!pmtmr_ioport) 189 if (!pmtmr_ioport)
188 return -ENODEV; 190 return -ENODEV;
@@ -192,29 +194,26 @@ static int __init init_acpi_pm_clocksource(void)
192 194
193 /* "verify" this timing source: */ 195 /* "verify" this timing source: */
194 for (j = 0; j < ACPI_PM_MONOTONICITY_CHECKS; j++) { 196 for (j = 0; j < ACPI_PM_MONOTONICITY_CHECKS; j++) {
197 udelay(100 * j);
195 value1 = clocksource_acpi_pm.read(); 198 value1 = clocksource_acpi_pm.read();
196 for (i = 0; i < 10000; i++) { 199 for (i = 0; i < ACPI_PM_READ_CHECKS; i++) {
197 value2 = clocksource_acpi_pm.read(); 200 value2 = clocksource_acpi_pm.read();
198 if (value2 == value1) 201 if (value2 == value1)
199 continue; 202 continue;
200 if (value2 > value1) 203 if (value2 > value1)
201 good++;
202 break; 204 break;
203 if ((value2 < value1) && ((value2) < 0xFFF)) 205 if ((value2 < value1) && ((value2) < 0xFFF))
204 good++;
205 break; 206 break;
206 printk(KERN_INFO "PM-Timer had inconsistent results:" 207 printk(KERN_INFO "PM-Timer had inconsistent results:"
207 " 0x%#llx, 0x%#llx - aborting.\n", 208 " 0x%#llx, 0x%#llx - aborting.\n",
208 value1, value2); 209 value1, value2);
209 return -EINVAL; 210 return -EINVAL;
210 } 211 }
211 udelay(300 * i); 212 if (i == ACPI_PM_READ_CHECKS) {
212 } 213 printk(KERN_INFO "PM-Timer failed consistency check "
213 214 " (0x%#llx) - aborting.\n", value1);
214 if (good != ACPI_PM_MONOTONICITY_CHECKS) { 215 return -ENODEV;
215 printk(KERN_INFO "PM-Timer failed consistency check " 216 }
216 " (0x%#llx) - aborting.\n", value1);
217 return -ENODEV;
218 } 217 }
219 218
220 if (verify_pmtmr_rate() != 0) 219 if (verify_pmtmr_rate() != 0)
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c
index 1876b526c778..f8d968063cea 100644
--- a/kernel/time/clockevents.c
+++ b/kernel/time/clockevents.c
@@ -72,6 +72,16 @@ void clockevents_set_mode(struct clock_event_device *dev,
72} 72}
73 73
74/** 74/**
75 * clockevents_shutdown - shutdown the device and clear next_event
76 * @dev: device to shutdown
77 */
78void clockevents_shutdown(struct clock_event_device *dev)
79{
80 clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN);
81 dev->next_event.tv64 = KTIME_MAX;
82}
83
84/**
75 * clockevents_program_event - Reprogram the clock event device. 85 * clockevents_program_event - Reprogram the clock event device.
76 * @expires: absolute expiry time (monotonic clock) 86 * @expires: absolute expiry time (monotonic clock)
77 * 87 *
@@ -206,7 +216,7 @@ void clockevents_exchange_device(struct clock_event_device *old,
206 216
207 if (new) { 217 if (new) {
208 BUG_ON(new->mode != CLOCK_EVT_MODE_UNUSED); 218 BUG_ON(new->mode != CLOCK_EVT_MODE_UNUSED);
209 clockevents_set_mode(new, CLOCK_EVT_MODE_SHUTDOWN); 219 clockevents_shutdown(new);
210 } 220 }
211 local_irq_restore(flags); 221 local_irq_restore(flags);
212} 222}
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index 2f5a38294bf9..f1f3eee28113 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -236,8 +236,7 @@ static void tick_do_broadcast_on_off(void *why)
236 if (!cpu_isset(cpu, tick_broadcast_mask)) { 236 if (!cpu_isset(cpu, tick_broadcast_mask)) {
237 cpu_set(cpu, tick_broadcast_mask); 237 cpu_set(cpu, tick_broadcast_mask);
238 if (td->mode == TICKDEV_MODE_PERIODIC) 238 if (td->mode == TICKDEV_MODE_PERIODIC)
239 clockevents_set_mode(dev, 239 clockevents_shutdown(dev);
240 CLOCK_EVT_MODE_SHUTDOWN);
241 } 240 }
242 if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_FORCE) 241 if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_FORCE)
243 tick_broadcast_force = 1; 242 tick_broadcast_force = 1;
@@ -254,7 +253,7 @@ static void tick_do_broadcast_on_off(void *why)
254 253
255 if (cpus_empty(tick_broadcast_mask)) { 254 if (cpus_empty(tick_broadcast_mask)) {
256 if (!bc_stopped) 255 if (!bc_stopped)
257 clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN); 256 clockevents_shutdown(bc);
258 } else if (bc_stopped) { 257 } else if (bc_stopped) {
259 if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) 258 if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC)
260 tick_broadcast_start_periodic(bc); 259 tick_broadcast_start_periodic(bc);
@@ -306,7 +305,7 @@ void tick_shutdown_broadcast(unsigned int *cpup)
306 305
307 if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) { 306 if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) {
308 if (bc && cpus_empty(tick_broadcast_mask)) 307 if (bc && cpus_empty(tick_broadcast_mask))
309 clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN); 308 clockevents_shutdown(bc);
310 } 309 }
311 310
312 spin_unlock_irqrestore(&tick_broadcast_lock, flags); 311 spin_unlock_irqrestore(&tick_broadcast_lock, flags);
@@ -321,7 +320,7 @@ void tick_suspend_broadcast(void)
321 320
322 bc = tick_broadcast_device.evtdev; 321 bc = tick_broadcast_device.evtdev;
323 if (bc) 322 if (bc)
324 clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN); 323 clockevents_shutdown(bc);
325 324
326 spin_unlock_irqrestore(&tick_broadcast_lock, flags); 325 spin_unlock_irqrestore(&tick_broadcast_lock, flags);
327} 326}
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index c4777193d567..019315ebf9de 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -249,7 +249,7 @@ static int tick_check_new_device(struct clock_event_device *newdev)
249 * not give it back to the clockevents layer ! 249 * not give it back to the clockevents layer !
250 */ 250 */
251 if (tick_is_broadcast_device(curdev)) { 251 if (tick_is_broadcast_device(curdev)) {
252 clockevents_set_mode(curdev, CLOCK_EVT_MODE_SHUTDOWN); 252 clockevents_shutdown(curdev);
253 curdev = NULL; 253 curdev = NULL;
254 } 254 }
255 clockevents_exchange_device(curdev, newdev); 255 clockevents_exchange_device(curdev, newdev);
@@ -311,7 +311,7 @@ static void tick_suspend(void)
311 unsigned long flags; 311 unsigned long flags;
312 312
313 spin_lock_irqsave(&tick_device_lock, flags); 313 spin_lock_irqsave(&tick_device_lock, flags);
314 clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_SHUTDOWN); 314 clockevents_shutdown(td->evtdev);
315 spin_unlock_irqrestore(&tick_device_lock, flags); 315 spin_unlock_irqrestore(&tick_device_lock, flags);
316} 316}
317 317
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h
index 0ffc2918ea6f..6e9db9734aa6 100644
--- a/kernel/time/tick-internal.h
+++ b/kernel/time/tick-internal.h
@@ -10,6 +10,8 @@ extern int tick_do_timer_cpu __read_mostly;
10extern void tick_setup_periodic(struct clock_event_device *dev, int broadcast); 10extern void tick_setup_periodic(struct clock_event_device *dev, int broadcast);
11extern void tick_handle_periodic(struct clock_event_device *dev); 11extern void tick_handle_periodic(struct clock_event_device *dev);
12 12
13extern void clockevents_shutdown(struct clock_event_device *dev);
14
13/* 15/*
14 * NO_HZ / high resolution timer shared code 16 * NO_HZ / high resolution timer shared code
15 */ 17 */