LCOV - code coverage report
Current view: top level - drivers/net/zxdh - zxdh_rxtx.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 366 0.0 %
Date: 2025-03-01 20:23:48 Functions: 0 13 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 212 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2024 ZTE Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <stdint.h>
       6                 :            : #include <stdalign.h>
       7                 :            : 
       8                 :            : #include <rte_net.h>
       9                 :            : 
      10                 :            : #include "zxdh_logs.h"
      11                 :            : #include "zxdh_pci.h"
      12                 :            : #include "zxdh_queue.h"
      13                 :            : 
      14                 :            : #define ZXDH_SVLAN_TPID                       0x88a8
      15                 :            : #define ZXDH_CVLAN_TPID                       0x8100
      16                 :            : 
      17                 :            : #define ZXDH_PKT_FORM_CPU                     0x20    /* 1-cpu 0-np */
      18                 :            : #define ZXDH_NO_IP_FRAGMENT                   0x2000  /* ip fragment flag */
      19                 :            : #define ZXDH_NO_IPID_UPDATE                   0x4000  /* ipid update flag */
      20                 :            : 
      21                 :            : #define ZXDH_PI_L3TYPE_IP                     0x00
      22                 :            : #define ZXDH_PI_L3TYPE_IPV6                   0x40
      23                 :            : #define ZXDH_PI_L3TYPE_NOIP                   0x80
      24                 :            : #define ZXDH_PI_L3TYPE_RSV                    0xC0
      25                 :            : #define ZXDH_PI_L3TYPE_MASK                   0xC0
      26                 :            : 
      27                 :            : #define  ZXDH_PD_OFFLOAD_SVLAN_INSERT         (1 << 14)
      28                 :            : #define  ZXDH_PD_OFFLOAD_CVLAN_INSERT         (1 << 13)
      29                 :            : 
      30                 :            : #define ZXDH_PCODE_MASK                       0x1F
      31                 :            : #define ZXDH_PCODE_IP_PKT_TYPE                0x01
      32                 :            : #define ZXDH_PCODE_TCP_PKT_TYPE               0x02
      33                 :            : #define ZXDH_PCODE_UDP_PKT_TYPE               0x03
      34                 :            : #define ZXDH_PCODE_NO_IP_PKT_TYPE             0x09
      35                 :            : #define ZXDH_PCODE_NO_REASSMBLE_TCP_PKT_TYPE  0x0C
      36                 :            : 
      37                 :            : #define ZXDH_TX_MAX_SEGS                      31
      38                 :            : #define ZXDH_RX_MAX_SEGS                      31
      39                 :            : 
      40                 :            : uint32_t zxdh_outer_l2_type[16] = {
      41                 :            :         0,
      42                 :            :         RTE_PTYPE_L2_ETHER,
      43                 :            :         RTE_PTYPE_L2_ETHER_TIMESYNC,
      44                 :            :         RTE_PTYPE_L2_ETHER_ARP,
      45                 :            :         RTE_PTYPE_L2_ETHER_LLDP,
      46                 :            :         RTE_PTYPE_L2_ETHER_NSH,
      47                 :            :         RTE_PTYPE_L2_ETHER_VLAN,
      48                 :            :         RTE_PTYPE_L2_ETHER_QINQ,
      49                 :            :         RTE_PTYPE_L2_ETHER_PPPOE,
      50                 :            :         RTE_PTYPE_L2_ETHER_FCOE,
      51                 :            :         RTE_PTYPE_L2_ETHER_MPLS,
      52                 :            : };
      53                 :            : 
      54                 :            : uint32_t zxdh_outer_l3_type[16] = {
      55                 :            :         0,
      56                 :            :         RTE_PTYPE_L3_IPV4,
      57                 :            :         RTE_PTYPE_L3_IPV4_EXT,
      58                 :            :         RTE_PTYPE_L3_IPV6,
      59                 :            :         RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
      60                 :            :         RTE_PTYPE_L3_IPV6_EXT,
      61                 :            :         RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
      62                 :            : };
      63                 :            : 
      64                 :            : uint32_t zxdh_outer_l4_type[16] = {
      65                 :            :         0,
      66                 :            :         RTE_PTYPE_L4_TCP,
      67                 :            :         RTE_PTYPE_L4_UDP,
      68                 :            :         RTE_PTYPE_L4_FRAG,
      69                 :            :         RTE_PTYPE_L4_SCTP,
      70                 :            :         RTE_PTYPE_L4_ICMP,
      71                 :            :         RTE_PTYPE_L4_NONFRAG,
      72                 :            :         RTE_PTYPE_L4_IGMP,
      73                 :            : };
      74                 :            : 
      75                 :            : uint32_t zxdh_tunnel_type[16] = {
      76                 :            :         0,
      77                 :            :         RTE_PTYPE_TUNNEL_IP,
      78                 :            :         RTE_PTYPE_TUNNEL_GRE,
      79                 :            :         RTE_PTYPE_TUNNEL_VXLAN,
      80                 :            :         RTE_PTYPE_TUNNEL_NVGRE,
      81                 :            :         RTE_PTYPE_TUNNEL_GENEVE,
      82                 :            :         RTE_PTYPE_TUNNEL_GRENAT,
      83                 :            :         RTE_PTYPE_TUNNEL_GTPC,
      84                 :            :         RTE_PTYPE_TUNNEL_GTPU,
      85                 :            :         RTE_PTYPE_TUNNEL_ESP,
      86                 :            :         RTE_PTYPE_TUNNEL_L2TP,
      87                 :            :         RTE_PTYPE_TUNNEL_VXLAN_GPE,
      88                 :            :         RTE_PTYPE_TUNNEL_MPLS_IN_GRE,
      89                 :            :         RTE_PTYPE_TUNNEL_MPLS_IN_UDP,
      90                 :            : };
      91                 :            : 
      92                 :            : uint32_t zxdh_inner_l2_type[16] = {
      93                 :            :         0,
      94                 :            :         RTE_PTYPE_INNER_L2_ETHER,
      95                 :            :         0,
      96                 :            :         0,
      97                 :            :         0,
      98                 :            :         0,
      99                 :            :         RTE_PTYPE_INNER_L2_ETHER_VLAN,
     100                 :            :         RTE_PTYPE_INNER_L2_ETHER_QINQ,
     101                 :            :         0,
     102                 :            :         0,
     103                 :            :         0,
     104                 :            : };
     105                 :            : 
     106                 :            : uint32_t zxdh_inner_l3_type[16] = {
     107                 :            :         0,
     108                 :            :         RTE_PTYPE_INNER_L3_IPV4,
     109                 :            :         RTE_PTYPE_INNER_L3_IPV4_EXT,
     110                 :            :         RTE_PTYPE_INNER_L3_IPV6,
     111                 :            :         RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN,
     112                 :            :         RTE_PTYPE_INNER_L3_IPV6_EXT,
     113                 :            :         RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN,
     114                 :            : };
     115                 :            : 
     116                 :            : uint32_t zxdh_inner_l4_type[16] = {
     117                 :            :         0,
     118                 :            :         RTE_PTYPE_INNER_L4_TCP,
     119                 :            :         RTE_PTYPE_INNER_L4_UDP,
     120                 :            :         RTE_PTYPE_INNER_L4_FRAG,
     121                 :            :         RTE_PTYPE_INNER_L4_SCTP,
     122                 :            :         RTE_PTYPE_INNER_L4_ICMP,
     123                 :            :         0,
     124                 :            :         0,
     125                 :            : };
     126                 :            : 
     127                 :            : static void
     128                 :          0 : zxdh_xmit_cleanup_inorder_packed(struct zxdh_virtqueue *vq, int32_t num)
     129                 :            : {
     130                 :            :         uint16_t used_idx = 0;
     131                 :            :         uint16_t id       = 0;
     132                 :            :         uint16_t curr_id  = 0;
     133                 :            :         uint16_t free_cnt = 0;
     134                 :          0 :         uint16_t size     = vq->vq_nentries;
     135                 :          0 :         struct zxdh_vring_packed_desc *desc = vq->vq_packed.ring.desc;
     136                 :            :         struct zxdh_vq_desc_extra     *dxp  = NULL;
     137                 :            : 
     138                 :          0 :         used_idx = vq->vq_used_cons_idx;
     139                 :            :         /* desc_is_used has a load-acquire or rte_io_rmb inside
     140                 :            :          * and wait for used desc in virtqueue.
     141                 :            :          */
     142   [ #  #  #  # ]:          0 :         while (num > 0 && zxdh_desc_used(&desc[used_idx], vq)) {
     143                 :          0 :                 id = desc[used_idx].id;
     144                 :            :                 do {
     145                 :            :                         curr_id = used_idx;
     146                 :          0 :                         dxp = &vq->vq_descx[used_idx];
     147                 :          0 :                         used_idx += dxp->ndescs;
     148                 :          0 :                         free_cnt += dxp->ndescs;
     149                 :          0 :                         num -= dxp->ndescs;
     150         [ #  # ]:          0 :                         if (used_idx >= size) {
     151                 :          0 :                                 used_idx -= size;
     152                 :          0 :                                 vq->vq_packed.used_wrap_counter ^= 1;
     153                 :            :                         }
     154         [ #  # ]:          0 :                         if (dxp->cookie != NULL) {
     155                 :          0 :                                 rte_pktmbuf_free(dxp->cookie);
     156                 :          0 :                                 dxp->cookie = NULL;
     157                 :            :                         }
     158         [ #  # ]:          0 :                 } while (curr_id != id);
     159                 :            :         }
     160                 :          0 :         vq->vq_used_cons_idx = used_idx;
     161                 :          0 :         vq->vq_free_cnt += free_cnt;
     162                 :          0 : }
     163                 :            : 
     164                 :            : static void
     165                 :            : zxdh_ring_free_id_packed(struct zxdh_virtqueue *vq, uint16_t id)
     166                 :            : {
     167                 :            :         struct zxdh_vq_desc_extra *dxp = NULL;
     168                 :            : 
     169                 :            :         dxp = &vq->vq_descx[id];
     170                 :          0 :         vq->vq_free_cnt += dxp->ndescs;
     171                 :            : 
     172         [ #  # ]:          0 :         if (vq->vq_desc_tail_idx == ZXDH_VQ_RING_DESC_CHAIN_END)
     173                 :          0 :                 vq->vq_desc_head_idx = id;
     174                 :            :         else
     175                 :          0 :                 vq->vq_descx[vq->vq_desc_tail_idx].next = id;
     176                 :            : 
     177                 :          0 :         vq->vq_desc_tail_idx = id;
     178                 :          0 :         dxp->next = ZXDH_VQ_RING_DESC_CHAIN_END;
     179                 :            : }
     180                 :            : 
     181                 :            : static void
     182                 :          0 : zxdh_xmit_cleanup_normal_packed(struct zxdh_virtqueue *vq, int32_t num)
     183                 :            : {
     184                 :            :         uint16_t used_idx = 0;
     185                 :            :         uint16_t id = 0;
     186                 :          0 :         uint16_t size = vq->vq_nentries;
     187                 :          0 :         struct zxdh_vring_packed_desc *desc = vq->vq_packed.ring.desc;
     188                 :            :         struct zxdh_vq_desc_extra *dxp = NULL;
     189                 :            : 
     190                 :          0 :         used_idx = vq->vq_used_cons_idx;
     191                 :            :         /* desc_is_used has a load-acquire or rte_io_rmb inside
     192                 :            :          * and wait for used desc in virtqueue.
     193                 :            :          */
     194   [ #  #  #  # ]:          0 :         while (num-- && zxdh_desc_used(&desc[used_idx], vq)) {
     195                 :          0 :                 id = desc[used_idx].id;
     196                 :          0 :                 dxp = &vq->vq_descx[id];
     197                 :          0 :                 vq->vq_used_cons_idx += dxp->ndescs;
     198         [ #  # ]:          0 :                 if (vq->vq_used_cons_idx >= size) {
     199                 :          0 :                         vq->vq_used_cons_idx -= size;
     200                 :          0 :                         vq->vq_packed.used_wrap_counter ^= 1;
     201                 :            :                 }
     202                 :            :                 zxdh_ring_free_id_packed(vq, id);
     203         [ #  # ]:          0 :                 if (dxp->cookie != NULL) {
     204                 :          0 :                         rte_pktmbuf_free(dxp->cookie);
     205                 :          0 :                         dxp->cookie = NULL;
     206                 :            :                 }
     207                 :          0 :                 used_idx = vq->vq_used_cons_idx;
     208                 :            :         }
     209                 :          0 : }
     210                 :            : 
     211                 :            : static void
     212                 :            : zxdh_xmit_cleanup_packed(struct zxdh_virtqueue *vq, int32_t num, int32_t in_order)
     213                 :            : {
     214         [ #  # ]:          0 :         if (in_order)
     215                 :          0 :                 zxdh_xmit_cleanup_inorder_packed(vq, num);
     216                 :            :         else
     217                 :          0 :                 zxdh_xmit_cleanup_normal_packed(vq, num);
     218                 :            : }
     219                 :            : 
     220                 :            : static uint8_t
     221                 :          0 : zxdh_xmit_get_ptype(struct rte_mbuf *m)
     222                 :            : {
     223                 :            :         uint8_t pcode = ZXDH_PCODE_NO_IP_PKT_TYPE;
     224                 :            :         uint8_t l3_ptype = ZXDH_PI_L3TYPE_NOIP;
     225                 :            : 
     226         [ #  # ]:          0 :         if ((m->packet_type & RTE_PTYPE_INNER_L3_MASK) == RTE_PTYPE_INNER_L3_IPV4 ||
     227         [ #  # ]:          0 :                         ((!(m->packet_type & RTE_PTYPE_TUNNEL_MASK)) &&
     228                 :            :                         (m->packet_type & RTE_PTYPE_L3_MASK) == RTE_PTYPE_L3_IPV4)) {
     229                 :            :                 l3_ptype = ZXDH_PI_L3TYPE_IP;
     230                 :            :                 pcode = ZXDH_PCODE_IP_PKT_TYPE;
     231   [ #  #  #  # ]:          0 :         } else if ((m->packet_type & RTE_PTYPE_INNER_L3_MASK) == RTE_PTYPE_INNER_L3_IPV6 ||
     232                 :            :                         ((!(m->packet_type & RTE_PTYPE_TUNNEL_MASK)) &&
     233                 :            :                         (m->packet_type & RTE_PTYPE_L3_MASK) == RTE_PTYPE_L3_IPV6)) {
     234                 :            :                 l3_ptype = ZXDH_PI_L3TYPE_IPV6;
     235                 :            :                 pcode = ZXDH_PCODE_IP_PKT_TYPE;
     236                 :            :         } else {
     237                 :          0 :                 goto end;
     238                 :            :         }
     239                 :            : 
     240         [ #  # ]:          0 :         if ((m->packet_type & RTE_PTYPE_INNER_L4_MASK) == RTE_PTYPE_INNER_L4_TCP ||
     241         [ #  # ]:          0 :                         ((!(m->packet_type & RTE_PTYPE_TUNNEL_MASK)) &&
     242                 :            :                         (m->packet_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_TCP))
     243                 :            :                 pcode = ZXDH_PCODE_TCP_PKT_TYPE;
     244   [ #  #  #  # ]:          0 :         else if ((m->packet_type & RTE_PTYPE_INNER_L4_MASK) == RTE_PTYPE_INNER_L4_UDP ||
     245                 :            :                                 ((!(m->packet_type & RTE_PTYPE_TUNNEL_MASK)) &&
     246                 :            :                                 (m->packet_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_UDP))
     247                 :            :                 pcode = ZXDH_PCODE_UDP_PKT_TYPE;
     248                 :            : 
     249                 :          0 : end:
     250                 :          0 :         return  l3_ptype | ZXDH_PKT_FORM_CPU | pcode;
     251                 :            : }
     252                 :            : 
     253                 :          0 : static void zxdh_xmit_fill_net_hdr(struct rte_mbuf *cookie,
     254                 :            :                                 struct zxdh_net_hdr_dl *hdr)
     255                 :            : {
     256                 :            :         uint16_t pkt_flag_lw16 = ZXDH_NO_IPID_UPDATE;
     257                 :            :         uint16_t l3_offset;
     258                 :            :         uint32_t ol_flag = 0;
     259                 :            : 
     260                 :          0 :         hdr->pi_hdr.pkt_flag_lw16 = rte_be_to_cpu_16(pkt_flag_lw16);
     261                 :            : 
     262                 :          0 :         hdr->pi_hdr.pkt_type = zxdh_xmit_get_ptype(cookie);
     263                 :          0 :         l3_offset = ZXDH_DL_NET_HDR_SIZE + cookie->outer_l2_len +
     264                 :          0 :                                 cookie->outer_l3_len + cookie->l2_len;
     265         [ #  # ]:          0 :         hdr->pi_hdr.l3_offset = rte_be_to_cpu_16(l3_offset);
     266         [ #  # ]:          0 :         hdr->pi_hdr.l4_offset = rte_be_to_cpu_16(l3_offset + cookie->l3_len);
     267                 :            : 
     268         [ #  # ]:          0 :         if (cookie->ol_flags & RTE_MBUF_F_TX_VLAN) {
     269                 :            :                 ol_flag |= ZXDH_PD_OFFLOAD_CVLAN_INSERT;
     270         [ #  # ]:          0 :                 hdr->pi_hdr.vlan_id = rte_be_to_cpu_16(cookie->vlan_tci);
     271                 :          0 :                 hdr->pd_hdr.cvlan_insert =
     272         [ #  # ]:          0 :                         rte_be_to_cpu_32((ZXDH_CVLAN_TPID << 16) | cookie->vlan_tci);
     273                 :            :         }
     274         [ #  # ]:          0 :         if (cookie->ol_flags & RTE_MBUF_F_TX_QINQ) {
     275                 :          0 :                 ol_flag |= ZXDH_PD_OFFLOAD_SVLAN_INSERT;
     276                 :          0 :                 hdr->pd_hdr.svlan_insert =
     277         [ #  # ]:          0 :                         rte_be_to_cpu_32((ZXDH_SVLAN_TPID << 16) | cookie->vlan_tci_outer);
     278                 :            :         }
     279                 :            : 
     280         [ #  # ]:          0 :         hdr->pd_hdr.ol_flag = rte_be_to_cpu_32(ol_flag);
     281                 :          0 : }
     282                 :            : 
     283                 :          0 : static inline void zxdh_enqueue_xmit_packed_fast(struct zxdh_virtnet_tx *txvq,
     284                 :            :                                                 struct rte_mbuf *cookie, int32_t in_order)
     285                 :            : {
     286                 :          0 :         struct zxdh_virtqueue *vq = txvq->vq;
     287         [ #  # ]:          0 :         uint16_t id = in_order ? vq->vq_avail_idx : vq->vq_desc_head_idx;
     288                 :          0 :         struct zxdh_vq_desc_extra *dxp = &vq->vq_descx[id];
     289                 :          0 :         uint16_t flags = vq->vq_packed.cached_flags;
     290                 :            :         struct zxdh_net_hdr_dl *hdr = NULL;
     291                 :            : 
     292                 :          0 :         dxp->ndescs = 1;
     293                 :          0 :         dxp->cookie = cookie;
     294                 :          0 :         hdr = rte_pktmbuf_mtod_offset(cookie, struct zxdh_net_hdr_dl *, -ZXDH_DL_NET_HDR_SIZE);
     295                 :          0 :         zxdh_xmit_fill_net_hdr(cookie, hdr);
     296                 :            : 
     297                 :          0 :         uint16_t idx = vq->vq_avail_idx;
     298         [ #  # ]:          0 :         struct zxdh_vring_packed_desc *dp = &vq->vq_packed.ring.desc[idx];
     299                 :            : 
     300                 :          0 :         dp->addr = rte_pktmbuf_iova(cookie) - ZXDH_DL_NET_HDR_SIZE;
     301                 :          0 :         dp->len  = cookie->data_len + ZXDH_DL_NET_HDR_SIZE;
     302                 :          0 :         dp->id   = id;
     303         [ #  # ]:          0 :         if (++vq->vq_avail_idx >= vq->vq_nentries) {
     304                 :          0 :                 vq->vq_avail_idx -= vq->vq_nentries;
     305                 :          0 :                 vq->vq_packed.cached_flags ^= ZXDH_VRING_PACKED_DESC_F_AVAIL_USED;
     306                 :            :         }
     307                 :          0 :         vq->vq_free_cnt--;
     308         [ #  # ]:          0 :         if (!in_order) {
     309                 :          0 :                 vq->vq_desc_head_idx = dxp->next;
     310         [ #  # ]:          0 :                 if (vq->vq_desc_head_idx == ZXDH_VQ_RING_DESC_CHAIN_END)
     311                 :          0 :                         vq->vq_desc_tail_idx = ZXDH_VQ_RING_DESC_CHAIN_END;
     312                 :            :                 }
     313         [ #  # ]:          0 :                 zxdh_queue_store_flags_packed(dp, flags, vq->hw->weak_barriers);
     314                 :          0 : }
     315                 :            : 
     316                 :          0 : static inline void zxdh_enqueue_xmit_packed(struct zxdh_virtnet_tx *txvq,
     317                 :            :                                                 struct rte_mbuf *cookie,
     318                 :            :                                                 uint16_t needed,
     319                 :            :                                                 int32_t use_indirect,
     320                 :            :                                                 int32_t in_order)
     321                 :            : {
     322                 :          0 :         struct zxdh_tx_region *txr = txvq->zxdh_net_hdr_mz->addr;
     323                 :          0 :         struct zxdh_virtqueue *vq = txvq->vq;
     324                 :          0 :         struct zxdh_vring_packed_desc *start_dp = vq->vq_packed.ring.desc;
     325                 :            :         void *hdr = NULL;
     326                 :          0 :         uint16_t head_idx = vq->vq_avail_idx;
     327                 :            :         uint16_t idx = head_idx;
     328                 :            :         uint16_t prev = head_idx;
     329                 :          0 :         uint16_t head_flags = cookie->next ? ZXDH_VRING_DESC_F_NEXT : 0;
     330                 :          0 :         uint16_t seg_num = cookie->nb_segs;
     331         [ #  # ]:          0 :         uint16_t id = in_order ? vq->vq_avail_idx : vq->vq_desc_head_idx;
     332                 :          0 :         struct zxdh_vring_packed_desc *head_dp = &vq->vq_packed.ring.desc[idx];
     333                 :          0 :         struct zxdh_vq_desc_extra *dxp = &vq->vq_descx[id];
     334                 :            : 
     335                 :          0 :         dxp->ndescs = needed;
     336                 :          0 :         dxp->cookie = cookie;
     337                 :          0 :         head_flags |= vq->vq_packed.cached_flags;
     338                 :            :         /* if offload disabled, it is not zeroed below, do it now */
     339                 :            : 
     340         [ #  # ]:          0 :         if (use_indirect) {
     341                 :            :                 /**
     342                 :            :                  * setup tx ring slot to point to indirect
     343                 :            :                  * descriptor list stored in reserved region.
     344                 :            :                  * the first slot in indirect ring is already
     345                 :            :                  * preset to point to the header in reserved region
     346                 :            :                  **/
     347                 :          0 :                 start_dp[idx].addr =
     348                 :          0 :                         txvq->zxdh_net_hdr_mem + RTE_PTR_DIFF(&txr[idx].tx_packed_indir, txr);
     349                 :          0 :                 start_dp[idx].len  = (seg_num + 1) * sizeof(struct zxdh_vring_packed_desc);
     350                 :            :                 /* Packed descriptor id needs to be restored when inorder. */
     351         [ #  # ]:          0 :                 if (in_order)
     352                 :          0 :                         start_dp[idx].id = idx;
     353                 :            : 
     354                 :            :                 /* reset flags for indirect desc */
     355                 :            :                 head_flags = ZXDH_VRING_DESC_F_INDIRECT;
     356                 :          0 :                 head_flags |= vq->vq_packed.cached_flags;
     357                 :          0 :                 hdr = (void *)&txr[idx].tx_hdr;
     358                 :            :                 /* loop below will fill in rest of the indirect elements */
     359                 :            :                 start_dp = txr[idx].tx_packed_indir;
     360                 :          0 :                 start_dp->len = ZXDH_DL_NET_HDR_SIZE; /* update actual net or type hdr size */
     361                 :            :                 idx = 1;
     362                 :            :         } else {
     363                 :            :                 /* setup first tx ring slot to point to header stored in reserved region. */
     364                 :          0 :                 start_dp[idx].addr = txvq->zxdh_net_hdr_mem + RTE_PTR_DIFF(&txr[idx].tx_hdr, txr);
     365                 :          0 :                 start_dp[idx].len  = ZXDH_DL_NET_HDR_SIZE;
     366                 :          0 :                 head_flags |= ZXDH_VRING_DESC_F_NEXT;
     367                 :            :                 hdr = (void *)&txr[idx].tx_hdr;
     368                 :          0 :                 idx++;
     369         [ #  # ]:          0 :                 if (idx >= vq->vq_nentries) {
     370                 :          0 :                         idx -= vq->vq_nentries;
     371                 :          0 :                         vq->vq_packed.cached_flags ^= ZXDH_VRING_PACKED_DESC_F_AVAIL_USED;
     372                 :            :                 }
     373                 :            :         }
     374                 :          0 :         zxdh_xmit_fill_net_hdr(cookie, (struct zxdh_net_hdr_dl *)hdr);
     375                 :            : 
     376                 :            :         do {
     377                 :          0 :                 start_dp[idx].addr = rte_pktmbuf_iova(cookie);
     378                 :          0 :                 start_dp[idx].len  = cookie->data_len;
     379         [ #  # ]:          0 :                 if (likely(idx != head_idx)) {
     380                 :          0 :                         uint16_t flags = cookie->next ? ZXDH_VRING_DESC_F_NEXT : 0;
     381                 :          0 :                         flags |= vq->vq_packed.cached_flags;
     382                 :          0 :                         start_dp[idx].flags = flags;
     383                 :            :                 }
     384                 :            :                 prev = idx;
     385                 :          0 :                 idx++;
     386         [ #  # ]:          0 :                 if (idx >= vq->vq_nentries) {
     387                 :          0 :                         idx -= vq->vq_nentries;
     388                 :          0 :                         vq->vq_packed.cached_flags ^= ZXDH_VRING_PACKED_DESC_F_AVAIL_USED;
     389                 :            :                 }
     390         [ #  # ]:          0 :         } while ((cookie = cookie->next) != NULL);
     391                 :          0 :         start_dp[prev].id = id;
     392         [ #  # ]:          0 :         if (use_indirect) {
     393                 :            :                 idx = head_idx;
     394         [ #  # ]:          0 :                 if (++idx >= vq->vq_nentries) {
     395                 :          0 :                         idx -= vq->vq_nentries;
     396                 :          0 :                         vq->vq_packed.cached_flags ^= ZXDH_VRING_PACKED_DESC_F_AVAIL_USED;
     397                 :            :                 }
     398                 :            :         }
     399                 :          0 :         vq->vq_free_cnt = (uint16_t)(vq->vq_free_cnt - needed);
     400                 :          0 :         vq->vq_avail_idx = idx;
     401         [ #  # ]:          0 :         if (!in_order) {
     402                 :          0 :                 vq->vq_desc_head_idx = dxp->next;
     403         [ #  # ]:          0 :                 if (vq->vq_desc_head_idx == ZXDH_VQ_RING_DESC_CHAIN_END)
     404                 :          0 :                         vq->vq_desc_tail_idx = ZXDH_VQ_RING_DESC_CHAIN_END;
     405                 :            :         }
     406         [ #  # ]:          0 :         zxdh_queue_store_flags_packed(head_dp, head_flags, vq->hw->weak_barriers);
     407                 :          0 : }
     408                 :            : 
     409                 :            : static void
     410                 :          0 : zxdh_update_packet_stats(struct zxdh_virtnet_stats *stats, struct rte_mbuf *mbuf)
     411                 :            : {
     412                 :          0 :         uint32_t s = mbuf->pkt_len;
     413                 :            :         struct rte_ether_addr *ea = NULL;
     414                 :            : 
     415                 :          0 :         stats->bytes += s;
     416                 :            : 
     417         [ #  # ]:          0 :         if (s == 64) {
     418                 :          0 :                 stats->size_bins[1]++;
     419         [ #  # ]:          0 :         } else if (s > 64 && s < 1024) {
     420                 :            :                 uint32_t bin;
     421                 :            : 
     422                 :            :                 /* count zeros, and offset into correct bin */
     423                 :          0 :                 bin = (sizeof(s) * 8) - rte_clz32(s) - 5;
     424                 :          0 :                 stats->size_bins[bin]++;
     425                 :            :         } else {
     426         [ #  # ]:          0 :                 if (s < 64)
     427                 :          0 :                         stats->size_bins[0]++;
     428         [ #  # ]:          0 :                 else if (s < 1519)
     429                 :          0 :                         stats->size_bins[6]++;
     430                 :            :                 else
     431                 :          0 :                         stats->size_bins[7]++;
     432                 :            :         }
     433                 :            : 
     434         [ #  # ]:          0 :         ea = rte_pktmbuf_mtod(mbuf, struct rte_ether_addr *);
     435         [ #  # ]:          0 :         if (rte_is_multicast_ether_addr(ea)) {
     436         [ #  # ]:          0 :                 if (rte_is_broadcast_ether_addr(ea))
     437                 :          0 :                         stats->broadcast++;
     438                 :            :                 else
     439                 :          0 :                         stats->multicast++;
     440                 :            :         }
     441                 :          0 : }
     442                 :            : 
     443                 :            : uint16_t
     444                 :          0 : zxdh_xmit_pkts_packed(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
     445                 :            : {
     446                 :            :         struct zxdh_virtnet_tx *txvq = tx_queue;
     447                 :          0 :         struct zxdh_virtqueue  *vq   = txvq->vq;
     448         [ #  # ]:          0 :         struct zxdh_hw    *hw   = vq->hw;
     449                 :            :         uint16_t nb_tx = 0;
     450                 :            : 
     451                 :            :         bool in_order = zxdh_pci_with_feature(hw, ZXDH_F_IN_ORDER);
     452                 :            : 
     453         [ #  # ]:          0 :         if (nb_pkts > vq->vq_free_cnt)
     454         [ #  # ]:          0 :                 zxdh_xmit_cleanup_packed(vq, nb_pkts - vq->vq_free_cnt, in_order);
     455         [ #  # ]:          0 :         for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) {
     456         [ #  # ]:          0 :                 struct rte_mbuf *txm = tx_pkts[nb_tx];
     457                 :            :                 int32_t can_push     = 0;
     458                 :            :                 int32_t use_indirect = 0;
     459                 :            :                 int32_t slots        = 0;
     460                 :            :                 int32_t need         = 0;
     461                 :            : 
     462                 :            :                 /* optimize ring usage */
     463   [ #  #  #  # ]:          0 :                 if ((zxdh_pci_with_feature(hw, ZXDH_F_ANY_LAYOUT) ||
     464         [ #  # ]:          0 :                         zxdh_pci_with_feature(hw, ZXDH_F_VERSION_1)) &&
     465                 :          0 :                         rte_mbuf_refcnt_read(txm) == 1 &&
     466         [ #  # ]:          0 :                         RTE_MBUF_DIRECT(txm) &&
     467   [ #  #  #  # ]:          0 :                         txm->nb_segs == 1 &&
     468                 :            :                         rte_pktmbuf_headroom(txm) >= ZXDH_DL_NET_HDR_SIZE &&
     469                 :            :                         rte_is_aligned(rte_pktmbuf_mtod(txm, char *),
     470                 :            :                         alignof(struct zxdh_net_hdr_dl))) {
     471                 :            :                         can_push = 1;
     472         [ #  # ]:          0 :                 } else if (zxdh_pci_with_feature(hw, ZXDH_RING_F_INDIRECT_DESC) &&
     473         [ #  # ]:          0 :                                         txm->nb_segs < ZXDH_MAX_TX_INDIRECT) {
     474                 :            :                         use_indirect = 1;
     475                 :            :                 }
     476                 :            :                 /**
     477                 :            :                  * How many main ring entries are needed to this Tx?
     478                 :            :                  * indirect   => 1
     479                 :            :                  * any_layout => number of segments
     480                 :            :                  * default    => number of segments + 1
     481                 :            :                  **/
     482                 :          0 :                 slots = use_indirect ? 1 : (txm->nb_segs + !can_push);
     483                 :          0 :                 need = slots - vq->vq_free_cnt;
     484                 :            :                 /* Positive value indicates it need free vring descriptors */
     485         [ #  # ]:          0 :                 if (unlikely(need > 0)) {
     486                 :            :                         zxdh_xmit_cleanup_packed(vq, need, in_order);
     487                 :          0 :                         need = slots - vq->vq_free_cnt;
     488         [ #  # ]:          0 :                         if (unlikely(need > 0)) {
     489                 :          0 :                                 PMD_TX_LOG(ERR, "port[ep:%d, pf:%d, vf:%d, vfid:%d, pcieid:%d], queue:%d[pch:%d]. No free desc to xmit",
     490                 :            :                                         hw->vport.epid, hw->vport.pfid, hw->vport.vfid,
     491                 :            :                                         hw->vfid, hw->pcie_id, txvq->queue_id,
     492                 :            :                                         hw->channel_context[txvq->queue_id].ph_chno);
     493                 :          0 :                                 break;
     494                 :            :                         }
     495                 :            :                 }
     496         [ #  # ]:          0 :                 if (txm->nb_segs > ZXDH_TX_MAX_SEGS) {
     497                 :          0 :                         PMD_TX_LOG(ERR, "%d segs dropped", txm->nb_segs);
     498                 :          0 :                         txvq->stats.truncated_err += nb_pkts - nb_tx;
     499                 :          0 :                         break;
     500                 :            :                 }
     501                 :            :                 /* Enqueue Packet buffers */
     502         [ #  # ]:          0 :                 if (can_push)
     503                 :          0 :                         zxdh_enqueue_xmit_packed_fast(txvq, txm, in_order);
     504                 :            :                 else
     505                 :          0 :                         zxdh_enqueue_xmit_packed(txvq, txm, slots, use_indirect, in_order);
     506                 :          0 :                 zxdh_update_packet_stats(&txvq->stats, txm);
     507                 :            :         }
     508                 :          0 :         txvq->stats.packets += nb_tx;
     509         [ #  # ]:          0 :         if (likely(nb_tx)) {
     510         [ #  # ]:          0 :                 if (unlikely(zxdh_queue_kick_prepare_packed(vq))) {
     511                 :            :                         zxdh_queue_notify(vq);
     512                 :          0 :                         PMD_TX_LOG(DEBUG, "Notified backend after xmit");
     513                 :            :                 }
     514                 :            :         }
     515                 :          0 :         return nb_tx;
     516                 :            : }
     517                 :            : 
     518                 :          0 : uint16_t zxdh_xmit_pkts_prepare(void *tx_queue, struct rte_mbuf **tx_pkts,
     519                 :            :                                 uint16_t nb_pkts)
     520                 :            : {
     521                 :            :         struct zxdh_virtnet_tx *txvq = tx_queue;
     522                 :            :         uint16_t nb_tx;
     523                 :            : 
     524         [ #  # ]:          0 :         for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) {
     525                 :          0 :                 struct rte_mbuf *m = tx_pkts[nb_tx];
     526                 :            :                 int32_t error;
     527                 :            : 
     528                 :            : #ifdef RTE_LIBRTE_ETHDEV_DEBUG
     529                 :            :                 error = rte_validate_tx_offload(m);
     530                 :            :                 if (unlikely(error)) {
     531                 :            :                         rte_errno = -error;
     532                 :            :                         break;
     533                 :            :                 }
     534                 :            : #endif
     535                 :            : 
     536                 :            :                 error = rte_net_intel_cksum_prepare(m);
     537         [ #  # ]:          0 :                 if (unlikely(error)) {
     538                 :          0 :                         rte_errno = -error;
     539                 :          0 :                         break;
     540                 :            :                 }
     541         [ #  # ]:          0 :                 if (m->nb_segs > ZXDH_TX_MAX_SEGS) {
     542                 :          0 :                         PMD_TX_LOG(ERR, "%d segs dropped", m->nb_segs);
     543                 :          0 :                         txvq->stats.truncated_err += nb_pkts - nb_tx;
     544                 :          0 :                         rte_errno = ENOMEM;
     545                 :          0 :                         break;
     546                 :            :                 }
     547                 :            :         }
     548                 :          0 :         return nb_tx;
     549                 :            : }
     550                 :            : 
     551                 :          0 : static uint16_t zxdh_dequeue_burst_rx_packed(struct zxdh_virtqueue *vq,
     552                 :            :                                         struct rte_mbuf **rx_pkts,
     553                 :            :                                         uint32_t *len,
     554                 :            :                                         uint16_t num)
     555                 :            : {
     556                 :          0 :         struct zxdh_vring_packed_desc *desc = vq->vq_packed.ring.desc;
     557                 :            :         struct rte_mbuf *cookie = NULL;
     558                 :            :         uint16_t i, used_idx;
     559                 :            :         uint16_t id;
     560                 :            : 
     561         [ #  # ]:          0 :         for (i = 0; i < num; i++) {
     562                 :          0 :                 used_idx = vq->vq_used_cons_idx;
     563                 :            :                 /**
     564                 :            :                  * desc_is_used has a load-acquire or rte_io_rmb inside
     565                 :            :                  * and wait for used desc in virtqueue.
     566                 :            :                  */
     567         [ #  # ]:          0 :                 if (!zxdh_desc_used(&desc[used_idx], vq))
     568                 :          0 :                         return i;
     569                 :          0 :                 len[i] = desc[used_idx].len;
     570                 :          0 :                 id = desc[used_idx].id;
     571                 :          0 :                 cookie = (struct rte_mbuf *)vq->vq_descx[id].cookie;
     572                 :          0 :                 vq->vq_descx[id].cookie = NULL;
     573         [ #  # ]:          0 :                 if (unlikely(cookie == NULL)) {
     574                 :          0 :                         PMD_RX_LOG(ERR,
     575                 :            :                                 "vring descriptor with no mbuf cookie at %u", vq->vq_used_cons_idx);
     576                 :          0 :                         break;
     577                 :            :                 }
     578                 :          0 :                 rx_pkts[i] = cookie;
     579                 :          0 :                 vq->vq_free_cnt++;
     580                 :          0 :                 vq->vq_used_cons_idx++;
     581         [ #  # ]:          0 :                 if (vq->vq_used_cons_idx >= vq->vq_nentries) {
     582                 :          0 :                         vq->vq_used_cons_idx -= vq->vq_nentries;
     583                 :          0 :                         vq->vq_packed.used_wrap_counter ^= 1;
     584                 :            :                 }
     585                 :            :         }
     586                 :            :         return i;
     587                 :            : }
     588                 :            : 
     589                 :          0 : static int32_t zxdh_rx_update_mbuf(struct rte_mbuf *m, struct zxdh_net_hdr_ul *hdr)
     590                 :            : {
     591                 :            :         struct zxdh_pd_hdr_ul *pd_hdr = &hdr->pd_hdr;
     592                 :            :         struct zxdh_pi_hdr *pi_hdr = &hdr->pi_hdr;
     593                 :            :         uint32_t idx = 0;
     594                 :            : 
     595         [ #  # ]:          0 :         m->pkt_len = rte_be_to_cpu_16(pi_hdr->ul.pkt_len);
     596                 :            : 
     597         [ #  # ]:          0 :         uint16_t pkt_type_outer = rte_be_to_cpu_16(pd_hdr->pkt_type_out);
     598                 :            : 
     599                 :          0 :         idx = (pkt_type_outer >> 12) & 0xF;
     600                 :          0 :         m->packet_type  = zxdh_outer_l2_type[idx];
     601                 :          0 :         idx = (pkt_type_outer >> 8)  & 0xF;
     602                 :          0 :         m->packet_type |= zxdh_outer_l3_type[idx];
     603                 :          0 :         idx = (pkt_type_outer >> 4)  & 0xF;
     604                 :          0 :         m->packet_type |= zxdh_outer_l4_type[idx];
     605                 :          0 :         idx = pkt_type_outer         & 0xF;
     606                 :          0 :         m->packet_type |= zxdh_tunnel_type[idx];
     607                 :            : 
     608         [ #  # ]:          0 :         uint16_t pkt_type_inner = rte_be_to_cpu_16(pd_hdr->pkt_type_in);
     609                 :            : 
     610         [ #  # ]:          0 :         if (pkt_type_inner) {
     611                 :          0 :                 idx = (pkt_type_inner >> 12) & 0xF;
     612                 :          0 :                 m->packet_type |= zxdh_inner_l2_type[idx];
     613                 :          0 :                 idx = (pkt_type_inner >> 8)  & 0xF;
     614                 :          0 :                 m->packet_type |= zxdh_inner_l3_type[idx];
     615                 :          0 :                 idx = (pkt_type_inner >> 4)  & 0xF;
     616                 :          0 :                 m->packet_type |= zxdh_inner_l4_type[idx];
     617                 :            :         }
     618                 :            : 
     619                 :          0 :         return 0;
     620                 :            : }
     621                 :            : 
     622                 :          0 : static void zxdh_discard_rxbuf(struct zxdh_virtqueue *vq, struct rte_mbuf *m)
     623                 :            : {
     624                 :            :         int32_t error = 0;
     625                 :            :         /*
     626                 :            :          * Requeue the discarded mbuf. This should always be
     627                 :            :          * successful since it was just dequeued.
     628                 :            :          */
     629                 :          0 :         error = zxdh_enqueue_recv_refill_packed(vq, &m, 1);
     630         [ #  # ]:          0 :         if (unlikely(error)) {
     631                 :          0 :                 PMD_RX_LOG(ERR, "cannot enqueue discarded mbuf");
     632                 :          0 :                 rte_pktmbuf_free(m);
     633                 :            :         }
     634                 :          0 : }
     635                 :            : 
     636                 :          0 : uint16_t zxdh_recv_pkts_packed(void *rx_queue, struct rte_mbuf **rx_pkts,
     637                 :            :                                 uint16_t nb_pkts)
     638                 :            : {
     639                 :            :         struct zxdh_virtnet_rx *rxvq = rx_queue;
     640                 :          0 :         struct zxdh_virtqueue *vq = rxvq->vq;
     641                 :          0 :         struct zxdh_hw *hw = vq->hw;
     642                 :          0 :         struct rte_eth_dev *dev = hw->eth_dev;
     643                 :            :         struct rte_mbuf *rxm = NULL;
     644                 :            :         struct rte_mbuf *prev = NULL;
     645                 :          0 :         uint32_t len[ZXDH_MBUF_BURST_SZ] = {0};
     646                 :          0 :         struct rte_mbuf *rcv_pkts[ZXDH_MBUF_BURST_SZ] = {NULL};
     647                 :            :         uint32_t nb_enqueued = 0;
     648                 :            :         uint32_t seg_num = 0;
     649                 :            :         uint32_t seg_res = 0;
     650                 :            :         uint16_t hdr_size = 0;
     651                 :            :         int32_t error = 0;
     652                 :            :         uint16_t nb_rx = 0;
     653                 :            :         uint16_t num = nb_pkts;
     654                 :            : 
     655         [ #  # ]:          0 :         if (unlikely(num > ZXDH_MBUF_BURST_SZ))
     656                 :            :                 num = ZXDH_MBUF_BURST_SZ;
     657                 :            : 
     658                 :          0 :         num = zxdh_dequeue_burst_rx_packed(vq, rcv_pkts, len, num);
     659                 :            :         uint16_t i;
     660                 :            :         uint16_t rcvd_pkt_len = 0;
     661                 :            : 
     662         [ #  # ]:          0 :         for (i = 0; i < num; i++) {
     663                 :          0 :                 rxm = rcv_pkts[i];
     664         [ #  # ]:          0 :                 if (unlikely(len[i] < ZXDH_UL_NET_HDR_SIZE)) {
     665                 :          0 :                         nb_enqueued++;
     666                 :          0 :                         PMD_RX_LOG(ERR, "RX, len:%u err", len[i]);
     667                 :          0 :                         zxdh_discard_rxbuf(vq, rxm);
     668                 :          0 :                         rxvq->stats.errors++;
     669                 :          0 :                         continue;
     670                 :            :                 }
     671                 :          0 :                 struct zxdh_net_hdr_ul *header =
     672                 :          0 :                         (struct zxdh_net_hdr_ul *)((char *)rxm->buf_addr +
     673                 :            :                         RTE_PKTMBUF_HEADROOM);
     674                 :            : 
     675                 :          0 :                 seg_num  = header->type_hdr.num_buffers;
     676         [ #  # ]:          0 :                 if (seg_num == 0) {
     677                 :          0 :                         PMD_RX_LOG(ERR, "dequeue %d pkt, No.%d pkt seg_num is %d", num, i, seg_num);
     678                 :            :                         seg_num = 1;
     679                 :            :                 }
     680         [ #  # ]:          0 :                 if (seg_num > ZXDH_RX_MAX_SEGS) {
     681                 :          0 :                         PMD_RX_LOG(ERR, "dequeue %d pkt, No.%d pkt seg_num is %d", num, i, seg_num);
     682                 :          0 :                         nb_enqueued++;
     683                 :          0 :                         zxdh_discard_rxbuf(vq, rxm);
     684                 :          0 :                         rxvq->stats.errors++;
     685                 :          0 :                         continue;
     686                 :            :                 }
     687                 :            :                 /* bit[0:6]-pd_len unit:2B */
     688                 :          0 :                 uint16_t pd_len = header->type_hdr.pd_len << 1;
     689         [ #  # ]:          0 :                 if (pd_len > ZXDH_PD_HDR_SIZE_MAX || pd_len < ZXDH_PD_HDR_SIZE_MIN) {
     690                 :          0 :                         PMD_RX_LOG(ERR, "pd_len:%d is invalid", pd_len);
     691                 :          0 :                         nb_enqueued++;
     692                 :          0 :                         zxdh_discard_rxbuf(vq, rxm);
     693                 :          0 :                         rxvq->stats.errors++;
     694                 :          0 :                         continue;
     695                 :            :                 }
     696                 :            :                 /* Private queue only handle type hdr */
     697                 :            :                 hdr_size = pd_len;
     698                 :          0 :                 rxm->data_off = RTE_PKTMBUF_HEADROOM + hdr_size;
     699                 :          0 :                 rxm->nb_segs = seg_num;
     700                 :          0 :                 rxm->ol_flags = 0;
     701                 :          0 :                 rxm->vlan_tci = 0;
     702                 :          0 :                 rcvd_pkt_len = (uint32_t)(len[i] - hdr_size);
     703                 :          0 :                 rxm->data_len = (uint16_t)(len[i] - hdr_size);
     704                 :          0 :                 rxm->port = rxvq->port_id;
     705                 :          0 :                 rx_pkts[nb_rx] = rxm;
     706                 :            :                 prev = rxm;
     707                 :            :                 /* Update rte_mbuf according to pi/pd header */
     708         [ #  # ]:          0 :                 if (zxdh_rx_update_mbuf(rxm, header) < 0) {
     709                 :          0 :                         zxdh_discard_rxbuf(vq, rxm);
     710                 :          0 :                         rxvq->stats.errors++;
     711                 :          0 :                         continue;
     712                 :            :                 }
     713                 :          0 :                 seg_res = seg_num - 1;
     714                 :            :                 /* Merge remaining segments */
     715   [ #  #  #  # ]:          0 :                 while (seg_res != 0 && i < (num - 1)) {
     716                 :          0 :                         i++;
     717                 :          0 :                         rxm = rcv_pkts[i];
     718                 :          0 :                         rxm->data_off = RTE_PKTMBUF_HEADROOM;
     719                 :          0 :                         rxm->data_len = (uint16_t)(len[i]);
     720                 :            : 
     721                 :          0 :                         rcvd_pkt_len += (uint32_t)(len[i]);
     722                 :          0 :                         prev->next = rxm;
     723                 :            :                         prev = rxm;
     724                 :          0 :                         rxm->next = NULL;
     725                 :          0 :                         seg_res -= 1;
     726                 :            :                 }
     727                 :            : 
     728         [ #  # ]:          0 :                 if (!seg_res) {
     729         [ #  # ]:          0 :                         if (rcvd_pkt_len != rx_pkts[nb_rx]->pkt_len) {
     730                 :          0 :                                 PMD_RX_LOG(ERR, "dropped rcvd_pkt_len %d pktlen %d",
     731                 :            :                                         rcvd_pkt_len, rx_pkts[nb_rx]->pkt_len);
     732                 :          0 :                                 zxdh_discard_rxbuf(vq, rx_pkts[nb_rx]);
     733                 :          0 :                                 rxvq->stats.errors++;
     734                 :          0 :                                 rxvq->stats.truncated_err++;
     735                 :          0 :                                 continue;
     736                 :            :                         }
     737                 :          0 :                         zxdh_update_packet_stats(&rxvq->stats, rx_pkts[nb_rx]);
     738                 :          0 :                         nb_rx++;
     739                 :            :                 }
     740                 :            :         }
     741                 :            :         /* Last packet still need merge segments */
     742         [ #  # ]:          0 :         while (seg_res != 0) {
     743                 :          0 :                 uint16_t rcv_cnt = RTE_MIN((uint16_t)seg_res, ZXDH_MBUF_BURST_SZ);
     744                 :            :                 uint16_t extra_idx = 0;
     745                 :            : 
     746                 :          0 :                 rcv_cnt = zxdh_dequeue_burst_rx_packed(vq, rcv_pkts, len, rcv_cnt);
     747         [ #  # ]:          0 :                 if (unlikely(rcv_cnt == 0)) {
     748                 :          0 :                         PMD_RX_LOG(ERR, "No enough segments for packet");
     749                 :          0 :                         rte_pktmbuf_free(rx_pkts[nb_rx]);
     750                 :          0 :                         rxvq->stats.errors++;
     751                 :          0 :                         break;
     752                 :            :                 }
     753         [ #  # ]:          0 :                 while (extra_idx < rcv_cnt) {
     754                 :          0 :                         rxm = rcv_pkts[extra_idx];
     755                 :          0 :                         rxm->data_off = RTE_PKTMBUF_HEADROOM;
     756                 :          0 :                         rxm->pkt_len = (uint32_t)(len[extra_idx]);
     757                 :          0 :                         rxm->data_len = (uint16_t)(len[extra_idx]);
     758                 :          0 :                         prev->next = rxm;
     759                 :            :                         prev = rxm;
     760                 :          0 :                         rxm->next = NULL;
     761                 :          0 :                         rcvd_pkt_len += len[extra_idx];
     762                 :          0 :                         extra_idx += 1;
     763                 :            :                 }
     764                 :          0 :                 seg_res -= rcv_cnt;
     765         [ #  # ]:          0 :                 if (!seg_res) {
     766         [ #  # ]:          0 :                         if (rcvd_pkt_len != rx_pkts[nb_rx]->pkt_len) {
     767                 :          0 :                                 PMD_RX_LOG(ERR, "dropped rcvd_pkt_len %d pktlen %d",
     768                 :            :                                         rcvd_pkt_len, rx_pkts[nb_rx]->pkt_len);
     769                 :          0 :                                 zxdh_discard_rxbuf(vq, rx_pkts[nb_rx]);
     770                 :          0 :                                 rxvq->stats.errors++;
     771                 :          0 :                                 rxvq->stats.truncated_err++;
     772                 :          0 :                                 continue;
     773                 :            :                         }
     774                 :          0 :                         zxdh_update_packet_stats(&rxvq->stats, rx_pkts[nb_rx]);
     775                 :          0 :                         nb_rx++;
     776                 :            :                 }
     777                 :            :         }
     778         [ #  # ]:          0 :         rxvq->stats.packets += nb_rx;
     779                 :            : 
     780                 :            :         /* Allocate new mbuf for the used descriptor */
     781         [ #  # ]:          0 :         if (likely(!zxdh_queue_full(vq))) {
     782                 :            :                 /* free_cnt may include mrg descs */
     783                 :            :                 uint16_t free_cnt = vq->vq_free_cnt;
     784                 :          0 :                 struct rte_mbuf *new_pkts[free_cnt];
     785                 :            : 
     786         [ #  # ]:          0 :                 if (!rte_pktmbuf_alloc_bulk(rxvq->mpool, new_pkts, free_cnt)) {
     787                 :          0 :                         error = zxdh_enqueue_recv_refill_packed(vq, new_pkts, free_cnt);
     788         [ #  # ]:          0 :                         if (unlikely(error)) {
     789         [ #  # ]:          0 :                                 for (i = 0; i < free_cnt; i++)
     790                 :          0 :                                         rte_pktmbuf_free(new_pkts[i]);
     791                 :            :                         }
     792                 :          0 :                         nb_enqueued += free_cnt;
     793                 :            :                 } else {
     794                 :          0 :                         dev->data->rx_mbuf_alloc_failed += free_cnt;
     795                 :            :                 }
     796                 :            :         }
     797         [ #  # ]:          0 :         if (likely(nb_enqueued)) {
     798         [ #  # ]:          0 :                 if (unlikely(zxdh_queue_kick_prepare_packed(vq))) {
     799                 :            :                         zxdh_queue_notify(vq);
     800                 :          0 :                         PMD_RX_LOG(DEBUG, "Notified");
     801                 :            :                 }
     802                 :            :         }
     803                 :          0 :         return nb_rx;
     804                 :            : }

Generated by: LCOV version 1.14