Commit:     0fc4969b866671dfe39b1a9119d0fdc7ea0f63e5
Parent:     fd0cbdd378258fdf44eac5ea091256a4a665315b
Author:     Thomas Gleixner <[EMAIL PROTECTED]>
AuthorDate: Wed Aug 1 17:13:19 2007 +0200
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Wed Aug 1 20:46:22 2007 -0700

    genirq: temporary fix for level-triggered IRQ resend
    Marcin Slusarz reported a ne2k-pci "hung network interface" regression.
    delayed disable relies on the ability to re-trigger the interrupt in the
    case that a real interrupt happens after the software disable was set.
    In this case we actually disable the interrupt on the hardware level
    _after_ it occurred.
    On enable_irq, we need to re-trigger the interrupt. On i386 this relies
    on a hardware resend mechanism (send_IPI_self()).
    Actually we only need the resend for edge type interrupts. Level type
    interrupts come back once enable_irq() re-enables the interrupt line.
    I assume that the interrupt in question is level triggered because it is
    shared and above the legacy irqs 0-15:
        17:         12   IO-APIC-fasteoi   eth1, eth0
    Looking into the IO_APIC code, the resend via send_IPI_self() happens
    unconditionally. So the resend is done for level and edge interrupts.
    This makes the problem more mysterious.
    The code in question lib8390.c does
    The fiddle_with_the_network_card_hardware() might cause interrupts,
    which are cleared in the same code path again,
    Marcin found that when he disables the irq line on the hardware level
    (removing the delayed disable) the card is kept alive.
    So the difference is that we can get a resend on enable_irq, when an
    interrupt happens during the time, where we are in the disabled region.
    Signed-off-by: Ingo Molnar <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
 kernel/irq/resend.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/kernel/irq/resend.c b/kernel/irq/resend.c
index 5bfeaed..c382727 100644
--- a/kernel/irq/resend.c
+++ b/kernel/irq/resend.c
@@ -62,6 +62,15 @@ void check_irq_resend(struct irq_desc *desc, unsigned int 
+       /*
+        * Temporary hack to figure out more about the problem, which
+        * is causing the ancient network cards to die.
+        */
+       if (desc->handle_irq != handle_edge_irq) {
+               WARN_ON_ONCE(1);
+               return;
+       }
        if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
                desc->status = (status & ~IRQ_PENDING) | IRQ_REPLAY;
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

Reply via email to