[BNX2]: Fix RX packet rot.

Packets can be left in the RX ring if the NAPI budget is reached.
This is caused by storing the latest rx index at the beginning of
bnx2_rx_int(). We may not process all the work up to this index
if the budget is reached and so some packets in the RX ring may rot
when we later check for more work using this stored rx index.

The fix is to not store this latest hw index and only store the
processed rx index. We use a new function bnx2_get_hw_rx_cons()
to fetch the latest hw rx index.

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

authored by Michael Chan and committed by David S. Miller c09c2627 fb0c18bd

+14 -13
+14 -12
drivers/net/bnx2.c
··· 2387 2387 prod_bd->rx_bd_haddr_lo = cons_bd->rx_bd_haddr_lo; 2388 2388 } 2389 2389 2390 + static inline u16 2391 + bnx2_get_hw_rx_cons(struct bnx2 *bp) 2392 + { 2393 + u16 cons = bp->status_blk->status_rx_quick_consumer_index0; 2394 + 2395 + if (unlikely((cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT)) 2396 + cons++; 2397 + return cons; 2398 + } 2399 + 2390 2400 static int 2391 2401 bnx2_rx_int(struct bnx2 *bp, int budget) 2392 2402 { 2393 - struct status_block *sblk = bp->status_blk; 2394 2403 u16 hw_cons, sw_cons, sw_ring_cons, sw_prod, sw_ring_prod; 2395 2404 struct l2_fhdr *rx_hdr; 2396 2405 int rx_pkt = 0; 2397 2406 2398 - hw_cons = bp->hw_rx_cons = sblk->status_rx_quick_consumer_index0; 2399 - if ((hw_cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT) { 2400 - hw_cons++; 2401 - } 2407 + hw_cons = bnx2_get_hw_rx_cons(bp); 2402 2408 sw_cons = bp->rx_cons; 2403 2409 sw_prod = bp->rx_prod; 2404 2410 ··· 2521 2515 2522 2516 /* Refresh hw_cons to see if there is new work */ 2523 2517 if (sw_cons == hw_cons) { 2524 - hw_cons = bp->hw_rx_cons = 2525 - sblk->status_rx_quick_consumer_index0; 2526 - if ((hw_cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT) 2527 - hw_cons++; 2518 + hw_cons = bnx2_get_hw_rx_cons(bp); 2528 2519 rmb(); 2529 2520 } 2530 2521 } ··· 2625 2622 { 2626 2623 struct status_block *sblk = bp->status_blk; 2627 2624 2628 - if ((sblk->status_rx_quick_consumer_index0 != bp->hw_rx_cons) || 2625 + if ((bnx2_get_hw_rx_cons(bp) != bp->rx_cons) || 2629 2626 (sblk->status_tx_quick_consumer_index0 != bp->hw_tx_cons)) 2630 2627 return 1; 2631 2628 ··· 2658 2655 if (sblk->status_tx_quick_consumer_index0 != bp->hw_tx_cons) 2659 2656 bnx2_tx_int(bp); 2660 2657 2661 - if (sblk->status_rx_quick_consumer_index0 != bp->hw_rx_cons) 2658 + if (bnx2_get_hw_rx_cons(bp) != bp->rx_cons) 2662 2659 work_done += bnx2_rx_int(bp, budget - work_done); 2663 2660 2664 2661 return work_done; ··· 4180 4177 4181 4178 ring_prod = prod = bp->rx_prod = 0; 4182 4179 bp->rx_cons = 0; 4183 - bp->hw_rx_cons = 0; 4184 4180 bp->rx_prod_bseq = 0; 4185 4181 4186 4182 for (i = 0; i < bp->rx_max_ring; i++) {
-1
drivers/net/bnx2.h
··· 6513 6513 u32 rx_prod_bseq; 6514 6514 u16 rx_prod; 6515 6515 u16 rx_cons; 6516 - u16 hw_rx_cons; 6517 6516 6518 6517 u32 rx_csum; 6519 6518