diff options
author | Eilon Greenstein <eilong@broadcom.com> | 2009-03-02 07:59:45 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-03-02 22:32:39 -0800 |
commit | 8534f32c2fb86bff629f7152bc3096245252062c (patch) | |
tree | cbf591739b1f5a3cf5c0c40c00ed06e8eff32756 | |
parent | 7961f79123604a395dc467c605a94bbaed74df83 (diff) |
bnx2x: napi_poll budget check
Check the napi_poll budget only when updating it. Also add a comment to explain
the rmb
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/bnx2x_main.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index a66536ec10a..e0851a744c4 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -10068,14 +10068,27 @@ static int bnx2x_poll(struct napi_struct *napi, int budget) if (bnx2x_has_tx_work(fp)) bnx2x_tx_int(fp); - if (bnx2x_has_rx_work(fp)) + if (bnx2x_has_rx_work(fp)) { work_done = bnx2x_rx_int(fp, budget); - rmb(); /* BNX2X_HAS_WORK() reads the status block */ + /* must not complete if we consumed full budget */ + if (work_done >= budget) + goto poll_again; + } - /* must not complete if we consumed full budget */ - if ((work_done < budget) && !BNX2X_HAS_WORK(fp)) { + /* BNX2X_HAS_WORK() reads the status block, thus we need to + * ensure that status block indices have been actually read + * (bnx2x_update_fpsb_idx) prior to this check (BNX2X_HAS_WORK) + * so that we won't write the "newer" value of the status block to IGU + * (if there was a DMA right after BNX2X_HAS_WORK and + * if there is no rmb, the memory reading (bnx2x_update_fpsb_idx) + * may be postponed to right before bnx2x_ack_sb). In this case + * there will never be another interrupt until there is another update + * of the status block, while there is still unhandled work. + */ + rmb(); + if (!BNX2X_HAS_WORK(fp)) { #ifdef BNX2X_STOP_ON_ERROR poll_panic: #endif @@ -10087,6 +10100,7 @@ poll_panic: le16_to_cpu(fp->fp_c_idx), IGU_INT_ENABLE, 1); } +poll_again: return work_done; } |