Skip to content

Commit

Permalink
tg3: Fix RSS ring refill race condition
Browse files Browse the repository at this point in the history
The RSS feature in tg3 hardware has only one rx producer ring for all
RSS rings.  NAPI vector 1 is special and handles the refilling of the
rx producer ring on behalf of all RSS rings.  There is a race condition
between these RSS NAPIs and the NAPI[1].  If NAPI[1] finishes checking
for refill and then another RSS ring empties the rx producer ring
before NAPI[1] exits NAPI, the chip will be completely out of SKBs in
the rx producer ring.

We fix this by adding a flag tp->rx_refill and rely on napi_schedule()/
napi_complete() to help synchronize it to close the race condition.

Update driver version to 3.123.

Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Michael Chan authored and davem330 committed Mar 22, 2012
1 parent 5676cc7 commit 7ae5289
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 3 deletions.
25 changes: 22 additions & 3 deletions drivers/net/ethernet/broadcom/tg3.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,10 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)

#define DRV_MODULE_NAME "tg3"
#define TG3_MAJ_NUM 3
#define TG3_MIN_NUM 122
#define TG3_MIN_NUM 123
#define DRV_MODULE_VERSION \
__stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
#define DRV_MODULE_RELDATE "December 7, 2011"
#define DRV_MODULE_RELDATE "March 21, 2012"

#define RESET_KIND_SHUTDOWN 0
#define RESET_KIND_INIT 1
Expand Down Expand Up @@ -5953,8 +5953,10 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
tpr->rx_std_prod_idx = std_prod_idx & tp->rx_std_ring_mask;
tpr->rx_jmb_prod_idx = jmb_prod_idx & tp->rx_jmb_ring_mask;

if (tnapi != &tp->napi[1])
if (tnapi != &tp->napi[1]) {
tp->rx_refill = true;
napi_schedule(&tp->napi[1].napi);
}
}

return received;
Expand Down Expand Up @@ -6134,6 +6136,7 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget)
u32 std_prod_idx = dpr->rx_std_prod_idx;
u32 jmb_prod_idx = dpr->rx_jmb_prod_idx;

tp->rx_refill = false;
for (i = 1; i < tp->irq_cnt; i++)
err |= tg3_rx_prodring_xfer(tp, dpr,
&tp->napi[i].prodring);
Expand Down Expand Up @@ -6197,9 +6200,25 @@ static int tg3_poll_msix(struct napi_struct *napi, int budget)
/* check for RX/TX work to do */
if (likely(sblk->idx[0].tx_consumer == tnapi->tx_cons &&
*(tnapi->rx_rcb_prod_idx) == tnapi->rx_rcb_ptr)) {

/* This test here is not race free, but will reduce
* the number of interrupts by looping again.
*/
if (tnapi == &tp->napi[1] && tp->rx_refill)
continue;

napi_complete(napi);
/* Reenable interrupts. */
tw32_mailbox(tnapi->int_mbox, tnapi->last_tag << 24);

/* This test here is synchronized by napi_schedule()
* and napi_complete() to close the race condition.
*/
if (unlikely(tnapi == &tp->napi[1] && tp->rx_refill)) {
tw32(HOSTCC_MODE, tp->coalesce_mode |
HOSTCC_MODE_ENABLE |
tnapi->coal_now);
}
mmiowb();
break;
}
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/broadcom/tg3.h
Original file line number Diff line number Diff line change
Expand Up @@ -3007,6 +3007,7 @@ struct tg3 {
u32 rx_std_max_post;
u32 rx_offset;
u32 rx_pkt_map_sz;
bool rx_refill;


/* begin "everything else" cacheline(s) section */
Expand Down

0 comments on commit 7ae5289

Please sign in to comment.