Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=5a606b72a4309a656cd1a19ad137dc5557c4b8ea
Commit:     5a606b72a4309a656cd1a19ad137dc5557c4b8ea
Parent:     667ef3c3968e4e2ddc3f3f84f05e11fb2453d5b6
Author:     David S. Miller <[EMAIL PROTECTED]>
AuthorDate: Mon Jul 9 22:40:36 2007 -0700
Committer:  David S. Miller <[EMAIL PROTECTED]>
CommitDate: Mon Jul 16 04:04:05 2007 -0700

    [SPARC64]: Do not ACK an INO if it is disabled or inprogress.
    
    This is also a partial workaround for a bug in the LDOM firmware which
    double-transmits RX inos during high load.  Without this, such an
    event causes the kernel to loop forever in the interrupt call chain
    ACK'ing but never actually running the IRQ handler (and thus clearing
    the interrupt condition in the device).
    
    There is still a bad potential effect when double INOs occur,
    not covered by this changeset.  Namely, if the INO is already on
    the per-cpu INO vector list, we still blindly re-insert it and
    thus we can end up losing interrupts already linked in after
    it.
    
    We could deal with that by traversing the list before insertion,
    but that's too expensive for this edge case.
    
    Signed-off-by: David S. Miller <[EMAIL PROTECTED]>
---
 arch/sparc64/kernel/irq.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

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;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to