Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=6dee6421581d3484e9a01d403dbf158161942db6
Commit:     6dee6421581d3484e9a01d403dbf158161942db6
Parent:     4fd7ab5949edfdf99be0ceef206c9d0b7f186318
Author:     Michael Chan <[EMAIL PROTECTED]>
AuthorDate: Fri Oct 12 01:40:38 2007 -0700
Committer:  David S. Miller <[EMAIL PROTECTED]>
CommitDate: Fri Oct 12 02:01:21 2007 -0700

    [BNX2]: Refine napi poll loop.
    
    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 <[EMAIL PROTECTED]>
    Signed-off-by: David S. Miller <[EMAIL PROTECTED]>
---
 drivers/net/bnx2.c |   16 ++++++++++------
 1 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index d68acce..78ed633 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -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 |
-
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  http://vger.kernel.org/majordomo-info.html

Reply via email to