aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bnx2.c
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2007-07-08 01:51:03 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-07-11 01:18:35 -0400
commitb8a7ce7bedb2134acb731e08e588ad92087a40ff (patch)
tree2d18138f5c9697f71861c37f94aa2e7cbfc5228b /drivers/net/bnx2.c
parent9b1084b8f99a6b5e97c0c9bc1b4455db4fa51a07 (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.c13
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}