diff options
author | Michael Chan <mchan@broadcom.com> | 2007-07-08 01:51:03 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-07-11 01:18:35 -0400 |
commit | b8a7ce7bedb2134acb731e08e588ad92087a40ff (patch) | |
tree | 2d18138f5c9697f71861c37f94aa2e7cbfc5228b /drivers/net/bnx2.c | |
parent | 9b1084b8f99a6b5e97c0c9bc1b4455db4fa51a07 (diff) |
[BNX2]: Reduce spurious INTA interrupts.
Spurious interrupts are often encountered especially on systems
using the 8259 PIC mode. This is because the I/O write to deassert
the interrupt is posted and won't get to the chip immediately. As
a result, the IRQ may remain asserted after the IRQ handler exits,
causing spurious interrupts.
Add read back to flush the I/O write to deassert the IRQ immediately.
We also store the last_status_idx immediately in the IRQ handler to
help detect whether the interrupt is ours or not when the IRQ is
entered again before ->poll gets called.
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bnx2.c')
-rw-r--r-- | drivers/net/bnx2.c | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 439f4827addc..a806a8edec87 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c | |||
@@ -2547,6 +2547,7 @@ bnx2_interrupt(int irq, void *dev_instance) | |||
2547 | { | 2547 | { |
2548 | struct net_device *dev = dev_instance; | 2548 | struct net_device *dev = dev_instance; |
2549 | struct bnx2 *bp = netdev_priv(dev); | 2549 | struct bnx2 *bp = netdev_priv(dev); |
2550 | struct status_block *sblk = bp->status_blk; | ||
2550 | 2551 | ||
2551 | /* When using INTx, it is possible for the interrupt to arrive | 2552 | /* When using INTx, it is possible for the interrupt to arrive |
2552 | * at the CPU before the status block posted prior to the | 2553 | * at the CPU before the status block posted prior to the |
@@ -2554,7 +2555,7 @@ bnx2_interrupt(int irq, void *dev_instance) | |||
2554 | * When using MSI, the MSI message will always complete after | 2555 | * When using MSI, the MSI message will always complete after |
2555 | * the status block write. | 2556 | * the status block write. |
2556 | */ | 2557 | */ |
2557 | if ((bp->status_blk->status_idx == bp->last_status_idx) && | 2558 | if ((sblk->status_idx == bp->last_status_idx) && |
2558 | (REG_RD(bp, BNX2_PCICFG_MISC_STATUS) & | 2559 | (REG_RD(bp, BNX2_PCICFG_MISC_STATUS) & |
2559 | BNX2_PCICFG_MISC_STATUS_INTA_VALUE)) | 2560 | BNX2_PCICFG_MISC_STATUS_INTA_VALUE)) |
2560 | return IRQ_NONE; | 2561 | return IRQ_NONE; |
@@ -2563,11 +2564,19 @@ bnx2_interrupt(int irq, void *dev_instance) | |||
2563 | BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM | | 2564 | BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM | |
2564 | BNX2_PCICFG_INT_ACK_CMD_MASK_INT); | 2565 | BNX2_PCICFG_INT_ACK_CMD_MASK_INT); |
2565 | 2566 | ||
2567 | /* Read back to deassert IRQ immediately to avoid too many | ||
2568 | * spurious interrupts. | ||
2569 | */ | ||
2570 | REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD); | ||
2571 | |||
2566 | /* Return here if interrupt is shared and is disabled. */ | 2572 | /* Return here if interrupt is shared and is disabled. */ |
2567 | if (unlikely(atomic_read(&bp->intr_sem) != 0)) | 2573 | if (unlikely(atomic_read(&bp->intr_sem) != 0)) |
2568 | return IRQ_HANDLED; | 2574 | return IRQ_HANDLED; |
2569 | 2575 | ||
2570 | netif_rx_schedule(dev); | 2576 | if (netif_rx_schedule_prep(dev)) { |
2577 | bp->last_status_idx = sblk->status_idx; | ||
2578 | __netif_rx_schedule(dev); | ||
2579 | } | ||
2571 | 2580 | ||
2572 | return IRQ_HANDLED; | 2581 | return IRQ_HANDLED; |
2573 | } | 2582 | } |