lkml.org 
[lkml]   [2009]   [Oct]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[RFC patch 6/6] x86: remove local_irq_enable()/local_irq_disable() in fixup_irqs()
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>
Signed-off-by: Gary Hade <garyhade@us.ibm.com>
Cc: Eric W. Biederman <ebiederm@xmission.com>
---
arch/x86/kernel/irq.c | 32 ++++++++++++++++++++++++++++----
1 file changed, 28 insertions(+), 4 deletions(-)

Index: tip/arch/x86/kernel/irq.c
===================================================================
--- tip.orig/arch/x86/kernel/irq.c
+++ tip/arch/x86/kernel/irq.c
@@ -279,7 +279,7 @@ EXPORT_SYMBOL_GPL(vector_used_by_percpu_
/* A cpu has been removed from cpu_online_mask. Reset irq affinities. */
void fixup_irqs(void)
{
- unsigned int irq;
+ unsigned int irq, vector;
static int warned;
struct irq_desc *desc;

@@ -334,9 +334,33 @@ 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 (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
+ unsigned int irr;
+
+ if (__get_cpu_var(vector_irq)[vector] < 0)
+ continue;
+
+ irr = apic_read(APIC_IRR + (vector / 32 * 0x10));
+ if (irr & (1 << (vector % 32))) {
+ irq = __get_cpu_var(vector_irq)[vector];
+
+ desc = irq_to_desc(irq);
+ spin_lock(&desc->lock);
+ if (desc->chip->retrigger)
+ desc->chip->retrigger(irq);
+ spin_unlock(&desc->lock);
+ }
+ }
}
#endif



\
 
 \ /
  Last update: 2009-10-26 23:07    [W:0.085 / U:0.320 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site