bnx2x: Rx work check

The has Rx work check was wrong: when the FW was at the end of the page,
the driver was already at the beginning of the next page. Since the
check only validated that both driver and FW are pointing to the same
place, it concluded that there is still work to be done. This caused
some serious issues including long latency results on ping-pong test and
lockups while unloading the driver in that condition.

Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by Eilon Greenstein and committed by David S. Miller 2772f903 ce3113ec

+8 -1
+1 -1
drivers/net/bnx2x.h
··· 271 271 (fp->tx_pkt_prod != fp->tx_pkt_cons)) 272 272 273 273 #define BNX2X_HAS_RX_WORK(fp) \ 274 - (fp->rx_comp_cons != le16_to_cpu(*fp->rx_cons_sb)) 274 + (fp->rx_comp_cons != rx_cons_sb) 275 275 276 276 #define BNX2X_HAS_WORK(fp) (BNX2X_HAS_RX_WORK(fp) || BNX2X_HAS_TX_WORK(fp)) 277 277
+7
drivers/net/bnx2x_main.c
··· 9250 9250 napi); 9251 9251 struct bnx2x *bp = fp->bp; 9252 9252 int work_done = 0; 9253 + u16 rx_cons_sb; 9253 9254 9254 9255 #ifdef BNX2X_STOP_ON_ERROR 9255 9256 if (unlikely(bp->panic)) ··· 9266 9265 if (BNX2X_HAS_TX_WORK(fp)) 9267 9266 bnx2x_tx_int(fp, budget); 9268 9267 9268 + rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb); 9269 + if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT) 9270 + rx_cons_sb++; 9269 9271 if (BNX2X_HAS_RX_WORK(fp)) 9270 9272 work_done = bnx2x_rx_int(fp, budget); 9271 9273 9272 9274 rmb(); /* BNX2X_HAS_WORK() reads the status block */ 9275 + rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb); 9276 + if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT) 9277 + rx_cons_sb++; 9273 9278 9274 9279 /* must not complete if we consumed full budget */ 9275 9280 if ((work_done < budget) && !BNX2X_HAS_WORK(fp)) {