]> err.no Git - linux-2.6/commitdiff
[BNX2]: Refine napi poll loop.
authorMichael Chan <mchan@broadcom.com>
Fri, 12 Oct 2007 08:40:38 +0000 (01:40 -0700)
committerDavid S. Miller <davem@sunset.davemloft.net>
Fri, 12 Oct 2007 09:01:21 +0000 (02:01 -0700)
Need to read and store sblk->status_idx before checking for more work.
The status idx is later written back to the hardware when enabling
interrupts to acknowledge how much work has been processed.  If the
order is reversed, we can end up acknowledging work we haven't
processed.

When completing bnx2_poll(), we should always break out of the while
loop and return work_done instead of returning 0.

Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/bnx2.c

index d68accea380bb3adcf40aaeece00d607d006d4bc..78ed633ceb829e121161a8a230a1350d9de06017 100644 (file)
@@ -2652,10 +2652,10 @@ static int bnx2_poll_work(struct bnx2 *bp, int work_done, int budget)
                REG_RD(bp, BNX2_HC_COMMAND);
        }
 
-       if (bp->status_blk->status_tx_quick_consumer_index0 != bp->hw_tx_cons)
+       if (sblk->status_tx_quick_consumer_index0 != bp->hw_tx_cons)
                bnx2_tx_int(bp);
 
-       if (bp->status_blk->status_rx_quick_consumer_index0 != bp->hw_rx_cons)
+       if (sblk->status_rx_quick_consumer_index0 != bp->hw_rx_cons)
                work_done += bnx2_rx_int(bp, budget - work_done);
 
        return work_done;
@@ -2665,6 +2665,7 @@ static int bnx2_poll(struct napi_struct *napi, int budget)
 {
        struct bnx2 *bp = container_of(napi, struct bnx2, napi);
        int work_done = 0;
+       struct status_block *sblk = bp->status_blk;
 
        while (1) {
                work_done = bnx2_poll_work(bp, work_done, budget);
@@ -2672,16 +2673,19 @@ static int bnx2_poll(struct napi_struct *napi, int budget)
                if (unlikely(work_done >= budget))
                        break;
 
+               /* bp->last_status_idx is used below to tell the hw how
+                * much work has been processed, so we must read it before
+                * checking for more work.
+                */
+               bp->last_status_idx = sblk->status_idx;
+               rmb();
                if (likely(!bnx2_has_work(bp))) {
-                       bp->last_status_idx = bp->status_blk->status_idx;
-                       rmb();
-
                        netif_rx_complete(bp->dev, napi);
                        if (likely(bp->flags & USING_MSI_FLAG)) {
                                REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
                                       BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
                                       bp->last_status_idx);
-                               return 0;
+                               break;
                        }
                        REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
                               BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |