Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: 3ca6c4c882a7 ("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>

authored by

Ratheesh Kannoth and committed by
Paolo Abeni
f0dfc4c8 b0c09c7f

+21 -13
+1
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
··· 898 898 } 899 899 900 900 sq->head = 0; 901 + sq->cons_head = 0; 901 902 sq->sqe_per_sqb = (pfvf->hw.sqb_size / sq->sqe_size) - 1; 902 903 sq->num_sqbs = (qset->sqe_cnt + sq->sqe_per_sqb) / sq->sqe_per_sqb; 903 904 /* Set SQE threshold to 10% of total SQEs */
+19 -13
drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
··· 441 441 struct otx2_cq_queue *cq, int budget) 442 442 { 443 443 int tx_pkts = 0, tx_bytes = 0, qidx; 444 + struct otx2_snd_queue *sq; 444 445 struct nix_cqe_tx_s *cqe; 445 446 int processed_cqe = 0; 446 447 ··· 452 451 return 0; 453 452 454 453 process_cqe: 454 + qidx = cq->cq_idx - pfvf->hw.rx_queues; 455 + sq = &pfvf->qset.sq[qidx]; 456 + 455 457 while (likely(processed_cqe < budget) && cq->pend_cqe) { 456 458 cqe = (struct nix_cqe_tx_s *)otx2_get_next_cqe(cq); 457 459 if (unlikely(!cqe)) { ··· 462 458 return 0; 463 459 break; 464 460 } 461 + 465 462 if (cq->cq_type == CQ_XDP) { 466 - qidx = cq->cq_idx - pfvf->hw.rx_queues; 467 - otx2_xdp_snd_pkt_handler(pfvf, &pfvf->qset.sq[qidx], 468 - cqe); 463 + otx2_xdp_snd_pkt_handler(pfvf, sq, cqe); 469 464 } else { 470 - otx2_snd_pkt_handler(pfvf, cq, 471 - &pfvf->qset.sq[cq->cint_idx], 472 - cqe, budget, &tx_pkts, &tx_bytes); 465 + otx2_snd_pkt_handler(pfvf, cq, sq, cqe, budget, 466 + &tx_pkts, &tx_bytes); 473 467 } 468 + 474 469 cqe->hdr.cqe_type = NIX_XQE_TYPE_INVALID; 475 470 processed_cqe++; 476 471 cq->pend_cqe--; 472 + 473 + sq->cons_head++; 474 + sq->cons_head &= (sq->sqe_cnt - 1); 477 475 } 478 476 479 477 /* Free CQEs to HW */ ··· 1078 1072 { 1079 1073 struct netdev_queue *txq = netdev_get_tx_queue(netdev, qidx); 1080 1074 struct otx2_nic *pfvf = netdev_priv(netdev); 1081 - int offset, num_segs, free_sqe; 1075 + int offset, num_segs, free_desc; 1082 1076 struct nix_sqe_hdr_s *sqe_hdr; 1083 1077 1084 - /* Check if there is room for new SQE. 1085 - * 'Num of SQBs freed to SQ's pool - SQ's Aura count' 1086 - * will give free SQE count. 1078 + /* Check if there is enough room between producer 1079 + * and consumer index. 1087 1080 */ 1088 - free_sqe = (sq->num_sqbs - *sq->aura_fc_addr) * sq->sqe_per_sqb; 1081 + free_desc = (sq->cons_head - sq->head - 1 + sq->sqe_cnt) & (sq->sqe_cnt - 1); 1082 + if (free_desc < sq->sqe_thresh) 1083 + return false; 1089 1084 1090 - if (free_sqe < sq->sqe_thresh || 1091 - free_sqe < otx2_get_sqe_count(pfvf, skb)) 1085 + if (free_desc < otx2_get_sqe_count(pfvf, skb)) 1092 1086 return false; 1093 1087 1094 1088 num_segs = skb_shinfo(skb)->nr_frags + 1;
+1
drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h
··· 79 79 struct otx2_snd_queue { 80 80 u8 aura_id; 81 81 u16 head; 82 + u16 cons_head; 82 83 u16 sqe_size; 83 84 u32 sqe_cnt; 84 85 u16 num_sqbs;