LCOV - code coverage report
Current view: top level - drivers/net/enic - enic_rxtx.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 304 0.0 %
Date: 2025-02-01 18:54:23 Functions: 0 10 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 156 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright 2008-2017 Cisco Systems, Inc.  All rights reserved.
       3                 :            :  * Copyright 2007 Nuova Systems, Inc.  All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include <rte_mbuf.h>
       7                 :            : #include <ethdev_driver.h>
       8                 :            : #include <rte_net.h>
       9                 :            : #include <rte_prefetch.h>
      10                 :            : 
      11                 :            : #include "enic_compat.h"
      12                 :            : #include "rq_enet_desc.h"
      13                 :            : #include "enic.h"
      14                 :            : #include "enic_rxtx_common.h"
      15                 :            : #include <rte_ether.h>
      16                 :            : #include <rte_ip.h>
      17                 :            : #include <rte_tcp.h>
      18                 :            : 
      19                 :            : #define RTE_PMD_USE_PREFETCH
      20                 :            : 
      21                 :            : #ifdef RTE_PMD_USE_PREFETCH
      22                 :            : /*Prefetch a cache line into all cache levels. */
      23                 :            : #define rte_enic_prefetch(p) rte_prefetch0(p)
      24                 :            : #else
      25                 :            : #define rte_enic_prefetch(p) do {} while (0)
      26                 :            : #endif
      27                 :            : 
      28                 :            : #ifdef RTE_PMD_PACKET_PREFETCH
      29                 :            : #define rte_packet_prefetch(p) rte_prefetch1(p)
      30                 :            : #else
      31                 :            : #define rte_packet_prefetch(p) do {} while (0)
      32                 :            : #endif
      33                 :            : 
      34                 :            : static inline uint16_t
      35                 :          0 : enic_recv_pkts_common(void *rx_queue, struct rte_mbuf **rx_pkts,
      36                 :            :                       uint16_t nb_pkts, const bool use_64b_desc)
      37                 :            : {
      38                 :            :         struct vnic_rq *sop_rq = rx_queue;
      39                 :            :         struct vnic_rq *data_rq;
      40                 :            :         struct vnic_rq *rq;
      41                 :          0 :         struct enic *enic = vnic_dev_priv(sop_rq->vdev);
      42                 :            :         uint16_t cq_idx;
      43                 :            :         uint16_t rq_idx, max_rx;
      44                 :            :         uint16_t rq_num;
      45                 :            :         struct rte_mbuf *nmb, *rxmb;
      46                 :            :         uint16_t nb_rx = 0;
      47                 :            :         struct vnic_cq *cq;
      48                 :            :         volatile struct cq_desc *cqd_ptr;
      49                 :            :         uint8_t color;
      50                 :            :         uint8_t tnl;
      51                 :            :         uint16_t seg_length;
      52                 :          0 :         struct rte_mbuf *first_seg = sop_rq->pkt_first_seg;
      53                 :          0 :         struct rte_mbuf *last_seg = sop_rq->pkt_last_seg;
      54         [ #  # ]:          0 :         const int desc_size = use_64b_desc ?
      55                 :            :                 sizeof(struct cq_enet_rq_desc_64) :
      56                 :            :                 sizeof(struct cq_enet_rq_desc);
      57                 :            :         RTE_BUILD_BUG_ON(sizeof(struct cq_enet_rq_desc_64) != 64);
      58                 :            :         uint64_t bytes;
      59                 :            : 
      60                 :          0 :         cq = &enic->cq[enic_cq_rq(enic, sop_rq->index)];
      61                 :          0 :         cq_idx = cq->to_clean;               /* index of cqd, rqd, mbuf_table */
      62                 :          0 :         cqd_ptr = (struct cq_desc *)((uintptr_t)(cq->ring.descs) +
      63                 :          0 :                                      (uintptr_t)cq_idx * desc_size);
      64                 :          0 :         color = cq->last_color;
      65                 :            : 
      66                 :          0 :         data_rq = &enic->rq[sop_rq->data_queue_idx];
      67                 :            : 
      68                 :            :         /* Receive until the end of the ring, at most. */
      69                 :          0 :         max_rx = RTE_MIN(nb_pkts, cq->ring.desc_count - cq_idx);
      70                 :            : 
      71                 :            :         bytes = 0;
      72                 :            : 
      73         [ #  # ]:          0 :         while (max_rx) {
      74                 :            :                 volatile struct rq_enet_desc *rqd_ptr;
      75                 :            :                 struct cq_desc cqd;
      76                 :            :                 uint8_t packet_error;
      77                 :            :                 uint16_t ciflags;
      78                 :            :                 uint8_t tc;
      79                 :            :                 uint16_t rq_idx_msbs = 0;
      80                 :            : 
      81                 :          0 :                 max_rx--;
      82                 :            : 
      83                 :          0 :                 tc = *(volatile uint8_t *)((uintptr_t)cqd_ptr + desc_size - 1);
      84                 :            :                 /* Check for pkts available */
      85         [ #  # ]:          0 :                 if ((tc & CQ_DESC_COLOR_MASK_NOSHIFT) == color)
      86                 :            :                         break;
      87                 :            : 
      88                 :            :                 /* Get the cq descriptor and extract rq info from it */
      89                 :          0 :                 cqd = *cqd_ptr;
      90                 :            : 
      91                 :            :                 /*
      92                 :            :                  * The first 16B of a 64B descriptor is identical to a 16B
      93                 :            :                  * descriptor except for the type_color and fetch index. Extract
      94                 :            :                  * fetch index and copy the type_color from the 64B to where it
      95                 :            :                  * would be in a 16B descriptor so sebwequent code can run
      96                 :            :                  * without further conditionals.
      97                 :            :                  */
      98         [ #  # ]:          0 :                 if (use_64b_desc) {
      99                 :          0 :                         rq_idx_msbs = (((volatile struct cq_enet_rq_desc_64 *)
     100                 :          0 :                                       cqd_ptr)->fetch_idx_flags
     101                 :            :                                       & CQ_ENET_RQ_DESC_FETCH_IDX_MASK)
     102                 :          0 :                                       << CQ_DESC_COMP_NDX_BITS;
     103                 :          0 :                         cqd.type_color = tc;
     104                 :            :                 }
     105                 :          0 :                 rq_num = cqd.q_number & CQ_DESC_Q_NUM_MASK;
     106                 :          0 :                 rq_idx = rq_idx_msbs +
     107                 :          0 :                          (cqd.completed_index & CQ_DESC_COMP_NDX_MASK);
     108                 :            : 
     109                 :          0 :                 rq = &enic->rq[rq_num];
     110                 :          0 :                 rqd_ptr = ((struct rq_enet_desc *)rq->ring.descs) + rq_idx;
     111                 :            : 
     112                 :            :                 /* allocate a new mbuf */
     113                 :          0 :                 nmb = rte_mbuf_raw_alloc(rq->mp);
     114         [ #  # ]:          0 :                 if (nmb == NULL) {
     115                 :          0 :                         rte_atomic64_inc(&enic->soft_stats.rx_nombuf);
     116                 :            :                         break;
     117                 :            :                 }
     118                 :            : 
     119                 :            :                 /* A packet error means descriptor and data are untrusted */
     120                 :            :                 packet_error = enic_cq_rx_check_err(&cqd);
     121                 :            : 
     122                 :            :                 /* Get the mbuf to return and replace with one just allocated */
     123                 :          0 :                 rxmb = rq->mbuf_ring[rq_idx];
     124                 :          0 :                 rq->mbuf_ring[rq_idx] = nmb;
     125                 :          0 :                 cq_idx++;
     126                 :            : 
     127                 :            :                 /* Prefetch next mbuf & desc while processing current one */
     128                 :          0 :                 cqd_ptr = (struct cq_desc *)((uintptr_t)(cq->ring.descs) +
     129                 :          0 :                                              (uintptr_t)cq_idx * desc_size);
     130                 :            :                 rte_enic_prefetch(cqd_ptr);
     131                 :            : 
     132                 :            :                 ciflags = enic_cq_rx_desc_ciflags(
     133                 :            :                         (struct cq_enet_rq_desc *)&cqd);
     134                 :            : 
     135                 :            :                 /* Push descriptor for newly allocated mbuf */
     136                 :          0 :                 nmb->data_off = RTE_PKTMBUF_HEADROOM;
     137                 :            :                 /*
     138                 :            :                  * Only the address needs to be refilled. length_type of the
     139                 :            :                  * descriptor it set during initialization
     140                 :            :                  * (enic_alloc_rx_queue_mbufs) and does not change.
     141                 :            :                  */
     142         [ #  # ]:          0 :                 rqd_ptr->address = rte_cpu_to_le_64(nmb->buf_iova +
     143                 :            :                                                     RTE_PKTMBUF_HEADROOM);
     144                 :            : 
     145                 :            :                 /* Fill in the rest of the mbuf */
     146                 :            :                 seg_length = enic_cq_rx_desc_n_bytes(&cqd);
     147                 :            : 
     148         [ #  # ]:          0 :                 if (rq->is_sop) {
     149                 :            :                         first_seg = rxmb;
     150                 :          0 :                         first_seg->pkt_len = seg_length;
     151                 :            :                 } else {
     152                 :          0 :                         first_seg->pkt_len = (uint16_t)(first_seg->pkt_len
     153                 :            :                                                         + seg_length);
     154                 :          0 :                         first_seg->nb_segs++;
     155                 :          0 :                         last_seg->next = rxmb;
     156                 :            :                 }
     157                 :            : 
     158                 :          0 :                 rxmb->port = enic->port_id;
     159                 :          0 :                 rxmb->data_len = seg_length;
     160                 :            : 
     161                 :          0 :                 bytes += seg_length;
     162                 :            : 
     163                 :          0 :                 rq->rx_nb_hold++;
     164                 :            : 
     165         [ #  # ]:          0 :                 if (!(enic_cq_rx_desc_eop(ciflags))) {
     166                 :            :                         last_seg = rxmb;
     167                 :          0 :                         continue;
     168                 :            :                 }
     169                 :            : 
     170                 :            :                 /*
     171                 :            :                  * When overlay offload is enabled, CQ.fcoe indicates the
     172                 :            :                  * packet is tunnelled.
     173                 :            :                  */
     174   [ #  #  #  # ]:          0 :                 tnl = enic->overlay_offload &&
     175                 :            :                         (ciflags & CQ_ENET_RQ_DESC_FLAGS_FCOE) != 0;
     176                 :            :                 /* cq rx flags are only valid if eop bit is set */
     177                 :          0 :                 first_seg->packet_type =
     178                 :            :                         enic_cq_rx_flags_to_pkt_type(&cqd, tnl);
     179                 :          0 :                 enic_cq_rx_to_pkt_flags(&cqd, first_seg);
     180                 :            : 
     181                 :            :                 /* Wipe the outer types set by enic_cq_rx_flags_to_pkt_type() */
     182         [ #  # ]:          0 :                 if (tnl) {
     183                 :          0 :                         first_seg->packet_type &= ~(RTE_PTYPE_L3_MASK |
     184                 :            :                                                     RTE_PTYPE_L4_MASK);
     185                 :            :                 }
     186         [ #  # ]:          0 :                 if (unlikely(packet_error)) {
     187                 :          0 :                         rte_pktmbuf_free(first_seg);
     188                 :          0 :                         rte_atomic64_inc(&enic->soft_stats.rx_packet_errors);
     189                 :          0 :                         continue;
     190                 :            :                 }
     191                 :            : 
     192                 :            : 
     193                 :            :                 /* prefetch mbuf data for caller */
     194                 :          0 :                 rte_packet_prefetch(RTE_PTR_ADD(first_seg->buf_addr,
     195                 :            :                                     RTE_PKTMBUF_HEADROOM));
     196                 :            : 
     197                 :            :                 /* store the mbuf address into the next entry of the array */
     198                 :          0 :                 rx_pkts[nb_rx++] = first_seg;
     199                 :            :         }
     200         [ #  # ]:          0 :         if (unlikely(cq_idx == cq->ring.desc_count)) {
     201                 :            :                 cq_idx = 0;
     202                 :          0 :                 cq->last_color ^= CQ_DESC_COLOR_MASK_NOSHIFT;
     203                 :            :         }
     204                 :            : 
     205                 :          0 :         sop_rq->pkt_first_seg = first_seg;
     206                 :          0 :         sop_rq->pkt_last_seg = last_seg;
     207                 :            : 
     208                 :          0 :         cq->to_clean = cq_idx;
     209                 :            : 
     210                 :          0 :         if ((sop_rq->rx_nb_hold + data_rq->rx_nb_hold) >
     211         [ #  # ]:          0 :             sop_rq->rx_free_thresh) {
     212         [ #  # ]:          0 :                 if (data_rq->in_use) {
     213                 :          0 :                         data_rq->posted_index =
     214         [ #  # ]:          0 :                                 enic_ring_add(data_rq->ring.desc_count,
     215                 :            :                                               data_rq->posted_index,
     216                 :            :                                               data_rq->rx_nb_hold);
     217                 :          0 :                         data_rq->rx_nb_hold = 0;
     218                 :            :                 }
     219                 :          0 :                 sop_rq->posted_index = enic_ring_add(sop_rq->ring.desc_count,
     220                 :            :                                                      sop_rq->posted_index,
     221         [ #  # ]:          0 :                                                      sop_rq->rx_nb_hold);
     222                 :          0 :                 sop_rq->rx_nb_hold = 0;
     223                 :            : 
     224                 :            :                 rte_mb();
     225         [ #  # ]:          0 :                 if (data_rq->in_use)
     226                 :          0 :                         iowrite32_relaxed(data_rq->posted_index,
     227                 :          0 :                                           &data_rq->ctrl->posted_index);
     228                 :          0 :                 rte_compiler_barrier();
     229                 :          0 :                 iowrite32_relaxed(sop_rq->posted_index,
     230                 :          0 :                                   &sop_rq->ctrl->posted_index);
     231                 :            :         }
     232                 :            : 
     233   [ #  #  #  # ]:          0 :         if (enic->sriov_vf_soft_rx_stats && bytes) {
     234                 :          0 :                 sop_rq->soft_stats_pkts += nb_rx;
     235                 :          0 :                 sop_rq->soft_stats_bytes += bytes;
     236                 :            :         }
     237                 :            : 
     238                 :          0 :         return nb_rx;
     239                 :            : }
     240                 :            : 
     241                 :            : uint16_t
     242                 :          0 : enic_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
     243                 :            : {
     244                 :          0 :         return enic_recv_pkts_common(rx_queue, rx_pkts, nb_pkts, false);
     245                 :            : }
     246                 :            : 
     247                 :            : uint16_t
     248                 :          0 : enic_recv_pkts_64(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
     249                 :            : {
     250                 :          0 :         return enic_recv_pkts_common(rx_queue, rx_pkts, nb_pkts, true);
     251                 :            : }
     252                 :            : 
     253                 :            : uint16_t
     254                 :          0 : enic_noscatter_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
     255                 :            :                          uint16_t nb_pkts)
     256                 :            : {
     257                 :            :         struct rte_mbuf *mb, **rx, **rxmb;
     258                 :            :         uint16_t cq_idx, nb_rx, max_rx;
     259                 :            :         struct cq_enet_rq_desc *cqd;
     260                 :            :         struct rq_enet_desc *rqd;
     261                 :            :         unsigned int port_id;
     262                 :            :         struct vnic_cq *cq;
     263                 :            :         struct vnic_rq *rq;
     264                 :            :         struct enic *enic;
     265                 :            :         uint8_t color;
     266                 :            :         bool overlay;
     267                 :            :         bool tnl;
     268                 :            :         uint64_t bytes;
     269                 :            : 
     270                 :            :         rq = rx_queue;
     271                 :          0 :         enic = vnic_dev_priv(rq->vdev);
     272                 :          0 :         cq = &enic->cq[enic_cq_rq(enic, rq->index)];
     273                 :          0 :         cq_idx = cq->to_clean;
     274                 :            : 
     275                 :            :         /*
     276                 :            :          * Fill up the reserve of free mbufs. Below, we restock the receive
     277                 :            :          * ring with these mbufs to avoid allocation failures.
     278                 :            :          */
     279         [ #  # ]:          0 :         if (rq->num_free_mbufs == 0) {
     280   [ #  #  #  # ]:          0 :                 if (rte_mempool_get_bulk(rq->mp, (void **)rq->free_mbufs,
     281                 :            :                                          ENIC_RX_BURST_MAX))
     282                 :            :                         return 0;
     283                 :          0 :                 rq->num_free_mbufs = ENIC_RX_BURST_MAX;
     284                 :            :         }
     285                 :            : 
     286                 :            :         /* Receive until the end of the ring, at most. */
     287                 :          0 :         max_rx = RTE_MIN(nb_pkts, rq->num_free_mbufs);
     288                 :          0 :         max_rx = RTE_MIN(max_rx, cq->ring.desc_count - cq_idx);
     289                 :            : 
     290                 :          0 :         cqd = (struct cq_enet_rq_desc *)(cq->ring.descs) + cq_idx;
     291                 :          0 :         color = cq->last_color;
     292                 :          0 :         rxmb = rq->mbuf_ring + cq_idx;
     293                 :          0 :         port_id = enic->port_id;
     294                 :          0 :         overlay = enic->overlay_offload;
     295                 :            : 
     296                 :            :         bytes = 0;
     297                 :            : 
     298                 :            :         rx = rx_pkts;
     299         [ #  # ]:          0 :         while (max_rx) {
     300                 :          0 :                 max_rx--;
     301         [ #  # ]:          0 :                 if ((cqd->type_color & CQ_DESC_COLOR_MASK_NOSHIFT) == color)
     302                 :            :                         break;
     303         [ #  # ]:          0 :                 if (unlikely(cqd->bytes_written_flags &
     304                 :            :                              CQ_ENET_RQ_DESC_FLAGS_TRUNCATED)) {
     305                 :          0 :                         rte_pktmbuf_free(*rxmb++);
     306                 :          0 :                         rte_atomic64_inc(&enic->soft_stats.rx_packet_errors);
     307                 :          0 :                         cqd++;
     308                 :          0 :                         continue;
     309                 :            :                 }
     310                 :            : 
     311                 :          0 :                 mb = *rxmb++;
     312                 :            :                 /* prefetch mbuf data for caller */
     313                 :          0 :                 rte_packet_prefetch(RTE_PTR_ADD(mb->buf_addr,
     314                 :            :                                     RTE_PKTMBUF_HEADROOM));
     315                 :          0 :                 mb->data_len = cqd->bytes_written_flags &
     316                 :            :                         CQ_ENET_RQ_DESC_BYTES_WRITTEN_MASK;
     317                 :          0 :                 mb->pkt_len = mb->data_len;
     318                 :          0 :                 mb->port = port_id;
     319                 :            : 
     320                 :          0 :                 bytes += mb->pkt_len;
     321                 :            : 
     322   [ #  #  #  # ]:          0 :                 tnl = overlay && (cqd->completed_index_flags &
     323                 :            :                                   CQ_ENET_RQ_DESC_FLAGS_FCOE) != 0;
     324                 :          0 :                 mb->packet_type =
     325                 :            :                         enic_cq_rx_flags_to_pkt_type((struct cq_desc *)cqd,
     326                 :            :                                                      tnl);
     327                 :          0 :                 enic_cq_rx_to_pkt_flags((struct cq_desc *)cqd, mb);
     328                 :            :                 /* Wipe the outer types set by enic_cq_rx_flags_to_pkt_type() */
     329         [ #  # ]:          0 :                 if (tnl) {
     330                 :          0 :                         mb->packet_type &= ~(RTE_PTYPE_L3_MASK |
     331                 :            :                                              RTE_PTYPE_L4_MASK);
     332                 :            :                 }
     333                 :          0 :                 cqd++;
     334                 :          0 :                 *rx++ = mb;
     335                 :            :         }
     336                 :            :         /* Number of descriptors visited */
     337                 :          0 :         nb_rx = cqd - (struct cq_enet_rq_desc *)(cq->ring.descs) - cq_idx;
     338         [ #  # ]:          0 :         if (nb_rx == 0)
     339                 :            :                 return 0;
     340                 :          0 :         rqd = ((struct rq_enet_desc *)rq->ring.descs) + cq_idx;
     341                 :          0 :         rxmb = rq->mbuf_ring + cq_idx;
     342                 :            :         cq_idx += nb_rx;
     343                 :          0 :         rq->rx_nb_hold += nb_rx;
     344         [ #  # ]:          0 :         if (unlikely(cq_idx == cq->ring.desc_count)) {
     345                 :            :                 cq_idx = 0;
     346                 :          0 :                 cq->last_color ^= CQ_DESC_COLOR_MASK_NOSHIFT;
     347                 :            :         }
     348                 :          0 :         cq->to_clean = cq_idx;
     349                 :            : 
     350                 :          0 :         memcpy(rxmb, rq->free_mbufs + ENIC_RX_BURST_MAX - rq->num_free_mbufs,
     351                 :            :                sizeof(struct rte_mbuf *) * nb_rx);
     352                 :          0 :         rq->num_free_mbufs -= nb_rx;
     353         [ #  # ]:          0 :         while (nb_rx) {
     354                 :          0 :                 nb_rx--;
     355                 :          0 :                 mb = *rxmb++;
     356                 :          0 :                 mb->data_off = RTE_PKTMBUF_HEADROOM;
     357                 :          0 :                 rqd->address = mb->buf_iova + RTE_PKTMBUF_HEADROOM;
     358                 :          0 :                 rqd++;
     359                 :            :         }
     360         [ #  # ]:          0 :         if (rq->rx_nb_hold > rq->rx_free_thresh) {
     361         [ #  # ]:          0 :                 rq->posted_index = enic_ring_add(rq->ring.desc_count,
     362                 :            :                                                  rq->posted_index,
     363                 :            :                                                  rq->rx_nb_hold);
     364                 :          0 :                 rq->rx_nb_hold = 0;
     365                 :            :                 rte_wmb();
     366                 :          0 :                 iowrite32_relaxed(rq->posted_index,
     367                 :          0 :                                   &rq->ctrl->posted_index);
     368                 :            :         }
     369                 :            : 
     370   [ #  #  #  # ]:          0 :         if (enic->sriov_vf_soft_rx_stats && bytes) {
     371                 :          0 :                 rq->soft_stats_pkts += (rx - rx_pkts);
     372                 :          0 :                 rq->soft_stats_bytes += bytes;
     373                 :            :         }
     374                 :            : 
     375                 :          0 :         return rx - rx_pkts;
     376                 :            : }
     377                 :            : 
     378                 :          0 : static inline void enic_free_wq_bufs(struct vnic_wq *wq,
     379                 :            :                                      uint16_t completed_index)
     380                 :            : {
     381                 :            :         struct rte_mbuf *buf;
     382                 :            :         struct rte_mbuf *m, *free[ENIC_LEGACY_MAX_WQ_DESCS];
     383                 :            :         unsigned int nb_to_free, nb_free = 0, i;
     384                 :            :         struct rte_mempool *pool;
     385                 :            :         unsigned int tail_idx;
     386                 :          0 :         unsigned int desc_count = wq->ring.desc_count;
     387                 :            : 
     388                 :            :         /*
     389                 :            :          * On 1500 Series VIC and beyond, greater than ENIC_LEGACY_MAX_WQ_DESCS
     390                 :            :          * may be attempted to be freed. Cap it at ENIC_LEGACY_MAX_WQ_DESCS.
     391                 :            :          */
     392         [ #  # ]:          0 :         nb_to_free = RTE_MIN(enic_ring_sub(desc_count, wq->tail_idx,
     393                 :            :                              completed_index) + 1,
     394                 :            :                              (uint32_t)ENIC_LEGACY_MAX_WQ_DESCS);
     395                 :            :         tail_idx = wq->tail_idx;
     396                 :          0 :         pool = wq->bufs[tail_idx]->pool;
     397         [ #  # ]:          0 :         for (i = 0; i < nb_to_free; i++) {
     398                 :          0 :                 buf = wq->bufs[tail_idx];
     399                 :            :                 m = rte_pktmbuf_prefree_seg(buf);
     400         [ #  # ]:          0 :                 if (unlikely(m == NULL)) {
     401                 :            :                         tail_idx = enic_ring_incr(desc_count, tail_idx);
     402                 :          0 :                         continue;
     403                 :            :                 }
     404                 :            : 
     405         [ #  # ]:          0 :                 if (likely(m->pool == pool)) {
     406                 :            :                         RTE_ASSERT(nb_free < ENIC_LEGACY_MAX_WQ_DESCS);
     407                 :          0 :                         free[nb_free++] = m;
     408                 :            :                 } else {
     409                 :            :                         rte_mempool_put_bulk(pool, (void *)free, nb_free);
     410                 :          0 :                         free[0] = m;
     411                 :            :                         nb_free = 1;
     412                 :          0 :                         pool = m->pool;
     413                 :            :                 }
     414                 :            :                 tail_idx = enic_ring_incr(desc_count, tail_idx);
     415                 :            :         }
     416                 :            : 
     417         [ #  # ]:          0 :         if (nb_free > 0)
     418                 :            :                 rte_mempool_put_bulk(pool, (void **)free, nb_free);
     419                 :            : 
     420                 :          0 :         wq->tail_idx = tail_idx;
     421                 :          0 :         wq->ring.desc_avail += nb_to_free;
     422                 :          0 : }
     423                 :            : 
     424                 :          0 : unsigned int enic_cleanup_wq(__rte_unused struct enic *enic, struct vnic_wq *wq)
     425                 :            : {
     426                 :            :         uint16_t completed_index;
     427                 :            : 
     428                 :          0 :         completed_index = *((uint32_t *)wq->cqmsg_rz->addr) & 0xffff;
     429                 :            : 
     430         [ #  # ]:          0 :         if (wq->last_completed_index != completed_index) {
     431                 :          0 :                 enic_free_wq_bufs(wq, completed_index);
     432                 :          0 :                 wq->last_completed_index = completed_index;
     433                 :            :         }
     434                 :          0 :         return 0;
     435                 :            : }
     436                 :            : 
     437                 :          0 : uint16_t enic_prep_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
     438                 :            :                         uint16_t nb_pkts)
     439                 :            : {
     440                 :            :         struct vnic_wq *wq = (struct vnic_wq *)tx_queue;
     441                 :            :         int32_t ret;
     442                 :            :         uint16_t i;
     443                 :            :         uint64_t ol_flags;
     444                 :            :         struct rte_mbuf *m;
     445                 :            : 
     446         [ #  # ]:          0 :         for (i = 0; i != nb_pkts; i++) {
     447                 :          0 :                 m = tx_pkts[i];
     448                 :          0 :                 ol_flags = m->ol_flags;
     449         [ #  # ]:          0 :                 if (!(ol_flags & RTE_MBUF_F_TX_TCP_SEG)) {
     450         [ #  # ]:          0 :                         if (unlikely(m->pkt_len > ENIC_TX_MAX_PKT_SIZE)) {
     451                 :          0 :                                 rte_errno = EINVAL;
     452                 :          0 :                                 return i;
     453                 :            :                         }
     454                 :            :                 } else {
     455                 :            :                         uint16_t header_len;
     456                 :            : 
     457                 :          0 :                         header_len = m->l2_len + m->l3_len + m->l4_len;
     458         [ #  # ]:          0 :                         if (m->tso_segsz + header_len > ENIC_TX_MAX_PKT_SIZE) {
     459                 :          0 :                                 rte_errno = EINVAL;
     460                 :          0 :                                 return i;
     461                 :            :                         }
     462                 :            :                 }
     463                 :            : 
     464         [ #  # ]:          0 :                 if (ol_flags & wq->tx_offload_notsup_mask) {
     465                 :          0 :                         rte_errno = ENOTSUP;
     466                 :          0 :                         return i;
     467                 :            :                 }
     468                 :            : #ifdef RTE_LIBRTE_ETHDEV_DEBUG
     469                 :            :                 ret = rte_validate_tx_offload(m);
     470                 :            :                 if (ret != 0) {
     471                 :            :                         rte_errno = -ret;
     472                 :            :                         return i;
     473                 :            :                 }
     474                 :            : #endif
     475                 :            :                 ret = rte_net_intel_cksum_prepare(m);
     476         [ #  # ]:          0 :                 if (ret != 0) {
     477                 :          0 :                         rte_errno = -ret;
     478                 :          0 :                         return i;
     479                 :            :                 }
     480                 :            :         }
     481                 :            : 
     482                 :            :         return i;
     483                 :            : }
     484                 :            : 
     485                 :          0 : uint16_t enic_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
     486                 :            :         uint16_t nb_pkts)
     487                 :            : {
     488                 :            :         uint16_t index;
     489                 :            :         unsigned int pkt_len, data_len;
     490                 :            :         unsigned int nb_segs;
     491                 :            :         struct rte_mbuf *tx_pkt;
     492                 :            :         struct vnic_wq *wq = (struct vnic_wq *)tx_queue;
     493                 :          0 :         struct enic *enic = vnic_dev_priv(wq->vdev);
     494                 :            :         unsigned short vlan_id;
     495                 :            :         uint64_t ol_flags;
     496                 :            :         uint64_t ol_flags_mask;
     497                 :            :         unsigned int wq_desc_avail;
     498                 :            :         int head_idx;
     499                 :            :         unsigned int desc_count;
     500                 :            :         struct wq_enet_desc *descs, *desc_p, desc_tmp;
     501                 :            :         uint16_t mss;
     502                 :            :         uint8_t vlan_tag_insert;
     503                 :            :         uint8_t eop, cq;
     504                 :            :         uint64_t bus_addr;
     505                 :            :         uint8_t offload_mode;
     506                 :            :         uint16_t header_len;
     507                 :            :         uint64_t tso;
     508                 :            :         rte_atomic64_t *tx_oversized;
     509                 :            : 
     510                 :          0 :         enic_cleanup_wq(enic, wq);
     511                 :            :         wq_desc_avail = vnic_wq_desc_avail(wq);
     512                 :          0 :         head_idx = wq->head_idx;
     513                 :          0 :         desc_count = wq->ring.desc_count;
     514                 :            :         ol_flags_mask = RTE_MBUF_F_TX_VLAN | RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_L4_MASK;
     515                 :          0 :         tx_oversized = &enic->soft_stats.tx_oversized;
     516                 :            : 
     517                 :          0 :         nb_pkts = RTE_MIN(nb_pkts, ENIC_TX_XMIT_MAX);
     518                 :            : 
     519         [ #  # ]:          0 :         for (index = 0; index < nb_pkts; index++) {
     520                 :          0 :                 tx_pkt = *tx_pkts++;
     521                 :          0 :                 pkt_len = tx_pkt->pkt_len;
     522                 :          0 :                 data_len = tx_pkt->data_len;
     523                 :          0 :                 ol_flags = tx_pkt->ol_flags;
     524                 :          0 :                 nb_segs = tx_pkt->nb_segs;
     525                 :          0 :                 tso = ol_flags & RTE_MBUF_F_TX_TCP_SEG;
     526                 :            : 
     527                 :            :                 /* drop packet if it's too big to send */
     528         [ #  # ]:          0 :                 if (unlikely(!tso && pkt_len > ENIC_TX_MAX_PKT_SIZE)) {
     529                 :          0 :                         rte_pktmbuf_free(tx_pkt);
     530                 :            :                         rte_atomic64_inc(tx_oversized);
     531                 :          0 :                         continue;
     532                 :            :                 }
     533                 :            : 
     534         [ #  # ]:          0 :                 if (nb_segs > wq_desc_avail) {
     535         [ #  # ]:          0 :                         if (index > 0)
     536                 :          0 :                                 goto post;
     537                 :          0 :                         goto done;
     538                 :            :                 }
     539                 :            : 
     540                 :            :                 mss = 0;
     541                 :          0 :                 vlan_id = tx_pkt->vlan_tci;
     542                 :          0 :                 vlan_tag_insert = !!(ol_flags & RTE_MBUF_F_TX_VLAN);
     543                 :          0 :                 bus_addr = (dma_addr_t)
     544                 :          0 :                            (tx_pkt->buf_iova + tx_pkt->data_off);
     545                 :            : 
     546                 :          0 :                 descs = (struct wq_enet_desc *)wq->ring.descs;
     547                 :          0 :                 desc_p = descs + head_idx;
     548                 :            : 
     549                 :          0 :                 eop = (data_len == pkt_len);
     550                 :            :                 offload_mode = WQ_ENET_OFFLOAD_MODE_CSUM;
     551                 :            :                 header_len = 0;
     552                 :            : 
     553         [ #  # ]:          0 :                 if (tso) {
     554                 :          0 :                         header_len = tx_pkt->l2_len + tx_pkt->l3_len +
     555                 :          0 :                                      tx_pkt->l4_len;
     556                 :            : 
     557                 :            :                         /* Drop if non-TCP packet or TSO seg size is too big */
     558   [ #  #  #  # ]:          0 :                         if (unlikely(header_len == 0 || ((tx_pkt->tso_segsz +
     559                 :            :                             header_len) > ENIC_TX_MAX_PKT_SIZE))) {
     560                 :          0 :                                 rte_pktmbuf_free(tx_pkt);
     561                 :            :                                 rte_atomic64_inc(tx_oversized);
     562                 :          0 :                                 continue;
     563                 :            :                         }
     564                 :            : 
     565                 :            :                         offload_mode = WQ_ENET_OFFLOAD_MODE_TSO;
     566                 :            :                         mss = tx_pkt->tso_segsz;
     567                 :            :                         /* For tunnel, need the size of outer+inner headers */
     568         [ #  # ]:          0 :                         if (ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) {
     569                 :          0 :                                 header_len += tx_pkt->outer_l2_len +
     570                 :          0 :                                         tx_pkt->outer_l3_len;
     571                 :            :                         }
     572                 :            :                 }
     573                 :            : 
     574   [ #  #  #  # ]:          0 :                 if ((ol_flags & ol_flags_mask) && (header_len == 0)) {
     575         [ #  # ]:          0 :                         if (ol_flags & RTE_MBUF_F_TX_IP_CKSUM)
     576                 :          0 :                                 mss |= ENIC_CALC_IP_CKSUM;
     577                 :            : 
     578                 :            :                         /* Nic uses just 1 bit for UDP and TCP */
     579         [ #  # ]:          0 :                         switch (ol_flags & RTE_MBUF_F_TX_L4_MASK) {
     580                 :          0 :                         case RTE_MBUF_F_TX_TCP_CKSUM:
     581                 :            :                         case RTE_MBUF_F_TX_UDP_CKSUM:
     582                 :          0 :                                 mss |= ENIC_CALC_TCP_UDP_CKSUM;
     583                 :          0 :                                 break;
     584                 :            :                         }
     585                 :            :                 }
     586                 :          0 :                 wq->cq_pend++;
     587                 :            :                 cq = 0;
     588   [ #  #  #  # ]:          0 :                 if (eop && wq->cq_pend >= ENIC_WQ_CQ_THRESH) {
     589                 :            :                         cq = 1;
     590                 :          0 :                         wq->cq_pend = 0;
     591                 :            :                 }
     592         [ #  # ]:          0 :                 wq_enet_desc_enc(&desc_tmp, bus_addr, data_len, mss, header_len,
     593                 :            :                                  offload_mode, eop, cq, 0, vlan_tag_insert,
     594                 :            :                                  vlan_id, 0);
     595                 :            : 
     596                 :          0 :                 *desc_p = desc_tmp;
     597                 :          0 :                 wq->bufs[head_idx] = tx_pkt;
     598         [ #  # ]:          0 :                 head_idx = enic_ring_incr(desc_count, head_idx);
     599                 :          0 :                 wq_desc_avail--;
     600                 :            : 
     601         [ #  # ]:          0 :                 if (!eop) {
     602         [ #  # ]:          0 :                         for (tx_pkt = tx_pkt->next; tx_pkt; tx_pkt =
     603                 :            :                             tx_pkt->next) {
     604                 :          0 :                                 data_len = tx_pkt->data_len;
     605                 :            : 
     606                 :          0 :                                 wq->cq_pend++;
     607                 :            :                                 cq = 0;
     608         [ #  # ]:          0 :                                 if (tx_pkt->next == NULL) {
     609                 :            :                                         eop = 1;
     610         [ #  # ]:          0 :                                         if (wq->cq_pend >= ENIC_WQ_CQ_THRESH) {
     611                 :            :                                                 cq = 1;
     612                 :          0 :                                                 wq->cq_pend = 0;
     613                 :            :                                         }
     614                 :            :                                 }
     615                 :          0 :                                 desc_p = descs + head_idx;
     616                 :          0 :                                 bus_addr = (dma_addr_t)(tx_pkt->buf_iova
     617                 :          0 :                                            + tx_pkt->data_off);
     618         [ #  # ]:          0 :                                 wq_enet_desc_enc((struct wq_enet_desc *)
     619                 :            :                                                  &desc_tmp, bus_addr, data_len,
     620                 :            :                                                  mss, 0, offload_mode, eop, cq,
     621                 :            :                                                  0, vlan_tag_insert, vlan_id,
     622                 :            :                                                  0);
     623                 :            : 
     624                 :          0 :                                 *desc_p = desc_tmp;
     625                 :          0 :                                 wq->bufs[head_idx] = tx_pkt;
     626         [ #  # ]:          0 :                                 head_idx = enic_ring_incr(desc_count, head_idx);
     627                 :          0 :                                 wq_desc_avail--;
     628                 :            :                         }
     629                 :            :                 }
     630                 :            :         }
     631                 :          0 :  post:
     632                 :            :         rte_wmb();
     633                 :          0 :         iowrite32_relaxed(head_idx, &wq->ctrl->posted_index);
     634                 :          0 :  done:
     635                 :          0 :         wq->ring.desc_avail = wq_desc_avail;
     636                 :          0 :         wq->head_idx = head_idx;
     637                 :            : 
     638                 :          0 :         return index;
     639                 :            : }
     640                 :            : 
     641                 :          0 : static void enqueue_simple_pkts(struct rte_mbuf **pkts,
     642                 :            :                                 struct wq_enet_desc *desc,
     643                 :            :                                 uint16_t n,
     644                 :            :                                 struct enic *enic)
     645                 :            : {
     646                 :            :         struct rte_mbuf *p;
     647                 :            :         uint16_t mss;
     648                 :            : 
     649         [ #  # ]:          0 :         while (n) {
     650                 :          0 :                 n--;
     651                 :          0 :                 p = *pkts++;
     652                 :          0 :                 desc->address = p->buf_iova + p->data_off;
     653                 :          0 :                 desc->length = p->pkt_len;
     654                 :            :                 /* VLAN insert */
     655                 :          0 :                 desc->vlan_tag = p->vlan_tci;
     656                 :          0 :                 desc->header_length_flags &=
     657                 :            :                         ((1 << WQ_ENET_FLAGS_EOP_SHIFT) |
     658                 :            :                          (1 << WQ_ENET_FLAGS_CQ_ENTRY_SHIFT));
     659         [ #  # ]:          0 :                 if (p->ol_flags & RTE_MBUF_F_TX_VLAN) {
     660                 :          0 :                         desc->header_length_flags |=
     661                 :            :                                 1 << WQ_ENET_FLAGS_VLAN_TAG_INSERT_SHIFT;
     662                 :            :                 }
     663                 :            :                 /*
     664                 :            :                  * Checksum offload. We use WQ_ENET_OFFLOAD_MODE_CSUM, which
     665                 :            :                  * is 0, so no need to set offload_mode.
     666                 :            :                  */
     667                 :            :                 mss = 0;
     668         [ #  # ]:          0 :                 if (p->ol_flags & RTE_MBUF_F_TX_IP_CKSUM)
     669                 :            :                         mss |= ENIC_CALC_IP_CKSUM << WQ_ENET_MSS_SHIFT;
     670         [ #  # ]:          0 :                 if (p->ol_flags & RTE_MBUF_F_TX_L4_MASK)
     671                 :          0 :                         mss |= ENIC_CALC_TCP_UDP_CKSUM << WQ_ENET_MSS_SHIFT;
     672                 :          0 :                 desc->mss_loopback = mss;
     673                 :            : 
     674                 :            :                 /*
     675                 :            :                  * The app should not send oversized
     676                 :            :                  * packets. tx_pkt_prepare includes a check as
     677                 :            :                  * well. But some apps ignore the device max size and
     678                 :            :                  * tx_pkt_prepare. Oversized packets cause WQ errors
     679                 :            :                  * and the NIC ends up disabling the whole WQ. So
     680                 :            :                  * truncate packets..
     681                 :            :                  */
     682         [ #  # ]:          0 :                 if (unlikely(p->pkt_len > ENIC_TX_MAX_PKT_SIZE)) {
     683                 :          0 :                         desc->length = ENIC_TX_MAX_PKT_SIZE;
     684                 :          0 :                         rte_atomic64_inc(&enic->soft_stats.tx_oversized);
     685                 :            :                 }
     686                 :          0 :                 desc++;
     687                 :            :         }
     688                 :          0 : }
     689                 :            : 
     690                 :          0 : uint16_t enic_simple_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
     691                 :            :                                uint16_t nb_pkts)
     692                 :            : {
     693                 :            :         unsigned int head_idx, desc_count;
     694                 :            :         struct wq_enet_desc *desc;
     695                 :            :         struct vnic_wq *wq;
     696                 :            :         struct enic *enic;
     697                 :            :         uint16_t rem, n;
     698                 :            : 
     699                 :            :         wq = (struct vnic_wq *)tx_queue;
     700                 :          0 :         enic = vnic_dev_priv(wq->vdev);
     701                 :          0 :         enic_cleanup_wq(enic, wq);
     702                 :            :         /* Will enqueue this many packets in this call */
     703                 :          0 :         nb_pkts = RTE_MIN(nb_pkts, wq->ring.desc_avail);
     704         [ #  # ]:          0 :         if (nb_pkts == 0)
     705                 :            :                 return 0;
     706                 :            : 
     707                 :          0 :         head_idx = wq->head_idx;
     708                 :          0 :         desc_count = wq->ring.desc_count;
     709                 :            : 
     710                 :            :         /* Descriptors until the end of the ring */
     711                 :          0 :         n = desc_count - head_idx;
     712                 :          0 :         n = RTE_MIN(nb_pkts, n);
     713                 :            : 
     714                 :            :         /* Save mbuf pointers to free later */
     715                 :          0 :         memcpy(wq->bufs + head_idx, tx_pkts, sizeof(struct rte_mbuf *) * n);
     716                 :            : 
     717                 :            :         /* Enqueue until the ring end */
     718                 :          0 :         rem = nb_pkts - n;
     719                 :          0 :         desc = ((struct wq_enet_desc *)wq->ring.descs) + head_idx;
     720                 :          0 :         enqueue_simple_pkts(tx_pkts, desc, n, enic);
     721                 :            : 
     722                 :            :         /* Wrap to the start of the ring */
     723         [ #  # ]:          0 :         if (rem) {
     724                 :          0 :                 tx_pkts += n;
     725                 :          0 :                 memcpy(wq->bufs, tx_pkts, sizeof(struct rte_mbuf *) * rem);
     726                 :          0 :                 desc = (struct wq_enet_desc *)wq->ring.descs;
     727                 :          0 :                 enqueue_simple_pkts(tx_pkts, desc, rem, enic);
     728                 :            :         }
     729                 :            :         rte_wmb();
     730                 :            : 
     731                 :            :         /* Update head_idx and desc_avail */
     732                 :          0 :         wq->ring.desc_avail -= nb_pkts;
     733                 :          0 :         head_idx += nb_pkts;
     734         [ #  # ]:          0 :         if (head_idx >= desc_count)
     735                 :          0 :                 head_idx -= desc_count;
     736                 :          0 :         wq->head_idx = head_idx;
     737                 :          0 :         iowrite32_relaxed(head_idx, &wq->ctrl->posted_index);
     738                 :          0 :         return nb_pkts;
     739                 :            : }

Generated by: LCOV version 1.14