aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bnx2.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2007-10-11 21:08:29 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-11 21:08:29 -0400
commit6f535763165331bb91277d7519b507fed22034e5 (patch)
tree1968a01affa1cce3a3199c455d1fe1ebdca3ff47 /drivers/net/bnx2.c
parentb08d6cb22c777c8c91c16d8e3b8aafc93c98cbd9 (diff)
[NET]: Fix NAPI completion handling in some drivers.
In order for the list handling in net_rx_action() to be correct, drivers must follow certain rules as stated by this comment in net_rx_action(): /* Drivers must not modify the NAPI state if they * consume the entire weight. In such cases this code * still "owns" the NAPI instance and therefore can * move the instance around on the list at-will. */ A few drivers do not do this because they mix the budget checks with reading hardware state, resulting in crashes like the one reported by takano@axe-inc.co.jp. BNX2 and TG3 are taken care of here, SKY2 fix is from Stephen Hemminger. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bnx2.c')
-rw-r--r--drivers/net/bnx2.c52
1 files changed, 32 insertions, 20 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index bbfbdafb4ae5..d68accea380b 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -2633,15 +2633,11 @@ bnx2_has_work(struct bnx2 *bp)
2633 return 0; 2633 return 0;
2634} 2634}
2635 2635
2636static int 2636static int bnx2_poll_work(struct bnx2 *bp, int work_done, int budget)
2637bnx2_poll(struct napi_struct *napi, int budget)
2638{ 2637{
2639 struct bnx2 *bp = container_of(napi, struct bnx2, napi);
2640 struct net_device *dev = bp->dev;
2641 struct status_block *sblk = bp->status_blk; 2638 struct status_block *sblk = bp->status_blk;
2642 u32 status_attn_bits = sblk->status_attn_bits; 2639 u32 status_attn_bits = sblk->status_attn_bits;
2643 u32 status_attn_bits_ack = sblk->status_attn_bits_ack; 2640 u32 status_attn_bits_ack = sblk->status_attn_bits_ack;
2644 int work_done = 0;
2645 2641
2646 if ((status_attn_bits & STATUS_ATTN_EVENTS) != 2642 if ((status_attn_bits & STATUS_ATTN_EVENTS) !=
2647 (status_attn_bits_ack & STATUS_ATTN_EVENTS)) { 2643 (status_attn_bits_ack & STATUS_ATTN_EVENTS)) {
@@ -2660,27 +2656,43 @@ bnx2_poll(struct napi_struct *napi, int budget)
2660 bnx2_tx_int(bp); 2656 bnx2_tx_int(bp);
2661 2657
2662 if (bp->status_blk->status_rx_quick_consumer_index0 != bp->hw_rx_cons) 2658 if (bp->status_blk->status_rx_quick_consumer_index0 != bp->hw_rx_cons)
2663 work_done = bnx2_rx_int(bp, budget); 2659 work_done += bnx2_rx_int(bp, budget - work_done);
2664 2660
2665 bp->last_status_idx = bp->status_blk->status_idx; 2661 return work_done;
2666 rmb(); 2662}
2663
2664static int bnx2_poll(struct napi_struct *napi, int budget)
2665{
2666 struct bnx2 *bp = container_of(napi, struct bnx2, napi);
2667 int work_done = 0;
2668
2669 while (1) {
2670 work_done = bnx2_poll_work(bp, work_done, budget);
2667 2671
2668 if (!bnx2_has_work(bp)) { 2672 if (unlikely(work_done >= budget))
2669 netif_rx_complete(dev, napi); 2673 break;
2670 if (likely(bp->flags & USING_MSI_FLAG)) { 2674
2675 if (likely(!bnx2_has_work(bp))) {
2676 bp->last_status_idx = bp->status_blk->status_idx;
2677 rmb();
2678
2679 netif_rx_complete(bp->dev, napi);
2680 if (likely(bp->flags & USING_MSI_FLAG)) {
2681 REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
2682 BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
2683 bp->last_status_idx);
2684 return 0;
2685 }
2671 REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, 2686 REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
2672 BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | 2687 BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
2688 BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
2673 bp->last_status_idx); 2689 bp->last_status_idx);
2674 return 0;
2675 }
2676 REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
2677 BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
2678 BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
2679 bp->last_status_idx);
2680 2690
2681 REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, 2691 REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
2682 BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | 2692 BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
2683 bp->last_status_idx); 2693 bp->last_status_idx);
2694 break;
2695 }
2684 } 2696 }
2685 2697
2686 return work_done; 2698 return work_done;