Commit 1595f452f3d8daa066bfd3ba4120754bed3329e1
Committed by
Thomas Gleixner
1 parent
b097976e8d
Exists in
master
and in
4 other branches
clockevents: introduce force broadcast notifier
The 64bit SMP bootup is slightly different to the 32bit one. It enables the boot CPU local APIC timer before all CPUs are brought up. Some AMD C1E systems have the C1E feature flag only set in the secondary CPU. Due to the early enable of the boot CPU local APIC timer the APIC timer is registered as a fully functional device. When we detect the wreckage during the bringup of the secondary CPU, we need to force the boot CPU into broadcast mode. Add a new notifier reason and implement the force broadcast in the clock events layer. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Showing 3 changed files with 25 additions and 6 deletions Side-by-side Diff
include/linux/clockchips.h
kernel/time/tick-broadcast.c
... | ... | @@ -217,26 +217,43 @@ |
217 | 217 | bc = tick_broadcast_device.evtdev; |
218 | 218 | |
219 | 219 | /* |
220 | - * Is the device in broadcast mode forever or is it not | |
221 | - * affected by the powerstate ? | |
220 | + * Is the device not affected by the powerstate ? | |
222 | 221 | */ |
223 | - if (!dev || !tick_device_is_functional(dev) || | |
224 | - !(dev->features & CLOCK_EVT_FEAT_C3STOP)) | |
222 | + if (!dev || !(dev->features & CLOCK_EVT_FEAT_C3STOP)) | |
225 | 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 | 243 | if (!cpu_isset(cpu, tick_broadcast_mask)) { |
229 | 244 | cpu_set(cpu, tick_broadcast_mask); |
230 | 245 | if (td->mode == TICKDEV_MODE_PERIODIC) |
231 | 246 | clockevents_set_mode(dev, |
232 | 247 | CLOCK_EVT_MODE_SHUTDOWN); |
233 | 248 | } |
234 | - } else { | |
249 | + break; | |
250 | + case CLOCK_EVT_NOTIFY_BROADCAST_OFF: | |
235 | 251 | if (cpu_isset(cpu, tick_broadcast_mask)) { |
236 | 252 | cpu_clear(cpu, tick_broadcast_mask); |
237 | 253 | if (td->mode == TICKDEV_MODE_PERIODIC) |
238 | 254 | tick_setup_periodic(dev, 0); |
239 | 255 | } |
256 | + break; | |
240 | 257 | } |
241 | 258 | |
242 | 259 | if (cpus_empty(tick_broadcast_mask)) |