aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/time')
-rw-r--r--kernel/time/tick-broadcast.c29
-rw-r--r--kernel/time/tick-common.c1
2 files changed, 24 insertions, 6 deletions
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