Skip to content

Commit

Permalink
cxgb4: fix EOTID leak when disabling TC-MQPRIO offload
Browse files Browse the repository at this point in the history
Under heavy load, the EOTID termination FLOWC request fails to get
enqueued to the end of the Tx ring due to lack of credits. This
results in EOTID leak.

When disabling TC-MQPRIO offload, the link is already brought down
to cleanup EOTIDs. So, flush any pending enqueued skbs that can't be
sent outside the wire, to make room for FLOWC request. Also, move the
FLOWC descriptor consumption logic closer to when the FLOWC request is
actually posted to hardware.

Fixes: 0e395b3 ("cxgb4: add FLOWC based QoS offload")
Signed-off-by: Rahul Lakkireddy <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
chelsiocudbg authored and davem330 committed May 1, 2020
1 parent ab1c637 commit 69422a7
Showing 1 changed file with 36 additions and 3 deletions.
39 changes: 36 additions & 3 deletions drivers/net/ethernet/chelsio/cxgb4/sge.c
Original file line number Diff line number Diff line change
Expand Up @@ -2207,6 +2207,9 @@ static void ethofld_hard_xmit(struct net_device *dev,
if (unlikely(skip_eotx_wr)) {
start = (u64 *)wr;
eosw_txq->state = next_state;
eosw_txq->cred -= wrlen16;
eosw_txq->ncompl++;
eosw_txq->last_compl = 0;
goto write_wr_headers;
}

Expand Down Expand Up @@ -2365,6 +2368,34 @@ netdev_tx_t t4_start_xmit(struct sk_buff *skb, struct net_device *dev)
return cxgb4_eth_xmit(skb, dev);
}

static void eosw_txq_flush_pending_skbs(struct sge_eosw_txq *eosw_txq)
{
int pktcount = eosw_txq->pidx - eosw_txq->last_pidx;
int pidx = eosw_txq->pidx;
struct sk_buff *skb;

if (!pktcount)
return;

if (pktcount < 0)
pktcount += eosw_txq->ndesc;

while (pktcount--) {
pidx--;
if (pidx < 0)
pidx += eosw_txq->ndesc;

skb = eosw_txq->desc[pidx].skb;
if (skb) {
dev_consume_skb_any(skb);
eosw_txq->desc[pidx].skb = NULL;
eosw_txq->inuse--;
}
}

eosw_txq->pidx = eosw_txq->last_pidx + 1;
}

/**
* cxgb4_ethofld_send_flowc - Send ETHOFLD flowc request to bind eotid to tc.
* @dev - netdevice
Expand Down Expand Up @@ -2440,9 +2471,11 @@ int cxgb4_ethofld_send_flowc(struct net_device *dev, u32 eotid, u32 tc)
FW_FLOWC_MNEM_EOSTATE_CLOSING :
FW_FLOWC_MNEM_EOSTATE_ESTABLISHED);

eosw_txq->cred -= len16;
eosw_txq->ncompl++;
eosw_txq->last_compl = 0;
/* Free up any pending skbs to ensure there's room for
* termination FLOWC.
*/
if (tc == FW_SCHED_CLS_NONE)
eosw_txq_flush_pending_skbs(eosw_txq);

ret = eosw_txq_enqueue(eosw_txq, skb);
if (ret) {
Expand Down

0 comments on commit 69422a7

Please sign in to comment.