mirror of
https://abf.rosa.ru/djam/kernel-xen.git
synced 2025-02-23 07:42:46 +00:00
103 lines
3.4 KiB
Diff
103 lines
3.4 KiB
Diff
![]() |
From: Suresh Siddha <suresh.b.siddha@intel.com>
|
||
|
Subject: x86: Remove local_irq_enable()/local_irq_disable() in fixup_irqs()
|
||
|
References: bnc#558247
|
||
|
Patch-mainline: 2.6.33-rc1
|
||
|
Git-commit: 5231a68614b94f60e8f6c56bc6e3d75955b9e75e
|
||
|
|
||
|
Commit 5231a68614b94f60e8f6c56bc6e3d75955b9e75e upstream.
|
||
|
|
||
|
To ensure that we handle all the pending interrupts (destined
|
||
|
for this cpu that is going down) in the interrupt subsystem
|
||
|
before the cpu goes offline, fixup_irqs() does:
|
||
|
|
||
|
local_irq_enable();
|
||
|
mdelay(1);
|
||
|
local_irq_disable();
|
||
|
|
||
|
Enabling interrupts is not a good thing as this cpu is already
|
||
|
offline. So this patch replaces that logic with,
|
||
|
|
||
|
mdelay(1);
|
||
|
check APIC_IRR bits
|
||
|
Retrigger the irq at the new destination if any interrupt has arrived
|
||
|
via IPI.
|
||
|
|
||
|
For IO-APIC level triggered interrupts, this retrigger IPI will
|
||
|
appear as an edge interrupt. ack_apic_level() will detect this
|
||
|
condition and IO-APIC RTE's remoteIRR is cleared using directed
|
||
|
EOI(using IO-APIC EOI register) on Intel platforms and for
|
||
|
others it uses the existing mask+edge logic followed by
|
||
|
unmask+level.
|
||
|
|
||
|
We can also remove mdelay() and then send spuriuous interrupts
|
||
|
to new cpu targets for all the irqs that were handled previously
|
||
|
by this cpu that is going offline. While it works, I have seen
|
||
|
spurious interrupt messages (nothing wrong but still annoying
|
||
|
messages during cpu offline, which can be seen during
|
||
|
suspend/resume etc)
|
||
|
|
||
|
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
|
||
|
Acked-by: Gary Hade <garyhade@us.ibm.com>
|
||
|
Signed-off-by: Ingo Molnar <mingo@elte.hu>
|
||
|
Signed-off-by: Rafael J. Wysocki <rjw@suse.de>
|
||
|
Automatically created from "patches.arch/x86-Remove-local_irq_enable-local_irq_disable-in-fixup_irqs.patch" by xen-port-patches.py
|
||
|
|
||
|
--- head-2010-01-07.orig/arch/x86/kernel/irq-xen.c 2010-01-07 10:32:41.000000000 +0100
|
||
|
+++ head-2010-01-07/arch/x86/kernel/irq-xen.c 2010-01-07 11:22:00.000000000 +0100
|
||
|
@@ -288,12 +288,14 @@ void smp_generic_interrupt(struct pt_reg
|
||
|
#endif
|
||
|
|
||
|
#ifdef CONFIG_HOTPLUG_CPU
|
||
|
+#include <xen/evtchn.h>
|
||
|
/* A cpu has been removed from cpu_online_mask. Reset irq affinities. */
|
||
|
void fixup_irqs(void)
|
||
|
{
|
||
|
unsigned int irq;
|
||
|
static int warned;
|
||
|
struct irq_desc *desc;
|
||
|
+ static DECLARE_BITMAP(irqs_used, NR_IRQS);
|
||
|
|
||
|
for_each_irq_desc(irq, desc) {
|
||
|
int break_affinity = 0;
|
||
|
@@ -315,6 +317,9 @@ void fixup_irqs(void)
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
+ if (cpumask_test_cpu(smp_processor_id(), affinity))
|
||
|
+ __set_bit(irq, irqs_used);
|
||
|
+
|
||
|
if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
|
||
|
break_affinity = 1;
|
||
|
affinity = cpu_all_mask;
|
||
|
@@ -339,9 +344,27 @@ void fixup_irqs(void)
|
||
|
printk("Cannot set affinity for irq %i\n", irq);
|
||
|
}
|
||
|
|
||
|
- /* That doesn't seem sufficient. Give it 1ms. */
|
||
|
- local_irq_enable();
|
||
|
+ /*
|
||
|
+ * We can remove mdelay() and then send spuriuous interrupts to
|
||
|
+ * new cpu targets for all the irqs that were handled previously by
|
||
|
+ * this cpu. While it works, I have seen spurious interrupt messages
|
||
|
+ * (nothing wrong but still...).
|
||
|
+ *
|
||
|
+ * So for now, retain mdelay(1) and check the IRR and then send those
|
||
|
+ * interrupts to new targets as this cpu is already offlined...
|
||
|
+ */
|
||
|
mdelay(1);
|
||
|
- local_irq_disable();
|
||
|
+
|
||
|
+ for_each_irq_desc(irq, desc) {
|
||
|
+ if (!__test_and_clear_bit(irq, irqs_used))
|
||
|
+ continue;
|
||
|
+
|
||
|
+ if (xen_test_irq_pending(irq)) {
|
||
|
+ spin_lock(&desc->lock);
|
||
|
+ if (desc->chip->retrigger)
|
||
|
+ desc->chip->retrigger(irq);
|
||
|
+ spin_unlock(&desc->lock);
|
||
|
+ }
|
||
|
+ }
|
||
|
}
|
||
|
#endif
|