LCOV - code coverage report
Current view: top level - drivers/net/nfp/nfdk - nfp_nfdk_dp.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 219 0.0 %
Date: 2024-01-22 16:26:08 Functions: 0 9 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 133 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright (c) 2023 Corigine, Inc.
       3                 :            :  * All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "nfp_nfdk.h"
       7                 :            : 
       8                 :            : #include <bus_pci_driver.h>
       9                 :            : #include <nfp_platform.h>
      10                 :            : #include <rte_malloc.h>
      11                 :            : 
      12                 :            : #include "../flower/nfp_flower.h"
      13                 :            : #include "../nfp_logs.h"
      14                 :            : 
      15                 :            : #define NFDK_TX_DESC_GATHER_MAX         17
      16                 :            : 
      17                 :            : /* Set TX CSUM offload flags in TX descriptor of nfdk */
      18                 :            : static uint64_t
      19                 :          0 : nfp_net_nfdk_tx_cksum(struct nfp_net_txq *txq,
      20                 :            :                 struct rte_mbuf *mb,
      21                 :            :                 uint64_t flags)
      22                 :            : {
      23                 :            :         uint64_t ol_flags;
      24                 :          0 :         struct nfp_net_hw *hw = txq->hw;
      25                 :            : 
      26         [ #  # ]:          0 :         if ((hw->super.cap & NFP_NET_CFG_CTRL_TXCSUM) == 0)
      27                 :            :                 return flags;
      28                 :            : 
      29                 :          0 :         ol_flags = mb->ol_flags;
      30                 :            : 
      31                 :            :         /* Set TCP csum offload if TSO enabled. */
      32         [ #  # ]:          0 :         if ((ol_flags & RTE_MBUF_F_TX_TCP_SEG) != 0)
      33                 :          0 :                 flags |= NFDK_DESC_TX_L4_CSUM;
      34                 :            : 
      35         [ #  # ]:          0 :         if ((ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) != 0)
      36                 :          0 :                 flags |= NFDK_DESC_TX_ENCAP;
      37                 :            : 
      38                 :            :         /* IPv6 does not need checksum */
      39         [ #  # ]:          0 :         if ((ol_flags & RTE_MBUF_F_TX_IP_CKSUM) != 0)
      40                 :          0 :                 flags |= NFDK_DESC_TX_L3_CSUM;
      41                 :            : 
      42         [ #  # ]:          0 :         if ((ol_flags & RTE_MBUF_F_TX_L4_MASK) != 0)
      43                 :          0 :                 flags |= NFDK_DESC_TX_L4_CSUM;
      44                 :            : 
      45                 :            :         return flags;
      46                 :            : }
      47                 :            : 
      48                 :            : /* Set TX descriptor for TSO of nfdk */
      49                 :            : static uint64_t
      50                 :          0 : nfp_net_nfdk_tx_tso(struct nfp_net_txq *txq,
      51                 :            :                 struct rte_mbuf *mb)
      52                 :            : {
      53                 :            :         uint8_t outer_len;
      54                 :            :         uint64_t ol_flags;
      55                 :            :         struct nfp_net_nfdk_tx_desc txd;
      56                 :          0 :         struct nfp_net_hw *hw = txq->hw;
      57                 :            : 
      58                 :          0 :         txd.raw = 0;
      59                 :            : 
      60         [ #  # ]:          0 :         if ((hw->super.cap & NFP_NET_CFG_CTRL_LSO_ANY) == 0)
      61                 :            :                 return txd.raw;
      62                 :            : 
      63                 :          0 :         ol_flags = mb->ol_flags;
      64         [ #  # ]:          0 :         if ((ol_flags & RTE_MBUF_F_TX_TCP_SEG) == 0)
      65                 :            :                 return txd.raw;
      66                 :            : 
      67                 :          0 :         txd.l3_offset = mb->l2_len;
      68                 :          0 :         txd.l4_offset = mb->l2_len + mb->l3_len;
      69                 :            :         txd.lso_meta_res = 0;
      70                 :          0 :         txd.mss = rte_cpu_to_le_16(mb->tso_segsz);
      71                 :          0 :         txd.lso_hdrlen = mb->l2_len + mb->l3_len + mb->l4_len;
      72                 :          0 :         txd.lso_totsegs = (mb->pkt_len + mb->tso_segsz) / mb->tso_segsz;
      73                 :            : 
      74         [ #  # ]:          0 :         if ((ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) != 0) {
      75                 :          0 :                 outer_len = mb->outer_l2_len + mb->outer_l3_len;
      76                 :          0 :                 txd.l3_offset += outer_len;
      77                 :          0 :                 txd.l4_offset += outer_len;
      78                 :          0 :                 txd.lso_hdrlen += outer_len;
      79                 :            :         }
      80                 :            : 
      81                 :          0 :         return txd.raw;
      82                 :            : }
      83                 :            : 
      84                 :            : uint32_t
      85         [ #  # ]:          0 : nfp_flower_nfdk_pkt_add_metadata(struct rte_mbuf *mbuf,
      86                 :            :                 uint32_t port_id)
      87                 :            : {
      88                 :            :         uint32_t header;
      89                 :            :         char *meta_offset;
      90                 :            : 
      91                 :            :         meta_offset = rte_pktmbuf_prepend(mbuf, FLOWER_PKT_DATA_OFFSET);
      92                 :            :         header = NFP_NET_META_PORTID << NFP_NET_META_NFDK_LENGTH | FLOWER_PKT_DATA_OFFSET;
      93                 :          0 :         *(rte_be32_t *)meta_offset = rte_cpu_to_be_32(header);
      94                 :            :         meta_offset += NFP_NET_META_HEADER_SIZE;
      95         [ #  # ]:          0 :         *(rte_be32_t *)meta_offset = rte_cpu_to_be_32(port_id);
      96                 :            : 
      97                 :          0 :         return FLOWER_PKT_DATA_OFFSET;
      98                 :            : }
      99                 :            : 
     100                 :            : static inline uint16_t
     101                 :            : nfp_net_nfdk_headlen_to_segs(uint16_t headlen)
     102                 :            : {
     103                 :            :         /* First descriptor fits less data, so adjust for that */
     104                 :          0 :         return DIV_ROUND_UP(headlen + NFDK_TX_MAX_DATA_PER_DESC - NFDK_TX_MAX_DATA_PER_HEAD,
     105                 :            :                         NFDK_TX_MAX_DATA_PER_DESC);
     106                 :            : }
     107                 :            : 
     108                 :            : static inline void
     109                 :          0 : nfp_net_nfdk_tx_close_block(struct nfp_net_txq *txq,
     110                 :            :                 uint32_t nop_slots)
     111                 :            : {
     112                 :            :         uint32_t i;
     113                 :            :         uint32_t wr_p;
     114                 :            : 
     115                 :          0 :         wr_p = txq->wr_p;
     116                 :          0 :         memset(&txq->ktxds[wr_p], 0, nop_slots * sizeof(struct nfp_net_nfdk_tx_desc));
     117                 :            : 
     118         [ #  # ]:          0 :         for (i = wr_p; i < nop_slots + wr_p; i++) {
     119         [ #  # ]:          0 :                 if (txq->txbufs[i].mbuf != NULL) {
     120                 :            :                         rte_pktmbuf_free_seg(txq->txbufs[i].mbuf);
     121                 :          0 :                         txq->txbufs[i].mbuf = NULL;
     122                 :            :                 }
     123                 :            :         }
     124                 :            : 
     125                 :          0 :         txq->data_pending = 0;
     126                 :          0 :         txq->wr_p = D_IDX(txq, wr_p + nop_slots);
     127                 :          0 : }
     128                 :            : 
     129                 :            : int
     130                 :          0 : nfp_net_nfdk_tx_maybe_close_block(struct nfp_net_txq *txq,
     131                 :            :                 struct rte_mbuf *pkt)
     132                 :            : {
     133                 :            :         uint16_t n_descs;
     134                 :            :         uint32_t nop_slots;
     135                 :            :         struct rte_mbuf *pkt_temp;
     136                 :            : 
     137                 :            :         /* Count address descriptor */
     138                 :            :         pkt_temp = pkt;
     139                 :          0 :         n_descs = nfp_net_nfdk_headlen_to_segs(pkt_temp->data_len);
     140         [ #  # ]:          0 :         while (pkt_temp->next != NULL) {
     141                 :            :                 pkt_temp = pkt_temp->next;
     142                 :          0 :                 n_descs += DIV_ROUND_UP(pkt_temp->data_len, NFDK_TX_MAX_DATA_PER_DESC);
     143                 :            :         }
     144                 :            : 
     145         [ #  # ]:          0 :         if (unlikely(n_descs > NFDK_TX_DESC_GATHER_MAX))
     146                 :            :                 return -EINVAL;
     147                 :            : 
     148                 :            :         /* Count TSO descriptor */
     149         [ #  # ]:          0 :         if ((txq->hw->super.cap & NFP_NET_CFG_CTRL_LSO_ANY) != 0 &&
     150         [ #  # ]:          0 :                         (pkt->ol_flags & RTE_MBUF_F_TX_TCP_SEG) != 0)
     151                 :          0 :                 n_descs++;
     152                 :            : 
     153                 :            :         /* Don't count metadata descriptor, for the round down to work out */
     154                 :          0 :         if (RTE_ALIGN_FLOOR(txq->wr_p, NFDK_TX_DESC_BLOCK_CNT) !=
     155         [ #  # ]:          0 :                         RTE_ALIGN_FLOOR(txq->wr_p + n_descs, NFDK_TX_DESC_BLOCK_CNT))
     156                 :          0 :                 goto close_block;
     157                 :            : 
     158         [ #  # ]:          0 :         if (txq->data_pending + pkt->pkt_len > NFDK_TX_MAX_DATA_PER_BLOCK)
     159                 :          0 :                 goto close_block;
     160                 :            : 
     161                 :            :         return 0;
     162                 :            : 
     163                 :          0 : close_block:
     164                 :          0 :         nop_slots = D_BLOCK_CPL(txq->wr_p);
     165                 :          0 :         nfp_net_nfdk_tx_close_block(txq, nop_slots);
     166                 :            : 
     167                 :          0 :         return nop_slots;
     168                 :            : }
     169                 :            : 
     170                 :            : static void
     171         [ #  # ]:          0 : nfp_net_nfdk_set_meta_data(struct rte_mbuf *pkt,
     172                 :            :                 struct nfp_net_txq *txq,
     173                 :            :                 uint64_t *metadata)
     174                 :            : {
     175                 :            :         char *meta;
     176                 :            :         uint8_t layer = 0;
     177                 :            :         uint32_t meta_type;
     178                 :            :         uint32_t cap_extend;
     179                 :            :         struct nfp_net_hw *hw;
     180                 :            :         uint32_t header_offset;
     181                 :            :         uint8_t vlan_layer = 0;
     182                 :            :         uint8_t ipsec_layer = 0;
     183                 :            :         struct nfp_net_meta_raw meta_data;
     184                 :            : 
     185                 :            :         memset(&meta_data, 0, sizeof(meta_data));
     186                 :          0 :         hw = txq->hw;
     187                 :          0 :         cap_extend = hw->super.cap_ext;
     188                 :            : 
     189         [ #  # ]:          0 :         if ((pkt->ol_flags & RTE_MBUF_F_TX_VLAN) != 0 &&
     190         [ #  # ]:          0 :                         (hw->super.ctrl & NFP_NET_CFG_CTRL_TXVLAN_V2) != 0) {
     191                 :            :                 if (meta_data.length == 0)
     192                 :            :                         meta_data.length = NFP_NET_META_HEADER_SIZE;
     193                 :          0 :                 meta_data.length += NFP_NET_META_FIELD_SIZE;
     194                 :          0 :                 meta_data.header |= NFP_NET_META_VLAN;
     195                 :            :         }
     196                 :            : 
     197         [ #  # ]:          0 :         if ((pkt->ol_flags & RTE_MBUF_F_TX_SEC_OFFLOAD) != 0 &&
     198         [ #  # ]:          0 :                         (cap_extend & NFP_NET_CFG_CTRL_IPSEC) != 0) {
     199                 :            :                 uint32_t ipsec_type = NFP_NET_META_IPSEC |
     200                 :            :                                 NFP_NET_META_IPSEC << NFP_NET_META_FIELD_SIZE |
     201                 :            :                                 NFP_NET_META_IPSEC << (2 * NFP_NET_META_FIELD_SIZE);
     202         [ #  # ]:          0 :                 if (meta_data.length == 0)
     203                 :          0 :                         meta_data.length = NFP_NET_META_FIELD_SIZE;
     204                 :          0 :                 uint8_t ipsec_offset = meta_data.length - NFP_NET_META_FIELD_SIZE;
     205                 :          0 :                 meta_data.header |= (ipsec_type << ipsec_offset);
     206                 :          0 :                 meta_data.length += 3 * NFP_NET_META_FIELD_SIZE;
     207                 :            :         }
     208                 :            : 
     209         [ #  # ]:          0 :         if (meta_data.length == 0)
     210                 :          0 :                 return;
     211                 :            : 
     212                 :          0 :         meta_type = meta_data.header;
     213                 :          0 :         header_offset = meta_type << NFP_NET_META_NFDK_LENGTH;
     214                 :          0 :         meta_data.header = header_offset | meta_data.length;
     215   [ #  #  #  # ]:          0 :         meta_data.header = rte_cpu_to_be_32(meta_data.header);
     216                 :            :         meta = rte_pktmbuf_prepend(pkt, meta_data.length);
     217                 :            :         memcpy(meta, &meta_data.header, sizeof(meta_data.header));
     218                 :          0 :         meta += NFP_NET_META_HEADER_SIZE;
     219                 :            : 
     220         [ #  # ]:          0 :         for (; meta_type != 0; meta_type >>= NFP_NET_META_FIELD_SIZE, layer++,
     221                 :          0 :                         meta += NFP_NET_META_FIELD_SIZE) {
     222      [ #  #  # ]:          0 :                 switch (meta_type & NFP_NET_META_FIELD_MASK) {
     223                 :          0 :                 case NFP_NET_META_VLAN:
     224         [ #  # ]:          0 :                         if (vlan_layer > 0) {
     225                 :          0 :                                 PMD_DRV_LOG(ERR, "At most 1 layers of vlan is supported");
     226                 :          0 :                                 return;
     227                 :            :                         }
     228                 :          0 :                         nfp_net_set_meta_vlan(&meta_data, pkt, layer);
     229                 :            :                         vlan_layer++;
     230                 :          0 :                         break;
     231                 :          0 :                 case NFP_NET_META_IPSEC:
     232         [ #  # ]:          0 :                         if (ipsec_layer > 2) {
     233                 :          0 :                                 PMD_DRV_LOG(ERR, "At most 3 layers of ipsec is supported for now.");
     234                 :          0 :                                 return;
     235                 :            :                         }
     236                 :            : 
     237                 :          0 :                         nfp_net_set_meta_ipsec(&meta_data, txq, pkt, layer, ipsec_layer);
     238                 :          0 :                         ipsec_layer++;
     239                 :          0 :                         break;
     240                 :          0 :                 default:
     241                 :          0 :                         PMD_DRV_LOG(ERR, "The metadata type not supported");
     242                 :          0 :                         return;
     243                 :            :                 }
     244                 :            : 
     245                 :          0 :                 memcpy(meta, &meta_data.data[layer], sizeof(meta_data.data[layer]));
     246                 :            :         }
     247                 :            : 
     248                 :          0 :         *metadata = NFDK_DESC_TX_CHAIN_META;
     249                 :            : }
     250                 :            : 
     251                 :            : uint16_t
     252                 :          0 : nfp_net_nfdk_xmit_pkts(void *tx_queue,
     253                 :            :                 struct rte_mbuf **tx_pkts,
     254                 :            :                 uint16_t nb_pkts)
     255                 :            : {
     256                 :          0 :         return nfp_net_nfdk_xmit_pkts_common(tx_queue, tx_pkts, nb_pkts, false);
     257                 :            : }
     258                 :            : 
     259                 :            : uint16_t
     260                 :          0 : nfp_net_nfdk_xmit_pkts_common(void *tx_queue,
     261                 :            :                 struct rte_mbuf **tx_pkts,
     262                 :            :                 uint16_t nb_pkts,
     263                 :            :                 bool repr_flag)
     264                 :            : {
     265                 :            :         uint32_t buf_idx;
     266                 :            :         uint64_t dma_addr;
     267                 :            :         uint32_t free_descs;
     268                 :            :         uint32_t npkts = 0;
     269                 :            :         struct rte_mbuf *pkt;
     270                 :            :         struct nfp_net_hw *hw;
     271                 :            :         struct rte_mbuf **lmbuf;
     272                 :            :         struct nfp_net_txq *txq;
     273                 :            :         uint32_t issued_descs = 0;
     274                 :            :         struct rte_mbuf *temp_pkt;
     275                 :            :         struct nfp_net_nfdk_tx_desc *ktxds;
     276                 :            : 
     277                 :            :         txq = tx_queue;
     278         [ #  # ]:          0 :         hw = txq->hw;
     279                 :            : 
     280                 :            :         PMD_TX_LOG(DEBUG, "working for queue %hu at pos %d and %hu packets",
     281                 :            :                         txq->qidx, txq->wr_p, nb_pkts);
     282                 :            : 
     283   [ #  #  #  # ]:          0 :         if (nfp_net_nfdk_free_tx_desc(txq) < NFDK_TX_DESC_PER_SIMPLE_PKT * nb_pkts ||
     284                 :            :                         nfp_net_nfdk_txq_full(txq))
     285                 :          0 :                 nfp_net_tx_free_bufs(txq);
     286                 :            : 
     287                 :            :         free_descs = nfp_net_nfdk_free_tx_desc(txq);
     288         [ #  # ]:          0 :         if (unlikely(free_descs == 0))
     289                 :            :                 return 0;
     290                 :            : 
     291                 :            :         PMD_TX_LOG(DEBUG, "queue: %hu. Sending %hu packets", txq->qidx, nb_pkts);
     292                 :            : 
     293                 :            :         /* Sending packets */
     294   [ #  #  #  # ]:          0 :         while (npkts < nb_pkts && free_descs > 0) {
     295                 :            :                 int nop_descs;
     296                 :            :                 uint32_t type;
     297                 :            :                 uint32_t dma_len;
     298                 :            :                 uint32_t tmp_dlen;
     299                 :            :                 uint32_t dlen_type;
     300                 :            :                 uint32_t used_descs;
     301                 :          0 :                 uint64_t metadata = 0;
     302                 :            : 
     303                 :          0 :                 pkt = *(tx_pkts + npkts);
     304         [ #  # ]:          0 :                 if (pkt == NULL)
     305                 :          0 :                         goto xmit_end;
     306                 :            : 
     307                 :          0 :                 nop_descs = nfp_net_nfdk_tx_maybe_close_block(txq, pkt);
     308         [ #  # ]:          0 :                 if (nop_descs < 0)
     309                 :          0 :                         goto xmit_end;
     310                 :            : 
     311                 :          0 :                 issued_descs += nop_descs;
     312                 :          0 :                 ktxds = &txq->ktxds[txq->wr_p];
     313                 :            : 
     314                 :            :                 /* Grabbing the mbuf linked to the current descriptor */
     315                 :            :                 buf_idx = txq->wr_p;
     316                 :          0 :                 lmbuf = &txq->txbufs[buf_idx++].mbuf;
     317                 :            :                 /* Warming the cache for releasing the mbuf later on */
     318         [ #  # ]:          0 :                 RTE_MBUF_PREFETCH_TO_FREE(*lmbuf);
     319                 :            : 
     320                 :            :                 temp_pkt = pkt;
     321                 :            : 
     322         [ #  # ]:          0 :                 if (repr_flag)
     323                 :          0 :                         metadata = NFDK_DESC_TX_CHAIN_META;
     324                 :            :                 else
     325                 :          0 :                         nfp_net_nfdk_set_meta_data(pkt, txq, &metadata);
     326                 :            : 
     327   [ #  #  #  # ]:          0 :                 if (unlikely(pkt->nb_segs > 1 &&
     328                 :            :                                 (hw->super.cap & NFP_NET_CFG_CTRL_GATHER) == 0)) {
     329                 :            :                         PMD_TX_LOG(ERR, "Multisegment packet not supported");
     330                 :          0 :                         goto xmit_end;
     331                 :            :                 }
     332                 :            : 
     333                 :            :                 /*
     334                 :            :                  * Checksum and VLAN flags just in the first descriptor for a
     335                 :            :                  * multisegment packet, but TSO info needs to be in all of them.
     336                 :            :                  */
     337                 :          0 :                 dma_len = pkt->data_len;
     338         [ #  # ]:          0 :                 if ((hw->super.cap & NFP_NET_CFG_CTRL_LSO_ANY) != 0 &&
     339         [ #  # ]:          0 :                                 (pkt->ol_flags & RTE_MBUF_F_TX_TCP_SEG) != 0) {
     340                 :            :                         type = NFDK_DESC_TX_TYPE_TSO;
     341   [ #  #  #  # ]:          0 :                 } else if (pkt->next == NULL && dma_len <= NFDK_TX_MAX_DATA_PER_HEAD) {
     342                 :            :                         type = NFDK_DESC_TX_TYPE_SIMPLE;
     343                 :            :                 } else {
     344                 :            :                         type = NFDK_DESC_TX_TYPE_GATHER;
     345                 :            :                 }
     346                 :            : 
     347                 :            :                 /* Implicitly truncates to chunk in below logic */
     348                 :          0 :                 dma_len -= 1;
     349                 :            : 
     350                 :            :                 /*
     351                 :            :                  * We will do our best to pass as much data as we can in descriptor
     352                 :            :                  * and we need to make sure the first descriptor includes whole
     353                 :            :                  * head since there is limitation in firmware side. Sometimes the
     354                 :            :                  * value of 'dma_len & NFDK_DESC_TX_DMA_LEN_HEAD' will be less
     355                 :            :                  * than packet head len.
     356                 :            :                  */
     357                 :            :                 if (dma_len > NFDK_DESC_TX_DMA_LEN_HEAD)
     358                 :            :                         tmp_dlen = NFDK_DESC_TX_DMA_LEN_HEAD;
     359                 :            :                 else
     360                 :            :                         tmp_dlen = dma_len;
     361                 :          0 :                 dlen_type = tmp_dlen | (NFDK_DESC_TX_TYPE_HEAD & (type << 12));
     362                 :          0 :                 ktxds->dma_len_type = rte_cpu_to_le_16(dlen_type);
     363                 :            :                 dma_addr = rte_mbuf_data_iova(pkt);
     364                 :          0 :                 ktxds->dma_addr_hi = rte_cpu_to_le_16(dma_addr >> 32);
     365                 :          0 :                 ktxds->dma_addr_lo = rte_cpu_to_le_32(dma_addr & 0xffffffff);
     366                 :          0 :                 ktxds++;
     367                 :            : 
     368                 :            :                 /*
     369                 :            :                  * Preserve the original dlen_type, this way below the EOP logic
     370                 :            :                  * can use dlen_type.
     371                 :            :                  */
     372                 :          0 :                 dma_len -= tmp_dlen;
     373                 :          0 :                 dma_addr += tmp_dlen + 1;
     374                 :            : 
     375                 :            :                 /*
     376                 :            :                  * The rest of the data (if any) will be in larger DMA descriptors
     377                 :            :                  * and is handled with the dma_len loop.
     378                 :            :                  */
     379                 :          0 :                 while (pkt != NULL) {
     380         [ #  # ]:          0 :                         if (*lmbuf != NULL)
     381                 :            :                                 rte_pktmbuf_free_seg(*lmbuf);
     382                 :          0 :                         *lmbuf = pkt;
     383         [ #  # ]:          0 :                         while (dma_len > 0) {
     384                 :          0 :                                 dma_len -= 1;
     385                 :          0 :                                 dlen_type = NFDK_DESC_TX_DMA_LEN & dma_len;
     386                 :            : 
     387                 :          0 :                                 ktxds->dma_len_type = rte_cpu_to_le_16(dlen_type);
     388                 :          0 :                                 ktxds->dma_addr_hi = rte_cpu_to_le_16(dma_addr >> 32);
     389                 :          0 :                                 ktxds->dma_addr_lo = rte_cpu_to_le_32(dma_addr & 0xffffffff);
     390                 :          0 :                                 ktxds++;
     391                 :            : 
     392                 :          0 :                                 dma_len -= dlen_type;
     393                 :          0 :                                 dma_addr += dlen_type + 1;
     394                 :            :                         }
     395                 :            : 
     396         [ #  # ]:          0 :                         if (pkt->next == NULL)
     397                 :            :                                 break;
     398                 :            : 
     399                 :            :                         pkt = pkt->next;
     400                 :          0 :                         dma_len = pkt->data_len;
     401                 :            :                         dma_addr = rte_mbuf_data_iova(pkt);
     402                 :            : 
     403                 :          0 :                         lmbuf = &txq->txbufs[buf_idx++].mbuf;
     404                 :            :                 }
     405                 :            : 
     406                 :          0 :                 (ktxds - 1)->dma_len_type = rte_cpu_to_le_16(dlen_type | NFDK_DESC_TX_EOP);
     407                 :            : 
     408                 :          0 :                 ktxds->raw = rte_cpu_to_le_64(nfp_net_nfdk_tx_cksum(txq, temp_pkt, metadata));
     409                 :          0 :                 ktxds++;
     410                 :            : 
     411         [ #  # ]:          0 :                 if ((hw->super.cap & NFP_NET_CFG_CTRL_LSO_ANY) != 0 &&
     412         [ #  # ]:          0 :                                 (temp_pkt->ol_flags & RTE_MBUF_F_TX_TCP_SEG) != 0) {
     413                 :          0 :                         ktxds->raw = rte_cpu_to_le_64(nfp_net_nfdk_tx_tso(txq, temp_pkt));
     414                 :          0 :                         ktxds++;
     415                 :            :                 }
     416                 :            : 
     417                 :          0 :                 used_descs = ktxds - txq->ktxds - txq->wr_p;
     418                 :          0 :                 if (RTE_ALIGN_FLOOR(txq->wr_p, NFDK_TX_DESC_BLOCK_CNT) !=
     419         [ #  # ]:          0 :                                 RTE_ALIGN_FLOOR(txq->wr_p + used_descs - 1,
     420                 :            :                                                 NFDK_TX_DESC_BLOCK_CNT)) {
     421                 :            :                         PMD_TX_LOG(INFO, "Used descs cross block boundary");
     422                 :          0 :                         goto xmit_end;
     423                 :            :                 }
     424                 :            : 
     425                 :          0 :                 txq->wr_p = D_IDX(txq, txq->wr_p + used_descs);
     426         [ #  # ]:          0 :                 if (txq->wr_p % NFDK_TX_DESC_BLOCK_CNT)
     427                 :          0 :                         txq->data_pending += temp_pkt->pkt_len;
     428                 :            :                 else
     429                 :          0 :                         txq->data_pending = 0;
     430                 :            : 
     431                 :          0 :                 issued_descs += used_descs;
     432         [ #  # ]:          0 :                 npkts++;
     433                 :            :                 free_descs = nfp_net_nfdk_free_tx_desc(txq);
     434                 :            :         }
     435                 :            : 
     436                 :          0 : xmit_end:
     437                 :            :         /* Increment write pointers. Force memory write before we let HW know */
     438                 :            :         rte_wmb();
     439                 :          0 :         nfp_qcp_ptr_add(txq->qcp_q, NFP_QCP_WRITE_PTR, issued_descs);
     440                 :            : 
     441                 :          0 :         return npkts;
     442                 :            : }
     443                 :            : 
     444                 :            : int
     445                 :          0 : nfp_net_nfdk_tx_queue_setup(struct rte_eth_dev *dev,
     446                 :            :                 uint16_t queue_idx,
     447                 :            :                 uint16_t nb_desc,
     448                 :            :                 unsigned int socket_id,
     449                 :            :                 const struct rte_eth_txconf *tx_conf)
     450                 :            : {
     451                 :            :         size_t size;
     452                 :            :         uint32_t tx_desc_sz;
     453                 :            :         uint16_t min_tx_desc;
     454                 :            :         uint16_t max_tx_desc;
     455                 :            :         struct nfp_net_hw *hw;
     456                 :            :         uint16_t tx_free_thresh;
     457                 :            :         struct nfp_net_txq *txq;
     458                 :            :         const struct rte_memzone *tz;
     459                 :            : 
     460                 :          0 :         hw = nfp_net_get_hw(dev);
     461                 :            : 
     462                 :          0 :         nfp_net_tx_desc_limits(hw, &min_tx_desc, &max_tx_desc);
     463                 :            : 
     464                 :            :         /* Validating number of descriptors */
     465                 :          0 :         tx_desc_sz = nb_desc * sizeof(struct nfp_net_nfdk_tx_desc);
     466         [ #  # ]:          0 :         if ((NFDK_TX_DESC_PER_SIMPLE_PKT * tx_desc_sz) % NFP_ALIGN_RING_DESC != 0 ||
     467         [ #  # ]:          0 :                         (NFDK_TX_DESC_PER_SIMPLE_PKT * nb_desc) % NFDK_TX_DESC_BLOCK_CNT != 0 ||
     468   [ #  #  #  # ]:          0 :                         nb_desc > max_tx_desc || nb_desc < min_tx_desc) {
     469                 :          0 :                 PMD_DRV_LOG(ERR, "Wrong nb_desc value");
     470                 :          0 :                 return -EINVAL;
     471                 :            :         }
     472                 :            : 
     473                 :          0 :         tx_free_thresh = tx_conf->tx_free_thresh;
     474         [ #  # ]:          0 :         if (tx_free_thresh == 0)
     475                 :            :                 tx_free_thresh = DEFAULT_TX_FREE_THRESH;
     476         [ #  # ]:          0 :         if (tx_free_thresh > nb_desc) {
     477                 :          0 :                 PMD_DRV_LOG(ERR, "tx_free_thresh must be less than the number of TX "
     478                 :            :                                 "descriptors. (tx_free_thresh=%u port=%d queue=%d)",
     479                 :            :                                 tx_free_thresh, dev->data->port_id, queue_idx);
     480                 :          0 :                 return -EINVAL;
     481                 :            :         }
     482                 :            : 
     483                 :            :         /*
     484                 :            :          * Free memory prior to re-allocation if needed. This is the case after
     485                 :            :          * calling nfp_net_stop().
     486                 :            :          */
     487         [ #  # ]:          0 :         if (dev->data->tx_queues[queue_idx] != NULL) {
     488                 :            :                 PMD_TX_LOG(DEBUG, "Freeing memory prior to re-allocation %d",
     489                 :            :                                 queue_idx);
     490                 :          0 :                 nfp_net_tx_queue_release(dev, queue_idx);
     491                 :          0 :                 dev->data->tx_queues[queue_idx] = NULL;
     492                 :            :         }
     493                 :            : 
     494                 :            :         /* Allocating tx queue data structure */
     495                 :          0 :         txq = rte_zmalloc_socket("ethdev TX queue", sizeof(struct nfp_net_txq),
     496                 :            :                         RTE_CACHE_LINE_SIZE, socket_id);
     497         [ #  # ]:          0 :         if (txq == NULL) {
     498                 :          0 :                 PMD_DRV_LOG(ERR, "Error allocating tx dma");
     499                 :          0 :                 return -ENOMEM;
     500                 :            :         }
     501                 :            : 
     502                 :            :         /*
     503                 :            :          * Allocate TX ring hardware descriptors. A memzone large enough to
     504                 :            :          * handle the maximum ring size is allocated in order to allow for
     505                 :            :          * resizing in later calls to the queue setup function.
     506                 :            :          */
     507                 :          0 :         size = sizeof(struct nfp_net_nfdk_tx_desc) * max_tx_desc *
     508                 :            :                         NFDK_TX_DESC_PER_SIMPLE_PKT;
     509                 :          0 :         tz = rte_eth_dma_zone_reserve(dev, "tx_ring", queue_idx, size,
     510                 :            :                         NFP_MEMZONE_ALIGN, socket_id);
     511         [ #  # ]:          0 :         if (tz == NULL) {
     512                 :          0 :                 PMD_DRV_LOG(ERR, "Error allocating tx dma");
     513                 :          0 :                 nfp_net_tx_queue_release(dev, queue_idx);
     514                 :          0 :                 return -ENOMEM;
     515                 :            :         }
     516                 :            : 
     517                 :          0 :         txq->tx_count = nb_desc * NFDK_TX_DESC_PER_SIMPLE_PKT;
     518                 :          0 :         txq->tx_free_thresh = tx_free_thresh;
     519                 :            : 
     520                 :            :         /* Queue mapping based on firmware configuration */
     521                 :          0 :         txq->qidx = queue_idx;
     522                 :          0 :         txq->tx_qcidx = queue_idx * hw->stride_tx;
     523                 :          0 :         txq->qcp_q = hw->tx_bar + NFP_QCP_QUEUE_OFF(txq->tx_qcidx);
     524                 :          0 :         txq->port_id = dev->data->port_id;
     525                 :            : 
     526                 :            :         /* Saving physical and virtual addresses for the TX ring */
     527                 :          0 :         txq->dma = tz->iova;
     528                 :          0 :         txq->ktxds = tz->addr;
     529                 :            : 
     530                 :            :         /* Mbuf pointers array for referencing mbufs linked to TX descriptors */
     531                 :          0 :         txq->txbufs = rte_zmalloc_socket("txq->txbufs",
     532                 :          0 :                         sizeof(*txq->txbufs) * txq->tx_count,
     533                 :            :                         RTE_CACHE_LINE_SIZE, socket_id);
     534         [ #  # ]:          0 :         if (txq->txbufs == NULL) {
     535                 :          0 :                 nfp_net_tx_queue_release(dev, queue_idx);
     536                 :          0 :                 return -ENOMEM;
     537                 :            :         }
     538                 :            : 
     539                 :          0 :         nfp_net_reset_tx_queue(txq);
     540                 :            : 
     541                 :          0 :         dev->data->tx_queues[queue_idx] = txq;
     542                 :          0 :         txq->hw = hw;
     543                 :            : 
     544                 :            :         /*
     545                 :            :          * Telling the HW about the physical address of the TX ring and number
     546                 :            :          * of descriptors in log2 format.
     547                 :            :          */
     548                 :          0 :         nn_cfg_writeq(&hw->super, NFP_NET_CFG_TXR_ADDR(queue_idx), txq->dma);
     549         [ #  # ]:          0 :         nn_cfg_writeb(&hw->super, NFP_NET_CFG_TXR_SZ(queue_idx), rte_log2_u32(txq->tx_count));
     550                 :            : 
     551                 :          0 :         return 0;
     552                 :            : }

Generated by: LCOV version 1.14