forked from Minki/linux
[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 <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
4fd7ab5949
commit
6dee642158
@ -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 |
|
||||
|
Loading…
Reference in New Issue
Block a user