Commit 6dee6421 authored by Michael Chan's avatar Michael Chan Committed by David S. Miller

[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: default avatarMichael Chan <mchan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4fd7ab59
...@@ -2652,10 +2652,10 @@ static int bnx2_poll_work(struct bnx2 *bp, int work_done, int budget) ...@@ -2652,10 +2652,10 @@ static int bnx2_poll_work(struct bnx2 *bp, int work_done, int budget)
REG_RD(bp, BNX2_HC_COMMAND); 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); 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); work_done += bnx2_rx_int(bp, budget - work_done);
return work_done; return work_done;
...@@ -2665,6 +2665,7 @@ static int bnx2_poll(struct napi_struct *napi, int budget) ...@@ -2665,6 +2665,7 @@ static int bnx2_poll(struct napi_struct *napi, int budget)
{ {
struct bnx2 *bp = container_of(napi, struct bnx2, napi); struct bnx2 *bp = container_of(napi, struct bnx2, napi);
int work_done = 0; int work_done = 0;
struct status_block *sblk = bp->status_blk;
while (1) { while (1) {
work_done = bnx2_poll_work(bp, work_done, budget); work_done = bnx2_poll_work(bp, work_done, budget);
...@@ -2672,16 +2673,19 @@ static int bnx2_poll(struct napi_struct *napi, int budget) ...@@ -2672,16 +2673,19 @@ static int bnx2_poll(struct napi_struct *napi, int budget)
if (unlikely(work_done >= budget)) if (unlikely(work_done >= budget))
break; break;
if (likely(!bnx2_has_work(bp))) { /* bp->last_status_idx is used below to tell the hw how
bp->last_status_idx = bp->status_blk->status_idx; * much work has been processed, so we must read it before
* checking for more work.
*/
bp->last_status_idx = sblk->status_idx;
rmb(); rmb();
if (likely(!bnx2_has_work(bp))) {
netif_rx_complete(bp->dev, napi); netif_rx_complete(bp->dev, napi);
if (likely(bp->flags & USING_MSI_FLAG)) { if (likely(bp->flags & USING_MSI_FLAG)) {
REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
bp->last_status_idx); bp->last_status_idx);
return 0; break;
} }
REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment