diff options
-rw-r--r-- | include/linux/clockchips.h | 1 | ||||
-rw-r--r-- | kernel/time/tick-broadcast.c | 29 | ||||
-rw-r--r-- | kernel/time/tick-common.c | 1 |
3 files changed, 25 insertions, 6 deletions
diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h index d2ddea926895..c33b0dc28e4d 100644 --- a/include/linux/clockchips.h +++ b/include/linux/clockchips.h | |||
@@ -31,6 +31,7 @@ enum clock_event_nofitiers { | |||
31 | CLOCK_EVT_NOTIFY_ADD, | 31 | CLOCK_EVT_NOTIFY_ADD, |
32 | CLOCK_EVT_NOTIFY_BROADCAST_ON, | 32 | CLOCK_EVT_NOTIFY_BROADCAST_ON, |
33 | CLOCK_EVT_NOTIFY_BROADCAST_OFF, | 33 | CLOCK_EVT_NOTIFY_BROADCAST_OFF, |
34 | CLOCK_EVT_NOTIFY_BROADCAST_FORCE, | ||
34 | CLOCK_EVT_NOTIFY_BROADCAST_ENTER, | 35 | CLOCK_EVT_NOTIFY_BROADCAST_ENTER, |
35 | CLOCK_EVT_NOTIFY_BROADCAST_EXIT, | 36 | CLOCK_EVT_NOTIFY_BROADCAST_EXIT, |
36 | CLOCK_EVT_NOTIFY_SUSPEND, | 37 | CLOCK_EVT_NOTIFY_SUSPEND, |
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index 298bc7c6f09f..fc3fc79b3d59 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c | |||
@@ -217,26 +217,43 @@ static void tick_do_broadcast_on_off(void *why) | |||
217 | bc = tick_broadcast_device.evtdev; | 217 | bc = tick_broadcast_device.evtdev; |
218 | 218 | ||
219 | /* | 219 | /* |
220 | * Is the device in broadcast mode forever or is it not | 220 | * Is the device not affected by the powerstate ? |
221 | * affected by the powerstate ? | ||
222 | */ | 221 | */ |
223 | if (!dev || !tick_device_is_functional(dev) || | 222 | if (!dev || !(dev->features & CLOCK_EVT_FEAT_C3STOP)) |
224 | !(dev->features & CLOCK_EVT_FEAT_C3STOP)) | ||
225 | goto out; | 223 | goto out; |
226 | 224 | ||
227 | if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_ON) { | 225 | /* |
226 | * Defect device ? | ||
227 | */ | ||
228 | if (!tick_device_is_functional(dev)) { | ||
229 | /* | ||
230 | * AMD C1E wreckage fixup: | ||
231 | * | ||
232 | * Device was registered functional in the first | ||
233 | * place. Now the secondary CPU detected the C1E | ||
234 | * misfeature and notifies us to fix it up | ||
235 | */ | ||
236 | if (*reason != CLOCK_EVT_NOTIFY_BROADCAST_FORCE) | ||
237 | goto out; | ||
238 | } | ||
239 | |||
240 | switch (*reason) { | ||
241 | case CLOCK_EVT_NOTIFY_BROADCAST_ON: | ||
242 | case CLOCK_EVT_NOTIFY_BROADCAST_FORCE: | ||
228 | if (!cpu_isset(cpu, tick_broadcast_mask)) { | 243 | if (!cpu_isset(cpu, tick_broadcast_mask)) { |
229 | cpu_set(cpu, tick_broadcast_mask); | 244 | cpu_set(cpu, tick_broadcast_mask); |
230 | if (td->mode == TICKDEV_MODE_PERIODIC) | 245 | if (td->mode == TICKDEV_MODE_PERIODIC) |
231 | clockevents_set_mode(dev, | 246 | clockevents_set_mode(dev, |
232 | CLOCK_EVT_MODE_SHUTDOWN); | 247 | CLOCK_EVT_MODE_SHUTDOWN); |
233 | } | 248 | } |
234 | } else { | 249 | break; |
250 | case CLOCK_EVT_NOTIFY_BROADCAST_OFF: | ||
235 | if (cpu_isset(cpu, tick_broadcast_mask)) { | 251 | if (cpu_isset(cpu, tick_broadcast_mask)) { |
236 | cpu_clear(cpu, tick_broadcast_mask); | 252 | cpu_clear(cpu, tick_broadcast_mask); |
237 | if (td->mode == TICKDEV_MODE_PERIODIC) | 253 | if (td->mode == TICKDEV_MODE_PERIODIC) |
238 | tick_setup_periodic(dev, 0); | 254 | tick_setup_periodic(dev, 0); |
239 | } | 255 | } |
256 | break; | ||
240 | } | 257 | } |
241 | 258 | ||
242 | if (cpus_empty(tick_broadcast_mask)) | 259 | if (cpus_empty(tick_broadcast_mask)) |
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index 3f3ae3907830..1bea399a9ef0 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c | |||
@@ -345,6 +345,7 @@ static int tick_notify(struct notifier_block *nb, unsigned long reason, | |||
345 | 345 | ||
346 | case CLOCK_EVT_NOTIFY_BROADCAST_ON: | 346 | case CLOCK_EVT_NOTIFY_BROADCAST_ON: |
347 | case CLOCK_EVT_NOTIFY_BROADCAST_OFF: | 347 | case CLOCK_EVT_NOTIFY_BROADCAST_OFF: |
348 | case CLOCK_EVT_NOTIFY_BROADCAST_FORCE: | ||
348 | tick_broadcast_on_off(reason, dev); | 349 | tick_broadcast_on_off(reason, dev); |
349 | break; | 350 | break; |
350 | 351 | ||