summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorSuresh Siddha <suresh.b.siddha@intel.com>2010-04-22 11:47:51 +0200
committerGreg Kroah-Hartman <gregkh@suse.de>2010-05-26 14:27:07 -0700
commit843447c62b771a9ad12f0e7f4a791804b4cc99f5 (patch)
tree46dff7ba661b3cb7a9abee96d29b7d6d1feac23a /arch
parent0851f4563b9e0770d4b3c071e605cb5e150c6ed3 (diff)
clockevent: Prevent dead lock on clockevents_lock
This is a merge of two mainline commits, intended for stable@kernel.org submission for 2.6.27 kernel. commit f833bab87fca5c3ce13778421b1365845843b976 and commit 918aae42aa9b611a3663b16ae849fdedc67c2292 Changelog of both: Currently clockevents_notify() is called with interrupts enabled at some places and interrupts disabled at some other places. This results in a deadlock in this scenario. cpu A holds clockevents_lock in clockevents_notify() with irqs enabled cpu B waits for clockevents_lock in clockevents_notify() with irqs disabled cpu C doing set_mtrr() which will try to rendezvous of all the cpus. This will result in C and A come to the rendezvous point and waiting for B. B is stuck forever waiting for the spinlock and thus not reaching the rendezvous point. Fix the clockevents code so that clockevents_lock is taken with interrupts disabled and thus avoid the above deadlock. Also call lapic_timer_propagate_broadcast() on the destination cpu so that we avoid calling smp_call_function() in the clockevents notifier chain. This issue left us wondering if we need to change the MTRR rendezvous logic to use stop machine logic (instead of smp_call_function) or add a check in spinlock debug code to see if there are other spinlocks which gets taken under both interrupts enabled/disabled conditions. Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> Cc: "Brown Len" <len.brown@intel.com> Cc: stable@kernel.org LKML-Reference: <1250544899.2709.210.camel@sbs-t61.sc.intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> I got following warning on ia64 box: In function 'acpi_processor_power_verify': 642: warning: passing argument 2 of 'smp_call_function_single' from incompatible pointer type This smp_call_function_single() was introduced by a commit f833bab87fca5c3ce13778421b1365845843b976: The problem is that the lapic_timer_propagate_broadcast() has 2 versions: One is real code that modified in the above commit, and the other is NOP code that used when !ARCH_APICTIMER_STOPS_ON_C3: static void lapic_timer_propagate_broadcast(struct acpi_processor *pr) { } So I got warning because of !ARCH_APICTIMER_STOPS_ON_C3. We really want to do nothing here on !ARCH_APICTIMER_STOPS_ON_C3, so modify lapic_timer_propagate_broadcast() of real version to use smp_call_function_single() in it. Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> Acked-by: Suresh Siddha <suresh.b.siddha@intel.com> Signed-off-by: Len Brown <len.brown@intel.com> Signed-off-by: Thomas Renninger <trenn@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kernel/process.c6
1 files changed, 1 insertions, 5 deletions
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 876e91890777..f459e3ee0473 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -283,16 +283,12 @@ static void c1e_idle(void)
if (!cpu_isset(cpu, c1e_mask)) {
cpu_set(cpu, c1e_mask);
/*
- * Force broadcast so ACPI can not interfere. Needs
- * to run with interrupts enabled as it uses
- * smp_function_call.
+ * Force broadcast so ACPI can not interfere.
*/
- 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);