Commit 4d6acb62 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

bnx2x: avoid soft lockup in bnx2x_poll()

Under heavy TX load, bnx2x_poll() can loop forever and trigger
soft lockup bugs.

A napi poll handler must yield after one TX completion round,
risk of livelock is too high otherwise.

Bug is very easy to trigger using a debug build, and udp flood, because
of added cpu cycles in TX completion, and we do not receive enough
packets to break the loop.
Reported-by: default avatarWillem de Bruijn <willemb@google.com>
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Cc: Ariel Elior <ariel.elior@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 46c749ea
...@@ -3204,13 +3204,12 @@ int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state) ...@@ -3204,13 +3204,12 @@ int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state)
*/ */
static int bnx2x_poll(struct napi_struct *napi, int budget) static int bnx2x_poll(struct napi_struct *napi, int budget)
{ {
int work_done = 0;
u8 cos;
struct bnx2x_fastpath *fp = container_of(napi, struct bnx2x_fastpath, struct bnx2x_fastpath *fp = container_of(napi, struct bnx2x_fastpath,
napi); napi);
struct bnx2x *bp = fp->bp; struct bnx2x *bp = fp->bp;
int rx_work_done;
u8 cos;
while (1) {
#ifdef BNX2X_STOP_ON_ERROR #ifdef BNX2X_STOP_ON_ERROR
if (unlikely(bp->panic)) { if (unlikely(bp->panic)) {
napi_complete(napi); napi_complete(napi);
...@@ -3221,25 +3220,16 @@ static int bnx2x_poll(struct napi_struct *napi, int budget) ...@@ -3221,25 +3220,16 @@ static int bnx2x_poll(struct napi_struct *napi, int budget)
if (bnx2x_tx_queue_has_work(fp->txdata_ptr[cos])) if (bnx2x_tx_queue_has_work(fp->txdata_ptr[cos]))
bnx2x_tx_int(bp, fp->txdata_ptr[cos]); bnx2x_tx_int(bp, fp->txdata_ptr[cos]);
if (bnx2x_has_rx_work(fp)) { rx_work_done = (bnx2x_has_rx_work(fp)) ? bnx2x_rx_int(fp, budget) : 0;
work_done += bnx2x_rx_int(fp, budget - work_done);
/* must not complete if we consumed full budget */
if (work_done >= budget)
break;
}
/* Fall out from the NAPI loop if needed */
if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {
if (rx_work_done < budget) {
/* No need to update SB for FCoE L2 ring as long as /* No need to update SB for FCoE L2 ring as long as
* it's connected to the default SB and the SB * it's connected to the default SB and the SB
* has been updated when NAPI was scheduled. * has been updated when NAPI was scheduled.
*/ */
if (IS_FCOE_FP(fp)) { if (IS_FCOE_FP(fp)) {
napi_complete(napi); napi_complete(napi);
break; } else {
}
bnx2x_update_fpsb_idx(fp); bnx2x_update_fpsb_idx(fp);
/* bnx2x_has_rx_work() reads the status block, /* bnx2x_has_rx_work() reads the status block,
* thus we need to ensure that status block indices * thus we need to ensure that status block indices
...@@ -3264,12 +3254,13 @@ static int bnx2x_poll(struct napi_struct *napi, int budget) ...@@ -3264,12 +3254,13 @@ static int bnx2x_poll(struct napi_struct *napi, int budget)
bnx2x_ack_sb(bp, fp->igu_sb_id, USTORM_ID, bnx2x_ack_sb(bp, fp->igu_sb_id, USTORM_ID,
le16_to_cpu(fp->fp_hc_idx), le16_to_cpu(fp->fp_hc_idx),
IGU_INT_ENABLE, 1); IGU_INT_ENABLE, 1);
break; } else {
rx_work_done = budget;
} }
} }
} }
return work_done; return rx_work_done;
} }
/* we split the first BD into headers and data BDs /* we split the first BD into headers and data BDs
......
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