LCOV - code coverage report
Current view: top level - drivers/net/sfc - sfc_ef100_rx.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 320 0.0 %
Date: 2025-01-02 22:41:34 Functions: 0 22 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 152 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *
       3                 :            :  * Copyright(c) 2019-2021 Xilinx, Inc.
       4                 :            :  * Copyright(c) 2018-2019 Solarflare Communications Inc.
       5                 :            :  *
       6                 :            :  * This software was jointly developed between OKTET Labs (under contract
       7                 :            :  * for Solarflare) and Solarflare Communications, Inc.
       8                 :            :  */
       9                 :            : 
      10                 :            : /* EF100 native datapath implementation */
      11                 :            : 
      12                 :            : #include <stdbool.h>
      13                 :            : 
      14                 :            : #include <rte_byteorder.h>
      15                 :            : #include <rte_mbuf_ptype.h>
      16                 :            : #include <rte_mbuf.h>
      17                 :            : #include <rte_io.h>
      18                 :            : 
      19                 :            : #include "efx_types.h"
      20                 :            : #include "efx_regs_ef100.h"
      21                 :            : #include "efx.h"
      22                 :            : 
      23                 :            : #include "sfc.h"
      24                 :            : #include "sfc_debug.h"
      25                 :            : #include "sfc_flow_tunnel.h"
      26                 :            : #include "sfc_tweak.h"
      27                 :            : #include "sfc_dp_rx.h"
      28                 :            : #include "sfc_kvargs.h"
      29                 :            : #include "sfc_ef100.h"
      30                 :            : #include "sfc_nic_dma_dp.h"
      31                 :            : 
      32                 :            : 
      33                 :            : #define sfc_ef100_rx_err(_rxq, ...) \
      34                 :            :         SFC_DP_LOG(SFC_KVARG_DATAPATH_EF100, ERR, &(_rxq)->dp.dpq, __VA_ARGS__)
      35                 :            : 
      36                 :            : #define sfc_ef100_rx_debug(_rxq, ...) \
      37                 :            :         SFC_DP_LOG(SFC_KVARG_DATAPATH_EF100, DEBUG, &(_rxq)->dp.dpq, \
      38                 :            :                    __VA_ARGS__)
      39                 :            : 
      40                 :            : /**
      41                 :            :  * Maximum number of descriptors/buffers in the Rx ring.
      42                 :            :  * It should guarantee that corresponding event queue never overfill.
      43                 :            :  * EF10 native datapath uses event queue of the same size as Rx queue.
      44                 :            :  * Maximum number of events on datapath can be estimated as number of
      45                 :            :  * Rx queue entries (one event per Rx buffer in the worst case) plus
      46                 :            :  * Rx error and flush events.
      47                 :            :  */
      48                 :            : #define SFC_EF100_RXQ_LIMIT(_ndesc) \
      49                 :            :         ((_ndesc) - 1 /* head must not step on tail */ - \
      50                 :            :          1 /* Rx error */ - 1 /* flush */)
      51                 :            : 
      52                 :            : /** Invalid user mark value when the mark should be treated as unset */
      53                 :            : #define SFC_EF100_USER_MARK_INVALID     0
      54                 :            : 
      55                 :            : struct sfc_ef100_rx_sw_desc {
      56                 :            :         struct rte_mbuf                 *mbuf;
      57                 :            : };
      58                 :            : 
      59                 :            : struct sfc_ef100_rxq {
      60                 :            :         /* Used on data path */
      61                 :            :         unsigned int                    flags;
      62                 :            : #define SFC_EF100_RXQ_STARTED           0x1
      63                 :            : #define SFC_EF100_RXQ_NOT_RUNNING       0x2
      64                 :            : #define SFC_EF100_RXQ_EXCEPTION         0x4
      65                 :            : #define SFC_EF100_RXQ_RSS_HASH          0x10
      66                 :            : #define SFC_EF100_RXQ_USER_MARK         0x20
      67                 :            : #define SFC_EF100_RXQ_FLAG_INTR_EN      0x40
      68                 :            : #define SFC_EF100_RXQ_INGRESS_MPORT     0x80
      69                 :            : #define SFC_EF100_RXQ_USER_FLAG         0x100
      70                 :            : #define SFC_EF100_RXQ_NIC_DMA_MAP       0x200
      71                 :            : #define SFC_EF100_RXQ_VLAN_STRIPPED_TCI 0x400
      72                 :            :         unsigned int                    ptr_mask;
      73                 :            :         unsigned int                    evq_phase_bit_shift;
      74                 :            :         unsigned int                    ready_pkts;
      75                 :            :         unsigned int                    completed;
      76                 :            :         unsigned int                    evq_read_ptr;
      77                 :            :         unsigned int                    evq_read_ptr_primed;
      78                 :            :         volatile efx_qword_t            *evq_hw_ring;
      79                 :            :         struct sfc_ef100_rx_sw_desc     *sw_ring;
      80                 :            :         uint64_t                        rearm_data;
      81                 :            :         uint16_t                        buf_size;
      82                 :            :         uint16_t                        prefix_size;
      83                 :            :         uint32_t                        user_mark_mask;
      84                 :            : 
      85                 :            :         unsigned int                    evq_hw_index;
      86                 :            :         volatile void                   *evq_prime;
      87                 :            : 
      88                 :            :         /* Used on refill */
      89                 :            :         unsigned int                    added;
      90                 :            :         unsigned int                    max_fill_level;
      91                 :            :         unsigned int                    refill_threshold;
      92                 :            :         struct rte_mempool              *refill_mb_pool;
      93                 :            :         efx_qword_t                     *rxq_hw_ring;
      94                 :            :         volatile void                   *doorbell;
      95                 :            : 
      96                 :            :         /* Datapath receive queue anchor */
      97                 :            :         struct sfc_dp_rxq               dp;
      98                 :            : 
      99                 :            :         const struct sfc_nic_dma_info   *nic_dma_info;
     100                 :            : };
     101                 :            : 
     102                 :            : static inline struct sfc_ef100_rxq *
     103                 :            : sfc_ef100_rxq_by_dp_rxq(struct sfc_dp_rxq *dp_rxq)
     104                 :            : {
     105                 :          0 :         return container_of(dp_rxq, struct sfc_ef100_rxq, dp);
     106                 :            : }
     107                 :            : 
     108                 :            : static void
     109                 :            : sfc_ef100_rx_qprime(struct sfc_ef100_rxq *rxq)
     110                 :            : {
     111                 :          0 :         sfc_ef100_evq_prime(rxq->evq_prime, rxq->evq_hw_index,
     112                 :          0 :                             rxq->evq_read_ptr & rxq->ptr_mask);
     113                 :          0 :         rxq->evq_read_ptr_primed = rxq->evq_read_ptr;
     114                 :          0 : }
     115                 :            : 
     116                 :            : static inline void
     117                 :            : sfc_ef100_rx_qpush(struct sfc_ef100_rxq *rxq, unsigned int added)
     118                 :            : {
     119                 :            :         efx_dword_t dword;
     120                 :            : 
     121                 :          0 :         EFX_POPULATE_DWORD_1(dword, ERF_GZ_RX_RING_PIDX, added & rxq->ptr_mask);
     122                 :            : 
     123                 :            :         /* DMA sync to device is not required */
     124                 :            : 
     125                 :            :         /*
     126                 :            :          * rte_write32() has rte_io_wmb() which guarantees that the STORE
     127                 :            :          * operations (i.e. Rx and event descriptor updates) that precede
     128                 :            :          * the rte_io_wmb() call are visible to NIC before the STORE
     129                 :            :          * operations that follow it (i.e. doorbell write).
     130                 :            :          */
     131                 :          0 :         rte_write32(dword.ed_u32[0], rxq->doorbell);
     132                 :          0 :         rxq->dp.dpq.dbells++;
     133                 :            : 
     134                 :            :         sfc_ef100_rx_debug(rxq, "RxQ pushed doorbell at pidx %u (added=%u)",
     135                 :            :                            EFX_DWORD_FIELD(dword, ERF_GZ_RX_RING_PIDX),
     136                 :            :                            added);
     137                 :            : }
     138                 :            : 
     139                 :            : static void
     140                 :          0 : sfc_ef100_rx_qrefill(struct sfc_ef100_rxq *rxq)
     141                 :            : {
     142                 :          0 :         const unsigned int ptr_mask = rxq->ptr_mask;
     143                 :            :         unsigned int free_space;
     144                 :            :         unsigned int bulks;
     145                 :            :         void *objs[SFC_RX_REFILL_BULK];
     146                 :          0 :         unsigned int added = rxq->added;
     147                 :            : 
     148                 :          0 :         free_space = rxq->max_fill_level - (added - rxq->completed);
     149                 :            : 
     150         [ #  # ]:          0 :         if (free_space < rxq->refill_threshold)
     151                 :          0 :                 return;
     152                 :            : 
     153                 :          0 :         bulks = free_space / RTE_DIM(objs);
     154                 :            :         /* refill_threshold guarantees that bulks is positive */
     155                 :            :         SFC_ASSERT(bulks > 0);
     156                 :            : 
     157                 :            :         do {
     158                 :            :                 unsigned int i;
     159                 :            : 
     160   [ #  #  #  # ]:          0 :                 if (unlikely(rte_mempool_get_bulk(rxq->refill_mb_pool, objs,
     161                 :            :                                                   RTE_DIM(objs)) < 0)) {
     162                 :          0 :                         struct rte_eth_dev_data *dev_data =
     163                 :          0 :                                 rte_eth_devices[rxq->dp.dpq.port_id].data;
     164                 :            : 
     165                 :            :                         /*
     166                 :            :                          * It is hardly a safe way to increment counter
     167                 :            :                          * from different contexts, but all PMDs do it.
     168                 :            :                          */
     169                 :          0 :                         dev_data->rx_mbuf_alloc_failed += RTE_DIM(objs);
     170                 :            :                         /* Return if we have posted nothing yet */
     171         [ #  # ]:          0 :                         if (added == rxq->added)
     172                 :            :                                 return;
     173                 :            :                         /* Push posted */
     174                 :            :                         break;
     175                 :            :                 }
     176                 :            : 
     177         [ #  # ]:          0 :                 for (i = 0; i < RTE_DIM(objs); ++i) {
     178         [ #  # ]:          0 :                         struct rte_mbuf *m = objs[i];
     179                 :            :                         struct sfc_ef100_rx_sw_desc *rxd;
     180                 :            :                         rte_iova_t dma_addr;
     181                 :            : 
     182                 :            :                         __rte_mbuf_raw_sanity_check(m);
     183                 :            : 
     184                 :            :                         dma_addr = rte_mbuf_data_iova_default(m);
     185         [ #  # ]:          0 :                         if (rxq->flags & SFC_EF100_RXQ_NIC_DMA_MAP) {
     186                 :          0 :                                 dma_addr = sfc_nic_dma_map(rxq->nic_dma_info,
     187                 :            :                                                 dma_addr,
     188                 :          0 :                                                 rte_pktmbuf_data_len(m));
     189         [ #  # ]:          0 :                                 if (unlikely(dma_addr == RTE_BAD_IOVA)) {
     190                 :          0 :                                         sfc_ef100_rx_err(rxq,
     191                 :            :                                                 "failed to map DMA address on Rx");
     192                 :            :                                         /* Just skip buffer and try to continue */
     193         [ #  # ]:          0 :                                         rte_mempool_put(rxq->refill_mb_pool, m);
     194                 :          0 :                                         continue;
     195                 :            :                                 }
     196                 :            :                         }
     197                 :            : 
     198                 :          0 :                         rxd = &rxq->sw_ring[added & ptr_mask];
     199                 :          0 :                         rxd->mbuf = m;
     200                 :            : 
     201                 :            :                         /*
     202                 :            :                          * Avoid writing to mbuf. It is cheaper to do it
     203                 :            :                          * when we receive packet and fill in nearby
     204                 :            :                          * structure members.
     205                 :            :                          */
     206                 :            : 
     207                 :          0 :                         EFX_POPULATE_QWORD_1(rxq->rxq_hw_ring[added & ptr_mask],
     208                 :            :                             ESF_GZ_RX_BUF_ADDR, dma_addr);
     209                 :          0 :                         added++;
     210                 :            :                 }
     211         [ #  # ]:          0 :         } while (--bulks > 0);
     212                 :            : 
     213                 :            :         SFC_ASSERT(rxq->added != added);
     214                 :          0 :         rxq->added = added;
     215                 :            :         sfc_ef100_rx_qpush(rxq, added);
     216                 :            : }
     217                 :            : 
     218                 :            : static inline uint64_t
     219                 :            : sfc_ef100_rx_nt_or_inner_l4_csum(const efx_word_t class)
     220                 :            : {
     221                 :          0 :         return EFX_WORD_FIELD(class,
     222                 :            :                               ESF_GZ_RX_PREFIX_HCLASS_NT_OR_INNER_L4_CSUM) ==
     223                 :            :                 ESE_GZ_RH_HCLASS_L4_CSUM_GOOD ?
     224                 :          0 :                 RTE_MBUF_F_RX_L4_CKSUM_GOOD : RTE_MBUF_F_RX_L4_CKSUM_BAD;
     225                 :            : }
     226                 :            : 
     227                 :            : static inline uint64_t
     228                 :            : sfc_ef100_rx_tun_outer_l4_csum(const efx_word_t class)
     229                 :            : {
     230                 :          0 :         return EFX_WORD_FIELD(class,
     231                 :            :                               ESF_GZ_RX_PREFIX_HCLASS_TUN_OUTER_L4_CSUM) ==
     232                 :            :                 ESE_GZ_RH_HCLASS_L4_CSUM_GOOD ?
     233                 :          0 :                 RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD : RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD;
     234                 :            : }
     235                 :            : 
     236                 :            : static uint32_t
     237                 :          0 : sfc_ef100_rx_class_decode(const efx_word_t class, uint64_t *ol_flags)
     238                 :            : {
     239                 :            :         uint32_t ptype;
     240                 :            :         bool no_tunnel = false;
     241                 :            : 
     242         [ #  # ]:          0 :         if (unlikely(EFX_WORD_FIELD(class, ESF_GZ_RX_PREFIX_HCLASS_L2_CLASS) !=
     243                 :            :                      ESE_GZ_RH_HCLASS_L2_CLASS_E2_0123VLAN))
     244                 :            :                 return 0;
     245                 :            : 
     246      [ #  #  # ]:          0 :         switch (EFX_WORD_FIELD(class, ESF_GZ_RX_PREFIX_HCLASS_L2_N_VLAN)) {
     247                 :            :         case 0:
     248                 :            :                 ptype = RTE_PTYPE_L2_ETHER;
     249                 :            :                 break;
     250                 :          0 :         case 1:
     251                 :            :                 ptype = RTE_PTYPE_L2_ETHER_VLAN;
     252                 :          0 :                 break;
     253                 :          0 :         default:
     254                 :            :                 ptype = RTE_PTYPE_L2_ETHER_QINQ;
     255                 :          0 :                 break;
     256                 :            :         }
     257                 :            : 
     258   [ #  #  #  #  :          0 :         switch (EFX_WORD_FIELD(class, ESF_GZ_RX_PREFIX_HCLASS_TUNNEL_CLASS)) {
                      # ]
     259                 :            :         case ESE_GZ_RH_HCLASS_TUNNEL_CLASS_NONE:
     260                 :            :                 no_tunnel = true;
     261                 :            :                 break;
     262                 :          0 :         case ESE_GZ_RH_HCLASS_TUNNEL_CLASS_VXLAN:
     263         [ #  # ]:          0 :                 ptype |= RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_L4_UDP;
     264                 :          0 :                 *ol_flags |= sfc_ef100_rx_tun_outer_l4_csum(class);
     265                 :            :                 break;
     266                 :          0 :         case ESE_GZ_RH_HCLASS_TUNNEL_CLASS_NVGRE:
     267                 :          0 :                 ptype |= RTE_PTYPE_TUNNEL_NVGRE;
     268                 :            :                 break;
     269                 :          0 :         case ESE_GZ_RH_HCLASS_TUNNEL_CLASS_GENEVE:
     270         [ #  # ]:          0 :                 ptype |= RTE_PTYPE_TUNNEL_GENEVE | RTE_PTYPE_L4_UDP;
     271                 :          0 :                 *ol_flags |= sfc_ef100_rx_tun_outer_l4_csum(class);
     272                 :            :                 break;
     273                 :            :         default:
     274                 :            :                 /*
     275                 :            :                  * Driver does not know the tunnel, but it is
     276                 :            :                  * still a tunnel and NT_OR_INNER refer to inner
     277                 :            :                  * frame.
     278                 :            :                  */
     279                 :            :                 no_tunnel = false;
     280                 :            :         }
     281                 :            : 
     282                 :            :         if (no_tunnel) {
     283                 :            :                 bool l4_valid = true;
     284                 :            : 
     285   [ #  #  #  # ]:          0 :                 switch (EFX_WORD_FIELD(class,
     286                 :            :                         ESF_GZ_RX_PREFIX_HCLASS_NT_OR_INNER_L3_CLASS)) {
     287                 :          0 :                 case ESE_GZ_RH_HCLASS_L3_CLASS_IP4GOOD:
     288                 :          0 :                         ptype |= RTE_PTYPE_L3_IPV4_EXT_UNKNOWN;
     289                 :          0 :                         *ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
     290                 :            :                         break;
     291                 :          0 :                 case ESE_GZ_RH_HCLASS_L3_CLASS_IP4BAD:
     292                 :          0 :                         ptype |= RTE_PTYPE_L3_IPV4_EXT_UNKNOWN;
     293                 :          0 :                         *ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD;
     294                 :            :                         break;
     295                 :          0 :                 case ESE_GZ_RH_HCLASS_L3_CLASS_IP6:
     296                 :          0 :                         ptype |= RTE_PTYPE_L3_IPV6_EXT_UNKNOWN;
     297                 :            :                         break;
     298                 :            :                 default:
     299                 :            :                         l4_valid = false;
     300                 :            :                 }
     301                 :            : 
     302                 :            :                 if (l4_valid) {
     303   [ #  #  #  # ]:          0 :                         switch (EFX_WORD_FIELD(class,
     304                 :            :                                 ESF_GZ_RX_PREFIX_HCLASS_NT_OR_INNER_L4_CLASS)) {
     305                 :          0 :                         case ESE_GZ_RH_HCLASS_L4_CLASS_TCP:
     306         [ #  # ]:          0 :                                 ptype |= RTE_PTYPE_L4_TCP;
     307                 :          0 :                                 *ol_flags |=
     308                 :            :                                         sfc_ef100_rx_nt_or_inner_l4_csum(class);
     309                 :          0 :                                 break;
     310                 :          0 :                         case ESE_GZ_RH_HCLASS_L4_CLASS_UDP:
     311         [ #  # ]:          0 :                                 ptype |= RTE_PTYPE_L4_UDP;
     312                 :          0 :                                 *ol_flags |=
     313                 :            :                                         sfc_ef100_rx_nt_or_inner_l4_csum(class);
     314                 :          0 :                                 break;
     315                 :          0 :                         case ESE_GZ_RH_HCLASS_L4_CLASS_FRAG:
     316                 :          0 :                                 ptype |= RTE_PTYPE_L4_FRAG;
     317                 :          0 :                                 break;
     318                 :            :                         }
     319                 :            :                 }
     320                 :            :         } else {
     321                 :            :                 bool l4_valid = true;
     322                 :            : 
     323   [ #  #  #  # ]:          0 :                 switch (EFX_WORD_FIELD(class,
     324                 :            :                         ESF_GZ_RX_PREFIX_HCLASS_TUN_OUTER_L3_CLASS)) {
     325                 :          0 :                 case ESE_GZ_RH_HCLASS_L3_CLASS_IP4GOOD:
     326                 :          0 :                         ptype |= RTE_PTYPE_L3_IPV4_EXT_UNKNOWN;
     327                 :          0 :                         break;
     328                 :          0 :                 case ESE_GZ_RH_HCLASS_L3_CLASS_IP4BAD:
     329                 :          0 :                         ptype |= RTE_PTYPE_L3_IPV4_EXT_UNKNOWN;
     330                 :          0 :                         *ol_flags |= RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD;
     331                 :          0 :                         break;
     332                 :          0 :                 case ESE_GZ_RH_HCLASS_L3_CLASS_IP6:
     333                 :          0 :                         ptype |= RTE_PTYPE_L3_IPV6_EXT_UNKNOWN;
     334                 :          0 :                         break;
     335                 :            :                 }
     336                 :            : 
     337   [ #  #  #  # ]:          0 :                 switch (EFX_WORD_FIELD(class,
     338                 :            :                         ESF_GZ_RX_PREFIX_HCLASS_NT_OR_INNER_L3_CLASS)) {
     339                 :          0 :                 case ESE_GZ_RH_HCLASS_L3_CLASS_IP4GOOD:
     340                 :          0 :                         ptype |= RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN;
     341                 :          0 :                         *ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
     342                 :            :                         break;
     343                 :          0 :                 case ESE_GZ_RH_HCLASS_L3_CLASS_IP4BAD:
     344                 :          0 :                         ptype |= RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN;
     345                 :          0 :                         *ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD;
     346                 :            :                         break;
     347                 :          0 :                 case ESE_GZ_RH_HCLASS_L3_CLASS_IP6:
     348                 :          0 :                         ptype |= RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN;
     349                 :            :                         break;
     350                 :            :                 default:
     351                 :            :                         l4_valid = false;
     352                 :            :                         break;
     353                 :            :                 }
     354                 :            : 
     355                 :            :                 if (l4_valid) {
     356   [ #  #  #  # ]:          0 :                         switch (EFX_WORD_FIELD(class,
     357                 :            :                                 ESF_GZ_RX_PREFIX_HCLASS_NT_OR_INNER_L4_CLASS)) {
     358                 :          0 :                         case ESE_GZ_RH_HCLASS_L4_CLASS_TCP:
     359         [ #  # ]:          0 :                                 ptype |= RTE_PTYPE_INNER_L4_TCP;
     360                 :          0 :                                 *ol_flags |=
     361                 :            :                                         sfc_ef100_rx_nt_or_inner_l4_csum(class);
     362                 :          0 :                                 break;
     363                 :          0 :                         case ESE_GZ_RH_HCLASS_L4_CLASS_UDP:
     364         [ #  # ]:          0 :                                 ptype |= RTE_PTYPE_INNER_L4_UDP;
     365                 :          0 :                                 *ol_flags |=
     366                 :            :                                         sfc_ef100_rx_nt_or_inner_l4_csum(class);
     367                 :          0 :                                 break;
     368                 :          0 :                         case ESE_GZ_RH_HCLASS_L4_CLASS_FRAG:
     369                 :          0 :                                 ptype |= RTE_PTYPE_INNER_L4_FRAG;
     370                 :          0 :                                 break;
     371                 :            :                         }
     372                 :            :                 }
     373                 :            :         }
     374                 :            : 
     375                 :            :         return ptype;
     376                 :            : }
     377                 :            : 
     378                 :            : /*
     379                 :            :  * Below function relies on the following fields in Rx prefix.
     380                 :            :  * Some fields are mandatory, some fields are optional.
     381                 :            :  * See sfc_ef100_rx_qstart() below.
     382                 :            :  */
     383                 :            : static const efx_rx_prefix_layout_t sfc_ef100_rx_prefix_layout = {
     384                 :            :         .erpl_fields    = {
     385                 :            : #define SFC_EF100_RX_PREFIX_FIELD(_name, _big_endian) \
     386                 :            :         EFX_RX_PREFIX_FIELD(_name, ESF_GZ_RX_PREFIX_ ## _name, _big_endian)
     387                 :            : 
     388                 :            :                 SFC_EF100_RX_PREFIX_FIELD(LENGTH, B_FALSE),
     389                 :            :                 SFC_EF100_RX_PREFIX_FIELD(RSS_HASH_VALID, B_FALSE),
     390                 :            :                 SFC_EF100_RX_PREFIX_FIELD(CLASS, B_FALSE),
     391                 :            :                 EFX_RX_PREFIX_FIELD(INGRESS_MPORT,
     392                 :            :                                     ESF_GZ_RX_PREFIX_INGRESS_MPORT, B_FALSE),
     393                 :            :                 SFC_EF100_RX_PREFIX_FIELD(RSS_HASH, B_FALSE),
     394                 :            :                 SFC_EF100_RX_PREFIX_FIELD(USER_FLAG, B_FALSE),
     395                 :            :                 SFC_EF100_RX_PREFIX_FIELD(USER_MARK, B_FALSE),
     396                 :            :                 SFC_EF100_RX_PREFIX_FIELD(VLAN_STRIP_TCI, B_FALSE),
     397                 :            : 
     398                 :            : #undef  SFC_EF100_RX_PREFIX_FIELD
     399                 :            :         }
     400                 :            : };
     401                 :            : 
     402                 :            : static bool
     403                 :          0 : sfc_ef100_rx_prefix_to_offloads(const struct sfc_ef100_rxq *rxq,
     404                 :            :                                 const efx_xword_t *rx_prefix,
     405                 :            :                                 struct rte_mbuf *m)
     406                 :            : {
     407                 :            :         const efx_word_t *class;
     408                 :          0 :         uint64_t ol_flags = 0;
     409                 :            : 
     410                 :            :         RTE_BUILD_BUG_ON(EFX_LOW_BIT(ESF_GZ_RX_PREFIX_CLASS) % CHAR_BIT != 0);
     411                 :            :         RTE_BUILD_BUG_ON(EFX_WIDTH(ESF_GZ_RX_PREFIX_CLASS) % CHAR_BIT != 0);
     412                 :            :         RTE_BUILD_BUG_ON(EFX_WIDTH(ESF_GZ_RX_PREFIX_CLASS) / CHAR_BIT !=
     413                 :            :                          sizeof(*class));
     414                 :          0 :         class = (const efx_word_t *)((const uint8_t *)rx_prefix +
     415                 :            :                 EFX_LOW_BIT(ESF_GZ_RX_PREFIX_CLASS) / CHAR_BIT);
     416         [ #  # ]:          0 :         if (unlikely(EFX_WORD_FIELD(*class,
     417                 :            :                                     ESF_GZ_RX_PREFIX_HCLASS_L2_STATUS) !=
     418                 :            :                      ESE_GZ_RH_HCLASS_L2_STATUS_OK))
     419                 :            :                 return false;
     420                 :            : 
     421                 :          0 :         m->packet_type = sfc_ef100_rx_class_decode(*class, &ol_flags);
     422                 :            : 
     423         [ #  # ]:          0 :         if ((rxq->flags & SFC_EF100_RXQ_RSS_HASH) &&
     424         [ #  # ]:          0 :             EFX_TEST_XWORD_BIT(rx_prefix[0],
     425                 :            :                                ESF_GZ_RX_PREFIX_RSS_HASH_VALID_LBN)) {
     426                 :          0 :                 ol_flags |= RTE_MBUF_F_RX_RSS_HASH;
     427                 :            :                 /* EFX_XWORD_FIELD converts little-endian to CPU */
     428                 :          0 :                 m->hash.rss = EFX_XWORD_FIELD(rx_prefix[0],
     429                 :            :                                               ESF_GZ_RX_PREFIX_RSS_HASH);
     430                 :            :         }
     431                 :            : 
     432         [ #  # ]:          0 :         if (rxq->flags & SFC_EF100_RXQ_USER_FLAG) {
     433                 :            :                 uint32_t user_flag;
     434                 :            : 
     435                 :          0 :                 user_flag = EFX_XWORD_FIELD(rx_prefix[0],
     436                 :            :                                             ESF_GZ_RX_PREFIX_USER_FLAG);
     437         [ #  # ]:          0 :                 if (user_flag != 0)
     438                 :          0 :                         ol_flags |= RTE_MBUF_F_RX_FDIR;
     439                 :            :         }
     440                 :            : 
     441         [ #  # ]:          0 :         if (rxq->flags & SFC_EF100_RXQ_USER_MARK) {
     442                 :            :                 uint8_t ft_ctx_mark;
     443                 :            :                 uint32_t user_mark;
     444                 :            :                 uint32_t mark;
     445                 :            : 
     446                 :            :                 /* EFX_XWORD_FIELD converts little-endian to CPU */
     447                 :          0 :                 mark = EFX_XWORD_FIELD(rx_prefix[0],
     448                 :            :                                        ESF_GZ_RX_PREFIX_USER_MARK);
     449                 :            : 
     450                 :          0 :                 user_mark = mark & rxq->user_mark_mask;
     451         [ #  # ]:          0 :                 if (user_mark != SFC_EF100_USER_MARK_INVALID) {
     452                 :          0 :                         ol_flags |= RTE_MBUF_F_RX_FDIR | RTE_MBUF_F_RX_FDIR_ID;
     453                 :          0 :                         m->hash.fdir.hi = user_mark;
     454                 :            :                 }
     455                 :            : 
     456                 :          0 :                 ft_ctx_mark = SFC_FT_FLOW_MARK_TO_CTX_MARK(mark);
     457         [ #  # ]:          0 :                 if (ft_ctx_mark != SFC_FT_CTX_MARK_INVALID) {
     458                 :            :                         sfc_ft_ctx_id_t ft_ctx_id;
     459                 :            : 
     460                 :          0 :                         ft_ctx_id = SFC_FT_CTX_MARK_TO_CTX_ID(ft_ctx_mark);
     461                 :            : 
     462                 :          0 :                         ol_flags |= sfc_dp_ft_ctx_id_valid;
     463                 :          0 :                         *RTE_MBUF_DYNFIELD(m, sfc_dp_ft_ctx_id_offset,
     464                 :          0 :                                            sfc_ft_ctx_id_t *) = ft_ctx_id;
     465                 :            :                 }
     466                 :            :         }
     467                 :            : 
     468         [ #  # ]:          0 :         if (rxq->flags & SFC_EF100_RXQ_INGRESS_MPORT) {
     469                 :          0 :                 ol_flags |= sfc_dp_mport_override;
     470                 :          0 :                 *RTE_MBUF_DYNFIELD(m,
     471                 :            :                         sfc_dp_mport_offset,
     472                 :          0 :                         typeof(&((efx_mport_id_t *)0)->id)) =
     473                 :          0 :                                 EFX_XWORD_FIELD(rx_prefix[0],
     474                 :            :                                                 ESF_GZ_RX_PREFIX_INGRESS_MPORT);
     475                 :            :         }
     476                 :            : 
     477         [ #  # ]:          0 :         if (rxq->flags & SFC_EF100_RXQ_VLAN_STRIPPED_TCI &&
     478         [ #  # ]:          0 :             EFX_TEST_XWORD_BIT(rx_prefix[0],
     479                 :            :                                    ESF_GZ_RX_PREFIX_VLAN_STRIPPED_LBN)) {
     480                 :          0 :                 ol_flags |= RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED;
     481                 :          0 :                 m->vlan_tci = EFX_XWORD_FIELD(rx_prefix[0],
     482                 :            :                                                 ESF_GZ_RX_PREFIX_VLAN_STRIP_TCI);
     483                 :            :         }
     484                 :            : 
     485                 :          0 :         m->ol_flags = ol_flags;
     486                 :          0 :         return true;
     487                 :            : }
     488                 :            : 
     489                 :            : static const uint8_t *
     490                 :            : sfc_ef100_rx_pkt_prefix(const struct rte_mbuf *m)
     491                 :            : {
     492                 :          0 :         return (const uint8_t *)m->buf_addr + RTE_PKTMBUF_HEADROOM;
     493                 :            : }
     494                 :            : 
     495                 :            : static struct rte_mbuf *
     496                 :          0 : sfc_ef100_rx_next_mbuf(struct sfc_ef100_rxq *rxq)
     497                 :            : {
     498                 :            :         struct rte_mbuf *m;
     499                 :            :         unsigned int id;
     500                 :            : 
     501                 :            :         /* mbuf associated with current Rx descriptor */
     502                 :          0 :         m = rxq->sw_ring[rxq->completed++ & rxq->ptr_mask].mbuf;
     503                 :            : 
     504                 :            :         /* completed is already moved to the next one */
     505         [ #  # ]:          0 :         if (unlikely(rxq->completed == rxq->added))
     506                 :          0 :                 goto done;
     507                 :            : 
     508                 :            :         /*
     509                 :            :          * Prefetch Rx prefix of the next packet.
     510                 :            :          * Current packet is scattered and the next mbuf is its fragment
     511                 :            :          * it simply prefetches some data - no harm since packet rate
     512                 :            :          * should not be high if scatter is used.
     513                 :            :          */
     514                 :          0 :         id = rxq->completed & rxq->ptr_mask;
     515                 :          0 :         rte_prefetch0(sfc_ef100_rx_pkt_prefix(rxq->sw_ring[id].mbuf));
     516                 :            : 
     517         [ #  # ]:          0 :         if (unlikely(rxq->completed + 1 == rxq->added))
     518                 :          0 :                 goto done;
     519                 :            : 
     520                 :            :         /*
     521                 :            :          * Prefetch mbuf control structure of the next after next Rx
     522                 :            :          * descriptor.
     523                 :            :          */
     524         [ #  # ]:          0 :         id = (id == rxq->ptr_mask) ? 0 : (id + 1);
     525                 :          0 :         rte_mbuf_prefetch_part1(rxq->sw_ring[id].mbuf);
     526                 :            : 
     527                 :            :         /*
     528                 :            :          * If the next time we'll need SW Rx descriptor from the next
     529                 :            :          * cache line, try to make sure that we have it in cache.
     530                 :            :          */
     531         [ #  # ]:          0 :         if ((id & 0x7) == 0x7)
     532                 :          0 :                 rte_prefetch0(&rxq->sw_ring[(id + 1) & rxq->ptr_mask]);
     533                 :            : 
     534                 :          0 : done:
     535                 :          0 :         return m;
     536                 :            : }
     537                 :            : 
     538                 :            : static struct rte_mbuf **
     539                 :          0 : sfc_ef100_rx_process_ready_pkts(struct sfc_ef100_rxq *rxq,
     540                 :            :                                 struct rte_mbuf **rx_pkts,
     541                 :            :                                 struct rte_mbuf ** const rx_pkts_end)
     542                 :            : {
     543   [ #  #  #  # ]:          0 :         while (rxq->ready_pkts > 0 && rx_pkts != rx_pkts_end) {
     544                 :            :                 struct rte_mbuf *pkt;
     545                 :            :                 struct rte_mbuf *lastseg;
     546                 :            :                 const efx_xword_t *rx_prefix;
     547                 :            :                 uint16_t pkt_len;
     548                 :            :                 uint16_t seg_len;
     549                 :            :                 bool deliver;
     550                 :            : 
     551                 :          0 :                 rxq->ready_pkts--;
     552                 :            : 
     553                 :          0 :                 pkt = sfc_ef100_rx_next_mbuf(rxq);
     554                 :            :                 __rte_mbuf_raw_sanity_check(pkt);
     555                 :            : 
     556                 :            :                 RTE_BUILD_BUG_ON(sizeof(pkt->rearm_data[0]) !=
     557                 :            :                                  sizeof(rxq->rearm_data));
     558                 :          0 :                 pkt->rearm_data[0] = rxq->rearm_data;
     559                 :            : 
     560                 :            :                 /* data_off already moved past Rx prefix */
     561                 :            :                 rx_prefix = (const efx_xword_t *)sfc_ef100_rx_pkt_prefix(pkt);
     562                 :            : 
     563                 :          0 :                 pkt_len = EFX_XWORD_FIELD(rx_prefix[0],
     564                 :            :                                           ESF_GZ_RX_PREFIX_LENGTH);
     565                 :            :                 SFC_ASSERT(pkt_len > 0);
     566                 :          0 :                 rte_pktmbuf_pkt_len(pkt) = pkt_len;
     567                 :            : 
     568                 :          0 :                 seg_len = RTE_MIN(pkt_len, rxq->buf_size - rxq->prefix_size);
     569                 :          0 :                 rte_pktmbuf_data_len(pkt) = seg_len;
     570                 :            : 
     571                 :          0 :                 deliver = sfc_ef100_rx_prefix_to_offloads(rxq, rx_prefix, pkt);
     572                 :            : 
     573                 :            :                 lastseg = pkt;
     574         [ #  # ]:          0 :                 while ((pkt_len -= seg_len) > 0) {
     575                 :            :                         struct rte_mbuf *seg;
     576                 :            : 
     577                 :          0 :                         seg = sfc_ef100_rx_next_mbuf(rxq);
     578                 :            :                         __rte_mbuf_raw_sanity_check(seg);
     579                 :            : 
     580                 :          0 :                         seg->data_off = RTE_PKTMBUF_HEADROOM;
     581                 :            : 
     582                 :          0 :                         seg_len = RTE_MIN(pkt_len, rxq->buf_size);
     583                 :          0 :                         rte_pktmbuf_data_len(seg) = seg_len;
     584                 :          0 :                         rte_pktmbuf_pkt_len(seg) = seg_len;
     585                 :            : 
     586                 :          0 :                         pkt->nb_segs++;
     587                 :          0 :                         lastseg->next = seg;
     588                 :            :                         lastseg = seg;
     589                 :            :                 }
     590                 :            : 
     591         [ #  # ]:          0 :                 if (likely(deliver)) {
     592                 :          0 :                         *rx_pkts++ = pkt;
     593                 :          0 :                         sfc_pkts_bytes_add(&rxq->dp.dpq.stats, 1,
     594                 :          0 :                                            rte_pktmbuf_pkt_len(pkt));
     595                 :            :                 } else {
     596                 :          0 :                         rte_pktmbuf_free(pkt);
     597                 :            :                 }
     598                 :            :         }
     599                 :            : 
     600                 :          0 :         return rx_pkts;
     601                 :            : }
     602                 :            : 
     603                 :            : static bool
     604                 :          0 : sfc_ef100_rx_get_event(struct sfc_ef100_rxq *rxq, efx_qword_t *ev)
     605                 :            : {
     606                 :          0 :         *ev = rxq->evq_hw_ring[rxq->evq_read_ptr & rxq->ptr_mask];
     607                 :            : 
     608                 :          0 :         if (!sfc_ef100_ev_present(ev,
     609         [ #  # ]:          0 :                         (rxq->evq_read_ptr >> rxq->evq_phase_bit_shift) & 1))
     610                 :            :                 return false;
     611                 :            : 
     612         [ #  # ]:          0 :         if (unlikely(!sfc_ef100_ev_type_is(ev, ESE_GZ_EF100_EV_RX_PKTS))) {
     613                 :            :                 /*
     614                 :            :                  * Do not move read_ptr to keep the event for exception
     615                 :            :                  * handling by the control path.
     616                 :            :                  */
     617                 :          0 :                 rxq->flags |= SFC_EF100_RXQ_EXCEPTION;
     618                 :          0 :                 sfc_ef100_rx_err(rxq,
     619                 :            :                         "RxQ exception at EvQ ptr %u(%#x), event %08x:%08x",
     620                 :            :                         rxq->evq_read_ptr, rxq->evq_read_ptr & rxq->ptr_mask,
     621                 :            :                         EFX_QWORD_FIELD(*ev, EFX_DWORD_1),
     622                 :            :                         EFX_QWORD_FIELD(*ev, EFX_DWORD_0));
     623                 :          0 :                 return false;
     624                 :            :         }
     625                 :            : 
     626                 :            :         sfc_ef100_rx_debug(rxq, "RxQ got event %08x:%08x at %u (%#x)",
     627                 :            :                            EFX_QWORD_FIELD(*ev, EFX_DWORD_1),
     628                 :            :                            EFX_QWORD_FIELD(*ev, EFX_DWORD_0),
     629                 :            :                            rxq->evq_read_ptr,
     630                 :            :                            rxq->evq_read_ptr & rxq->ptr_mask);
     631                 :            : 
     632                 :          0 :         rxq->evq_read_ptr++;
     633                 :          0 :         return true;
     634                 :            : }
     635                 :            : 
     636                 :            : static uint16_t
     637                 :          0 : sfc_ef100_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
     638                 :            : {
     639                 :            :         struct sfc_ef100_rxq *rxq = sfc_ef100_rxq_by_dp_rxq(rx_queue);
     640                 :          0 :         struct rte_mbuf ** const rx_pkts_end = &rx_pkts[nb_pkts];
     641                 :            :         efx_qword_t rx_ev;
     642                 :            : 
     643                 :          0 :         rx_pkts = sfc_ef100_rx_process_ready_pkts(rxq, rx_pkts, rx_pkts_end);
     644                 :            : 
     645         [ #  # ]:          0 :         if (unlikely(rxq->flags &
     646                 :            :                      (SFC_EF100_RXQ_NOT_RUNNING | SFC_EF100_RXQ_EXCEPTION)))
     647                 :          0 :                 goto done;
     648                 :            : 
     649   [ #  #  #  # ]:          0 :         while (rx_pkts != rx_pkts_end && sfc_ef100_rx_get_event(rxq, &rx_ev)) {
     650                 :          0 :                 rxq->ready_pkts =
     651                 :          0 :                         EFX_QWORD_FIELD(rx_ev, ESF_GZ_EV_RXPKTS_NUM_PKT);
     652                 :          0 :                 rx_pkts = sfc_ef100_rx_process_ready_pkts(rxq, rx_pkts,
     653                 :            :                                                           rx_pkts_end);
     654                 :            :         }
     655                 :            : 
     656                 :            :         /* It is not a problem if we refill in the case of exception */
     657                 :          0 :         sfc_ef100_rx_qrefill(rxq);
     658                 :            : 
     659         [ #  # ]:          0 :         if ((rxq->flags & SFC_EF100_RXQ_FLAG_INTR_EN) &&
     660         [ #  # ]:          0 :             rxq->evq_read_ptr_primed != rxq->evq_read_ptr)
     661                 :            :                 sfc_ef100_rx_qprime(rxq);
     662                 :            : 
     663                 :          0 : done:
     664                 :          0 :         return nb_pkts - (rx_pkts_end - rx_pkts);
     665                 :            : }
     666                 :            : 
     667                 :            : static const uint32_t *
     668                 :          0 : sfc_ef100_supported_ptypes_get(__rte_unused uint32_t tunnel_encaps,
     669                 :            :                                size_t *no_of_elements)
     670                 :            : {
     671                 :            :         static const uint32_t ef100_native_ptypes[] = {
     672                 :            :                 RTE_PTYPE_L2_ETHER,
     673                 :            :                 RTE_PTYPE_L2_ETHER_VLAN,
     674                 :            :                 RTE_PTYPE_L2_ETHER_QINQ,
     675                 :            :                 RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
     676                 :            :                 RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
     677                 :            :                 RTE_PTYPE_L4_TCP,
     678                 :            :                 RTE_PTYPE_L4_UDP,
     679                 :            :                 RTE_PTYPE_L4_FRAG,
     680                 :            :                 RTE_PTYPE_TUNNEL_VXLAN,
     681                 :            :                 RTE_PTYPE_TUNNEL_NVGRE,
     682                 :            :                 RTE_PTYPE_TUNNEL_GENEVE,
     683                 :            :                 RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN,
     684                 :            :                 RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN,
     685                 :            :                 RTE_PTYPE_INNER_L4_TCP,
     686                 :            :                 RTE_PTYPE_INNER_L4_UDP,
     687                 :            :                 RTE_PTYPE_INNER_L4_FRAG,
     688                 :            :         };
     689                 :            : 
     690                 :          0 :         *no_of_elements = RTE_DIM(ef100_native_ptypes);
     691                 :          0 :         return ef100_native_ptypes;
     692                 :            : }
     693                 :            : 
     694                 :            : static sfc_dp_rx_qdesc_npending_t sfc_ef100_rx_qdesc_npending;
     695                 :            : static unsigned int
     696                 :          0 : sfc_ef100_rx_qdesc_npending(__rte_unused struct sfc_dp_rxq *dp_rxq)
     697                 :            : {
     698                 :          0 :         return 0;
     699                 :            : }
     700                 :            : 
     701                 :            : static sfc_dp_rx_qdesc_status_t sfc_ef100_rx_qdesc_status;
     702                 :            : static int
     703                 :          0 : sfc_ef100_rx_qdesc_status(__rte_unused struct sfc_dp_rxq *dp_rxq,
     704                 :            :                           __rte_unused uint16_t offset)
     705                 :            : {
     706                 :          0 :         return -ENOTSUP;
     707                 :            : }
     708                 :            : 
     709                 :            : 
     710                 :            : static sfc_dp_rx_get_dev_info_t sfc_ef100_rx_get_dev_info;
     711                 :            : static void
     712                 :          0 : sfc_ef100_rx_get_dev_info(struct rte_eth_dev_info *dev_info)
     713                 :            : {
     714                 :            :         /*
     715                 :            :          * Number of descriptors just defines maximum number of pushed
     716                 :            :          * descriptors (fill level).
     717                 :            :          */
     718                 :          0 :         dev_info->rx_desc_lim.nb_min = SFC_RX_REFILL_BULK;
     719                 :          0 :         dev_info->rx_desc_lim.nb_align = SFC_RX_REFILL_BULK;
     720                 :          0 : }
     721                 :            : 
     722                 :            : 
     723                 :            : static sfc_dp_rx_qsize_up_rings_t sfc_ef100_rx_qsize_up_rings;
     724                 :            : static int
     725                 :          0 : sfc_ef100_rx_qsize_up_rings(uint16_t nb_rx_desc,
     726                 :            :                            struct sfc_dp_rx_hw_limits *limits,
     727                 :            :                            __rte_unused struct rte_mempool *mb_pool,
     728                 :            :                            unsigned int *rxq_entries,
     729                 :            :                            unsigned int *evq_entries,
     730                 :            :                            unsigned int *rxq_max_fill_level)
     731                 :            : {
     732                 :            :         /*
     733                 :            :          * rte_ethdev API guarantees that the number meets min, max and
     734                 :            :          * alignment requirements.
     735                 :            :          */
     736         [ #  # ]:          0 :         if (nb_rx_desc <= limits->rxq_min_entries)
     737                 :          0 :                 *rxq_entries = limits->rxq_min_entries;
     738                 :            :         else
     739                 :          0 :                 *rxq_entries = rte_align32pow2(nb_rx_desc);
     740                 :            : 
     741                 :          0 :         *evq_entries = *rxq_entries;
     742                 :            : 
     743                 :          0 :         *rxq_max_fill_level = RTE_MIN(nb_rx_desc,
     744                 :            :                                       SFC_EF100_RXQ_LIMIT(*evq_entries));
     745                 :          0 :         return 0;
     746                 :            : }
     747                 :            : 
     748                 :            : 
     749                 :            : static uint64_t
     750                 :          0 : sfc_ef100_mk_mbuf_rearm_data(uint16_t port_id, uint16_t prefix_size)
     751                 :            : {
     752                 :            :         struct rte_mbuf m;
     753                 :            : 
     754                 :            :         memset(&m, 0, sizeof(m));
     755                 :            : 
     756                 :            :         rte_mbuf_refcnt_set(&m, 1);
     757                 :          0 :         m.data_off = RTE_PKTMBUF_HEADROOM + prefix_size;
     758                 :          0 :         m.nb_segs = 1;
     759                 :          0 :         m.port = port_id;
     760                 :            : 
     761                 :            :         /* rearm_data covers structure members filled in above */
     762                 :          0 :         rte_compiler_barrier();
     763                 :            :         RTE_BUILD_BUG_ON(sizeof(m.rearm_data[0]) != sizeof(uint64_t));
     764                 :          0 :         return m.rearm_data[0];
     765                 :            : }
     766                 :            : 
     767                 :            : static sfc_dp_rx_qcreate_t sfc_ef100_rx_qcreate;
     768                 :            : static int
     769                 :          0 : sfc_ef100_rx_qcreate(uint16_t port_id, uint16_t queue_id,
     770                 :            :                     const struct rte_pci_addr *pci_addr, int socket_id,
     771                 :            :                     const struct sfc_dp_rx_qcreate_info *info,
     772                 :            :                     struct sfc_dp_rxq **dp_rxqp)
     773                 :            : {
     774                 :            :         struct sfc_ef100_rxq *rxq;
     775                 :            :         int rc;
     776                 :            : 
     777                 :            :         rc = EINVAL;
     778         [ #  # ]:          0 :         if (info->rxq_entries != info->evq_entries)
     779                 :          0 :                 goto fail_rxq_args;
     780                 :            : 
     781                 :            :         rc = ENOMEM;
     782                 :          0 :         rxq = rte_zmalloc_socket("sfc-ef100-rxq", sizeof(*rxq),
     783                 :            :                                  RTE_CACHE_LINE_SIZE, socket_id);
     784         [ #  # ]:          0 :         if (rxq == NULL)
     785                 :          0 :                 goto fail_rxq_alloc;
     786                 :            : 
     787                 :          0 :         sfc_dp_queue_init(&rxq->dp.dpq, port_id, queue_id, pci_addr);
     788                 :            : 
     789                 :            :         rc = ENOMEM;
     790                 :          0 :         rxq->sw_ring = rte_calloc_socket("sfc-ef100-rxq-sw_ring",
     791                 :          0 :                                          info->rxq_entries,
     792                 :            :                                          sizeof(*rxq->sw_ring),
     793                 :            :                                          RTE_CACHE_LINE_SIZE, socket_id);
     794         [ #  # ]:          0 :         if (rxq->sw_ring == NULL)
     795                 :          0 :                 goto fail_desc_alloc;
     796                 :            : 
     797                 :          0 :         rxq->flags |= SFC_EF100_RXQ_NOT_RUNNING;
     798                 :          0 :         rxq->ptr_mask = info->rxq_entries - 1;
     799         [ #  # ]:          0 :         rxq->evq_phase_bit_shift = rte_bsf32(info->evq_entries);
     800                 :          0 :         rxq->evq_hw_ring = info->evq_hw_ring;
     801                 :          0 :         rxq->max_fill_level = info->max_fill_level;
     802                 :          0 :         rxq->refill_threshold = info->refill_threshold;
     803                 :          0 :         rxq->prefix_size = info->prefix_size;
     804                 :            : 
     805                 :            :         SFC_ASSERT(info->user_mark_mask != 0);
     806                 :          0 :         rxq->user_mark_mask = info->user_mark_mask;
     807                 :            : 
     808                 :          0 :         rxq->buf_size = info->buf_size;
     809                 :          0 :         rxq->refill_mb_pool = info->refill_mb_pool;
     810                 :          0 :         rxq->rxq_hw_ring = info->rxq_hw_ring;
     811                 :          0 :         rxq->doorbell = (volatile uint8_t *)info->mem_bar +
     812                 :          0 :                         ER_GZ_RX_RING_DOORBELL_OFST +
     813                 :          0 :                         (info->hw_index << info->vi_window_shift);
     814                 :            : 
     815                 :          0 :         rxq->evq_hw_index = info->evq_hw_index;
     816                 :          0 :         rxq->evq_prime = (volatile uint8_t *)info->mem_bar +
     817                 :          0 :                          info->fcw_offset +
     818                 :            :                          ER_GZ_EVQ_INT_PRIME_OFST;
     819                 :            : 
     820                 :          0 :         rxq->nic_dma_info = info->nic_dma_info;
     821         [ #  # ]:          0 :         if (rxq->nic_dma_info->nb_regions > 0)
     822                 :          0 :                 rxq->flags |= SFC_EF100_RXQ_NIC_DMA_MAP;
     823                 :            : 
     824         [ #  # ]:          0 :         if (info->flags & SFC_RXQ_FLAG_INGRESS_MPORT)
     825                 :          0 :                 rxq->flags |= SFC_EF100_RXQ_INGRESS_MPORT;
     826                 :            : 
     827         [ #  # ]:          0 :         if (info->flags & SFC_RXQ_FLAG_VLAN_STRIPPED_TCI)
     828                 :          0 :                 rxq->flags |= SFC_EF100_RXQ_VLAN_STRIPPED_TCI;
     829                 :            : 
     830                 :            :         sfc_ef100_rx_debug(rxq, "RxQ doorbell is %p", rxq->doorbell);
     831                 :            : 
     832                 :          0 :         *dp_rxqp = &rxq->dp;
     833                 :          0 :         return 0;
     834                 :            : 
     835                 :            : fail_desc_alloc:
     836                 :          0 :         rte_free(rxq);
     837                 :            : 
     838                 :            : fail_rxq_alloc:
     839                 :            : fail_rxq_args:
     840                 :            :         return rc;
     841                 :            : }
     842                 :            : 
     843                 :            : static sfc_dp_rx_qdestroy_t sfc_ef100_rx_qdestroy;
     844                 :            : static void
     845                 :          0 : sfc_ef100_rx_qdestroy(struct sfc_dp_rxq *dp_rxq)
     846                 :            : {
     847                 :            :         struct sfc_ef100_rxq *rxq = sfc_ef100_rxq_by_dp_rxq(dp_rxq);
     848                 :            : 
     849                 :          0 :         rte_free(rxq->sw_ring);
     850                 :          0 :         rte_free(rxq);
     851                 :          0 : }
     852                 :            : 
     853                 :            : static sfc_dp_rx_qstart_t sfc_ef100_rx_qstart;
     854                 :            : static int
     855                 :          0 : sfc_ef100_rx_qstart(struct sfc_dp_rxq *dp_rxq, unsigned int evq_read_ptr,
     856                 :            :                     const efx_rx_prefix_layout_t *pinfo)
     857                 :            : {
     858                 :            :         struct sfc_ef100_rxq *rxq = sfc_ef100_rxq_by_dp_rxq(dp_rxq);
     859                 :            :         uint32_t unsup_rx_prefix_fields;
     860                 :            : 
     861                 :            :         SFC_ASSERT(rxq->completed == 0);
     862                 :            :         SFC_ASSERT(rxq->added == 0);
     863                 :            : 
     864                 :            :         /* Prefix must fit into reserved Rx buffer space */
     865         [ #  # ]:          0 :         if (pinfo->erpl_length > rxq->prefix_size)
     866                 :            :                 return ENOTSUP;
     867                 :            : 
     868                 :            :         unsup_rx_prefix_fields =
     869                 :          0 :                 efx_rx_prefix_layout_check(pinfo, &sfc_ef100_rx_prefix_layout);
     870                 :            : 
     871                 :            :         /* LENGTH and CLASS fields must always be present */
     872         [ #  # ]:          0 :         if ((unsup_rx_prefix_fields &
     873                 :            :              ((1U << EFX_RX_PREFIX_FIELD_LENGTH) |
     874                 :            :               (1U << EFX_RX_PREFIX_FIELD_CLASS))) != 0)
     875                 :            :                 return ENOTSUP;
     876                 :            : 
     877         [ #  # ]:          0 :         if ((unsup_rx_prefix_fields &
     878                 :            :              ((1U << EFX_RX_PREFIX_FIELD_RSS_HASH_VALID) |
     879                 :            :               (1U << EFX_RX_PREFIX_FIELD_RSS_HASH))) == 0)
     880                 :          0 :                 rxq->flags |= SFC_EF100_RXQ_RSS_HASH;
     881                 :            :         else
     882                 :          0 :                 rxq->flags &= ~SFC_EF100_RXQ_RSS_HASH;
     883                 :            : 
     884         [ #  # ]:          0 :         if ((unsup_rx_prefix_fields &
     885                 :            :              (1U << EFX_RX_PREFIX_FIELD_USER_FLAG)) == 0)
     886                 :          0 :                 rxq->flags |= SFC_EF100_RXQ_USER_FLAG;
     887                 :            :         else
     888                 :          0 :                 rxq->flags &= ~SFC_EF100_RXQ_USER_FLAG;
     889                 :            : 
     890         [ #  # ]:          0 :         if ((unsup_rx_prefix_fields &
     891                 :            :              (1U << EFX_RX_PREFIX_FIELD_USER_MARK)) == 0)
     892                 :          0 :                 rxq->flags |= SFC_EF100_RXQ_USER_MARK;
     893                 :            :         else
     894                 :          0 :                 rxq->flags &= ~SFC_EF100_RXQ_USER_MARK;
     895                 :            : 
     896                 :            : 
     897                 :            :         /*
     898                 :            :          * At the moment, this feature is used only
     899                 :            :          * by the representor proxy Rx queue and is
     900                 :            :          * essential for representor support, so if
     901                 :            :          * it has been requested but is unsupported,
     902                 :            :          * point this inconsistency out to the user.
     903                 :            :          */
     904         [ #  # ]:          0 :         if ((unsup_rx_prefix_fields &
     905                 :          0 :              (1U << EFX_RX_PREFIX_FIELD_INGRESS_MPORT)) &&
     906         [ #  # ]:          0 :             (rxq->flags & SFC_EF100_RXQ_INGRESS_MPORT))
     907                 :            :                 return ENOTSUP;
     908                 :            : 
     909                 :          0 :         rxq->prefix_size = pinfo->erpl_length;
     910                 :          0 :         rxq->rearm_data = sfc_ef100_mk_mbuf_rearm_data(rxq->dp.dpq.port_id,
     911                 :            :                                                        rxq->prefix_size);
     912                 :            : 
     913                 :          0 :         sfc_ef100_rx_qrefill(rxq);
     914                 :            : 
     915                 :          0 :         rxq->evq_read_ptr = evq_read_ptr;
     916                 :            : 
     917                 :          0 :         rxq->flags |= SFC_EF100_RXQ_STARTED;
     918                 :          0 :         rxq->flags &= ~(SFC_EF100_RXQ_NOT_RUNNING | SFC_EF100_RXQ_EXCEPTION);
     919                 :            : 
     920         [ #  # ]:          0 :         if (rxq->flags & SFC_EF100_RXQ_FLAG_INTR_EN)
     921                 :            :                 sfc_ef100_rx_qprime(rxq);
     922                 :            : 
     923                 :            :         return 0;
     924                 :            : }
     925                 :            : 
     926                 :            : static sfc_dp_rx_qstop_t sfc_ef100_rx_qstop;
     927                 :            : static void
     928                 :          0 : sfc_ef100_rx_qstop(struct sfc_dp_rxq *dp_rxq, unsigned int *evq_read_ptr)
     929                 :            : {
     930                 :            :         struct sfc_ef100_rxq *rxq = sfc_ef100_rxq_by_dp_rxq(dp_rxq);
     931                 :            : 
     932                 :          0 :         rxq->flags |= SFC_EF100_RXQ_NOT_RUNNING;
     933                 :            : 
     934                 :          0 :         *evq_read_ptr = rxq->evq_read_ptr;
     935                 :          0 : }
     936                 :            : 
     937                 :            : static sfc_dp_rx_qrx_ev_t sfc_ef100_rx_qrx_ev;
     938                 :            : static bool
     939                 :          0 : sfc_ef100_rx_qrx_ev(struct sfc_dp_rxq *dp_rxq, __rte_unused unsigned int id)
     940                 :            : {
     941                 :            :         __rte_unused struct sfc_ef100_rxq *rxq = sfc_ef100_rxq_by_dp_rxq(dp_rxq);
     942                 :            : 
     943                 :            :         SFC_ASSERT(rxq->flags & SFC_EF100_RXQ_NOT_RUNNING);
     944                 :            : 
     945                 :            :         /*
     946                 :            :          * It is safe to ignore Rx event since we free all mbufs on
     947                 :            :          * queue purge anyway.
     948                 :            :          */
     949                 :            : 
     950                 :          0 :         return false;
     951                 :            : }
     952                 :            : 
     953                 :            : static sfc_dp_rx_qpurge_t sfc_ef100_rx_qpurge;
     954                 :            : static void
     955                 :          0 : sfc_ef100_rx_qpurge(struct sfc_dp_rxq *dp_rxq)
     956                 :            : {
     957                 :            :         struct sfc_ef100_rxq *rxq = sfc_ef100_rxq_by_dp_rxq(dp_rxq);
     958                 :            :         unsigned int i;
     959                 :            :         struct sfc_ef100_rx_sw_desc *rxd;
     960                 :            : 
     961         [ #  # ]:          0 :         for (i = rxq->completed; i != rxq->added; ++i) {
     962                 :          0 :                 rxd = &rxq->sw_ring[i & rxq->ptr_mask];
     963         [ #  # ]:          0 :                 rte_mbuf_raw_free(rxd->mbuf);
     964                 :          0 :                 rxd->mbuf = NULL;
     965                 :            :         }
     966                 :            : 
     967                 :          0 :         rxq->completed = rxq->added = 0;
     968                 :          0 :         rxq->ready_pkts = 0;
     969                 :            : 
     970                 :          0 :         rxq->flags &= ~SFC_EF100_RXQ_STARTED;
     971                 :          0 : }
     972                 :            : 
     973                 :            : static sfc_dp_rx_intr_enable_t sfc_ef100_rx_intr_enable;
     974                 :            : static int
     975                 :          0 : sfc_ef100_rx_intr_enable(struct sfc_dp_rxq *dp_rxq)
     976                 :            : {
     977                 :            :         struct sfc_ef100_rxq *rxq = sfc_ef100_rxq_by_dp_rxq(dp_rxq);
     978                 :            : 
     979                 :          0 :         rxq->flags |= SFC_EF100_RXQ_FLAG_INTR_EN;
     980         [ #  # ]:          0 :         if (rxq->flags & SFC_EF100_RXQ_STARTED)
     981                 :            :                 sfc_ef100_rx_qprime(rxq);
     982                 :          0 :         return 0;
     983                 :            : }
     984                 :            : 
     985                 :            : static sfc_dp_rx_intr_disable_t sfc_ef100_rx_intr_disable;
     986                 :            : static int
     987                 :          0 : sfc_ef100_rx_intr_disable(struct sfc_dp_rxq *dp_rxq)
     988                 :            : {
     989                 :            :         struct sfc_ef100_rxq *rxq = sfc_ef100_rxq_by_dp_rxq(dp_rxq);
     990                 :            : 
     991                 :            :         /* Cannot disarm, just disable rearm */
     992                 :          0 :         rxq->flags &= ~SFC_EF100_RXQ_FLAG_INTR_EN;
     993                 :          0 :         return 0;
     994                 :            : }
     995                 :            : 
     996                 :            : static sfc_dp_rx_get_pushed_t sfc_ef100_rx_get_pushed;
     997                 :            : static unsigned int
     998                 :          0 : sfc_ef100_rx_get_pushed(struct sfc_dp_rxq *dp_rxq)
     999                 :            : {
    1000                 :            :         struct sfc_ef100_rxq *rxq = sfc_ef100_rxq_by_dp_rxq(dp_rxq);
    1001                 :            : 
    1002                 :            :         /*
    1003                 :            :          * The datapath keeps track only of added descriptors, since
    1004                 :            :          * the number of pushed descriptors always equals the number
    1005                 :            :          * of added descriptors due to enforced alignment.
    1006                 :            :          */
    1007                 :          0 :         return rxq->added;
    1008                 :            : }
    1009                 :            : 
    1010                 :            : struct sfc_dp_rx sfc_ef100_rx = {
    1011                 :            :         .dp = {
    1012                 :            :                 .name           = SFC_KVARG_DATAPATH_EF100,
    1013                 :            :                 .type           = SFC_DP_RX,
    1014                 :            :                 .hw_fw_caps     = SFC_DP_HW_FW_CAP_EF100,
    1015                 :            :         },
    1016                 :            :         .features               = SFC_DP_RX_FEAT_MULTI_PROCESS |
    1017                 :            :                                   SFC_DP_RX_FEAT_FLOW_FLAG |
    1018                 :            :                                   SFC_DP_RX_FEAT_FLOW_MARK |
    1019                 :            :                                   SFC_DP_RX_FEAT_INTR |
    1020                 :            :                                   SFC_DP_RX_FEAT_STATS,
    1021                 :            :         .dev_offload_capa       = RTE_ETH_RX_OFFLOAD_KEEP_CRC |
    1022                 :            :                                   RTE_ETH_RX_OFFLOAD_VLAN_STRIP,
    1023                 :            :         .queue_offload_capa     = RTE_ETH_RX_OFFLOAD_CHECKSUM |
    1024                 :            :                                   RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM |
    1025                 :            :                                   RTE_ETH_RX_OFFLOAD_OUTER_UDP_CKSUM |
    1026                 :            :                                   RTE_ETH_RX_OFFLOAD_SCATTER |
    1027                 :            :                                   RTE_ETH_RX_OFFLOAD_RSS_HASH,
    1028                 :            :         .get_dev_info           = sfc_ef100_rx_get_dev_info,
    1029                 :            :         .qsize_up_rings         = sfc_ef100_rx_qsize_up_rings,
    1030                 :            :         .qcreate                = sfc_ef100_rx_qcreate,
    1031                 :            :         .qdestroy               = sfc_ef100_rx_qdestroy,
    1032                 :            :         .qstart                 = sfc_ef100_rx_qstart,
    1033                 :            :         .qstop                  = sfc_ef100_rx_qstop,
    1034                 :            :         .qrx_ev                 = sfc_ef100_rx_qrx_ev,
    1035                 :            :         .qpurge                 = sfc_ef100_rx_qpurge,
    1036                 :            :         .supported_ptypes_get   = sfc_ef100_supported_ptypes_get,
    1037                 :            :         .qdesc_npending         = sfc_ef100_rx_qdesc_npending,
    1038                 :            :         .qdesc_status           = sfc_ef100_rx_qdesc_status,
    1039                 :            :         .intr_enable            = sfc_ef100_rx_intr_enable,
    1040                 :            :         .intr_disable           = sfc_ef100_rx_intr_disable,
    1041                 :            :         .get_pushed             = sfc_ef100_rx_get_pushed,
    1042                 :            :         .pkt_burst              = sfc_ef100_recv_pkts,
    1043                 :            : };

Generated by: LCOV version 1.14