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

Generated by: LCOV version 1.14