From: Long Wu <long...@corigine.com> If dma_len is larger than NFDK_DESC_TX_DMA_LEN_HEAD, the value of dma_len bitwise and NFDK_DESC_TX_DMA_LEN_HEAD maybe less than packet head length and the packet will be dropped. Fill maximum dma_len in first tx descriptor to make sure the whole head is included in the first descriptor. In addition, add comments to better explain the code flow.
Fixes: c73dced48c8c ("net/nfp: add NFDk Tx") Cc: jin....@corigine.com Cc: sta...@dpdk.org Signed-off-by: Long Wu <long...@corigine.com> Reviewed-by: Niklas Söderlund <niklas.soderl...@corigine.com> --- v2: * Rewrite the commit message. * Revise some logic according to the advice. --- drivers/net/nfp/nfp_rxtx.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/net/nfp/nfp_rxtx.c b/drivers/net/nfp/nfp_rxtx.c index 01cffdfde0..990007c03d 100644 --- a/drivers/net/nfp/nfp_rxtx.c +++ b/drivers/net/nfp/nfp_rxtx.c @@ -1063,6 +1063,7 @@ nfp_net_nfdk_tx_maybe_close_block(struct nfp_net_txq *txq, struct rte_mbuf *pkt) if (unlikely(n_descs > NFDK_TX_DESC_GATHER_MAX)) return -EINVAL; + /* Under count by 1 (don't count meta) for the round down to work out */ n_descs += !!(pkt->ol_flags & RTE_MBUF_F_TX_TCP_SEG); if (round_down(txq->wr_p, NFDK_TX_DESC_BLOCK_CNT) != @@ -1219,8 +1220,19 @@ nfp_net_nfdk_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pk } else { type = NFDK_DESC_TX_TYPE_GATHER; } + + /* Implicitly truncates to chunk in below logic */ dma_len -= 1; - dlen_type = (NFDK_DESC_TX_DMA_LEN_HEAD & dma_len) | + + /* + * We will do our best to pass as much data as we can in descriptor + * and we need to make sure the first descriptor includes whole + * head since there is limitation in firmware side. Sometimes the + * value of dma_len bitwise & NFDK_DESC_TX_DMA_LEN_HEAD will less + * than packet head len. + */ + dlen_type = (dma_len > NFDK_DESC_TX_DMA_LEN_HEAD ? + NFDK_DESC_TX_DMA_LEN_HEAD : dma_len) | (NFDK_DESC_TX_TYPE_HEAD & (type << 12)); ktxds->dma_len_type = rte_cpu_to_le_16(dlen_type); dma_addr = rte_mbuf_data_iova(pkt); @@ -1230,10 +1242,18 @@ nfp_net_nfdk_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pk ktxds->dma_addr_lo = rte_cpu_to_le_32(dma_addr & 0xffffffff); ktxds++; + /* + * Preserve the original dlen_type, this way below the EOP logic + * can use dlen_type. + */ tmp_dlen = dlen_type & NFDK_DESC_TX_DMA_LEN_HEAD; dma_len -= tmp_dlen; dma_addr += tmp_dlen + 1; + /* + * The rest of the data (if any) will be in larger dma descritors + * and is handled with the dma_len loop. + */ while (pkt) { if (*lmbuf) rte_pktmbuf_free_seg(*lmbuf); -- 2.29.3