octeontx2-pf: Fix SQE threshold checking

Current way of checking available SQE count which is based on
HW updated SQB count could result in driver submitting an SQE
even before CQE for the previously transmitted SQE at the same
index is processed in NAPI resulting losing SKB pointers,
hence a leak. Fix this by checking a consumer index which
is updated once CQE is processed.

Fixes: 3ca6c4c882 ("octeontx2-pf: Add packet transmission support")
Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
Reviewed-by: Sunil Kovvuri Goutham <sgoutham@marvell.com>
Link: https://lore.kernel.org/r/20221107033505.2491464-1-rkannoth@marvell.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Ratheesh Kannoth 2022-11-07 09:05:05 +05:30 committed by Paolo Abeni
parent b0c09c7f08
commit f0dfc4c88e
3 changed files with 21 additions and 13 deletions

View File

@ -898,6 +898,7 @@ static int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura)
} }
sq->head = 0; sq->head = 0;
sq->cons_head = 0;
sq->sqe_per_sqb = (pfvf->hw.sqb_size / sq->sqe_size) - 1; sq->sqe_per_sqb = (pfvf->hw.sqb_size / sq->sqe_size) - 1;
sq->num_sqbs = (qset->sqe_cnt + sq->sqe_per_sqb) / sq->sqe_per_sqb; sq->num_sqbs = (qset->sqe_cnt + sq->sqe_per_sqb) / sq->sqe_per_sqb;
/* Set SQE threshold to 10% of total SQEs */ /* Set SQE threshold to 10% of total SQEs */

View File

@ -441,6 +441,7 @@ static int otx2_tx_napi_handler(struct otx2_nic *pfvf,
struct otx2_cq_queue *cq, int budget) struct otx2_cq_queue *cq, int budget)
{ {
int tx_pkts = 0, tx_bytes = 0, qidx; int tx_pkts = 0, tx_bytes = 0, qidx;
struct otx2_snd_queue *sq;
struct nix_cqe_tx_s *cqe; struct nix_cqe_tx_s *cqe;
int processed_cqe = 0; int processed_cqe = 0;
@ -451,6 +452,9 @@ static int otx2_tx_napi_handler(struct otx2_nic *pfvf,
return 0; return 0;
process_cqe: process_cqe:
qidx = cq->cq_idx - pfvf->hw.rx_queues;
sq = &pfvf->qset.sq[qidx];
while (likely(processed_cqe < budget) && cq->pend_cqe) { while (likely(processed_cqe < budget) && cq->pend_cqe) {
cqe = (struct nix_cqe_tx_s *)otx2_get_next_cqe(cq); cqe = (struct nix_cqe_tx_s *)otx2_get_next_cqe(cq);
if (unlikely(!cqe)) { if (unlikely(!cqe)) {
@ -458,18 +462,20 @@ process_cqe:
return 0; return 0;
break; break;
} }
if (cq->cq_type == CQ_XDP) { if (cq->cq_type == CQ_XDP) {
qidx = cq->cq_idx - pfvf->hw.rx_queues; otx2_xdp_snd_pkt_handler(pfvf, sq, cqe);
otx2_xdp_snd_pkt_handler(pfvf, &pfvf->qset.sq[qidx],
cqe);
} else { } else {
otx2_snd_pkt_handler(pfvf, cq, otx2_snd_pkt_handler(pfvf, cq, sq, cqe, budget,
&pfvf->qset.sq[cq->cint_idx], &tx_pkts, &tx_bytes);
cqe, budget, &tx_pkts, &tx_bytes);
} }
cqe->hdr.cqe_type = NIX_XQE_TYPE_INVALID; cqe->hdr.cqe_type = NIX_XQE_TYPE_INVALID;
processed_cqe++; processed_cqe++;
cq->pend_cqe--; cq->pend_cqe--;
sq->cons_head++;
sq->cons_head &= (sq->sqe_cnt - 1);
} }
/* Free CQEs to HW */ /* Free CQEs to HW */
@ -1072,17 +1078,17 @@ bool otx2_sq_append_skb(struct net_device *netdev, struct otx2_snd_queue *sq,
{ {
struct netdev_queue *txq = netdev_get_tx_queue(netdev, qidx); struct netdev_queue *txq = netdev_get_tx_queue(netdev, qidx);
struct otx2_nic *pfvf = netdev_priv(netdev); struct otx2_nic *pfvf = netdev_priv(netdev);
int offset, num_segs, free_sqe; int offset, num_segs, free_desc;
struct nix_sqe_hdr_s *sqe_hdr; struct nix_sqe_hdr_s *sqe_hdr;
/* Check if there is room for new SQE. /* Check if there is enough room between producer
* 'Num of SQBs freed to SQ's pool - SQ's Aura count' * and consumer index.
* will give free SQE count.
*/ */
free_sqe = (sq->num_sqbs - *sq->aura_fc_addr) * sq->sqe_per_sqb; free_desc = (sq->cons_head - sq->head - 1 + sq->sqe_cnt) & (sq->sqe_cnt - 1);
if (free_desc < sq->sqe_thresh)
return false;
if (free_sqe < sq->sqe_thresh || if (free_desc < otx2_get_sqe_count(pfvf, skb))
free_sqe < otx2_get_sqe_count(pfvf, skb))
return false; return false;
num_segs = skb_shinfo(skb)->nr_frags + 1; num_segs = skb_shinfo(skb)->nr_frags + 1;

View File

@ -79,6 +79,7 @@ struct sg_list {
struct otx2_snd_queue { struct otx2_snd_queue {
u8 aura_id; u8 aura_id;
u16 head; u16 head;
u16 cons_head;
u16 sqe_size; u16 sqe_size;
u32 sqe_cnt; u32 sqe_cnt;
u16 num_sqbs; u16 num_sqbs;