|
@@ -267,17 +267,29 @@ static void c1e_idle(void)
|
|
|
|
|
|
if (!cpu_isset(cpu, c1e_mask)) {
|
|
|
cpu_set(cpu, c1e_mask);
|
|
|
- /* Force broadcast so ACPI can not interfere */
|
|
|
+ /*
|
|
|
+ * Force broadcast so ACPI can not interfere. Needs
|
|
|
+ * to run with interrupts enabled as it uses
|
|
|
+ * smp_function_call.
|
|
|
+ */
|
|
|
+ local_irq_enable();
|
|
|
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
|
|
|
&cpu);
|
|
|
printk(KERN_INFO "Switch to broadcast mode on CPU%d\n",
|
|
|
cpu);
|
|
|
+ local_irq_disable();
|
|
|
}
|
|
|
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
|
|
|
+
|
|
|
default_idle();
|
|
|
- local_irq_disable();
|
|
|
- clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
|
|
|
- local_irq_enable();
|
|
|
+
|
|
|
+ /*
|
|
|
+ * The switch back from broadcast mode needs to be
|
|
|
+ * called with interrupts disabled.
|
|
|
+ */
|
|
|
+ local_irq_disable();
|
|
|
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
|
|
|
+ local_irq_enable();
|
|
|
} else
|
|
|
default_idle();
|
|
|
}
|