Message ID | 20090429.155218.210110117.davem@davemloft.net |
---|---|
State | Not Applicable |
Delegated to: | David Miller |
Headers | show |
From: Chris Torek <chris.torek@windriver.com> Date: Wed, 29 Apr 2009 18:06:57 -0600 > Yes, this one is in. I did (and still do) suspect a hypervisor > bug. I think in this case the problem is that this test is not > sufficent for the "two vnets on one vswitch" case, though, > because this results in the desc->status not having > IRQ_INPROGRESS set on the "other" vnet that gets a double > interrupt. You can know if it's this hypervisor bug by simply updating your hypervisor to the latest version available. > I'm also wondering now if it has something to do with the code we > added that attempts to redistribute interrupts, so that in the case > of a double interrupt, the second one goes to a different CPU > than the CPU already handling the first one. Although we > should still see IRQ_INPROGRESS then... If you're making local changes on that scale, it's irresponsible to make mention of them when reporting a bug you want this list to look at :-( -- To unsubscribe from this list: send the line "unsubscribe sparclinux" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 6b6165d..634194e 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -309,6 +309,10 @@ static void sun4u_irq_disable(unsigned int virt_irq) static void sun4u_irq_end(unsigned int virt_irq) { struct irq_handler_data *data = get_irq_chip_data(virt_irq); + struct irq_desc *desc = irq_desc + virt_irq; + + if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) + return; if (likely(data)) upa_writeq(ICLR_IDLE, data->iclr); @@ -373,6 +377,10 @@ static void sun4v_irq_end(unsigned int virt_irq) { struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); unsigned int ino = bucket - &ivector_table[0]; + struct irq_desc *desc = irq_desc + virt_irq; + + if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) + return; if (likely(bucket)) { int err; @@ -443,6 +451,10 @@ static void sun4v_virq_end(unsigned int virt_irq) { struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); unsigned int ino = bucket - &ivector_table[0]; + struct irq_desc *desc = irq_desc + virt_irq; + + if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) + return; if (likely(bucket)) { unsigned long dev_handle, dev_ino;