Add simple Tx xmit functions (zxdh_xmit_pkts_simple)
for single-segment packet xmit.

Signed-off-by: Junlong Wang <[email protected]>
---
 drivers/net/zxdh/zxdh_ethdev.c |  11 +-
 drivers/net/zxdh/zxdh_rxtx.c   | 341 +++++++++++++++++++++++++--------
 drivers/net/zxdh/zxdh_rxtx.h   |  11 +-
 3 files changed, 271 insertions(+), 92 deletions(-)

diff --git a/drivers/net/zxdh/zxdh_ethdev.c b/drivers/net/zxdh/zxdh_ethdev.c
index 0ab137189b..54d43b54d9 100644
--- a/drivers/net/zxdh/zxdh_ethdev.c
+++ b/drivers/net/zxdh/zxdh_ethdev.c
@@ -490,7 +490,7 @@ zxdh_dev_free_mbufs(struct rte_eth_dev *dev)
                if (!vq)
                        continue;
                while ((buf = zxdh_queue_detach_unused(vq)) != NULL)
-                       rte_pktmbuf_free(buf);
+                       rte_pktmbuf_free_seg(buf);
                PMD_DRV_LOG(DEBUG, "freeing %s[%d] used and unused buf",
                "rxq", i * 2);
        }
@@ -499,7 +499,7 @@ zxdh_dev_free_mbufs(struct rte_eth_dev *dev)
                if (!vq)
                        continue;
                while ((buf = zxdh_queue_detach_unused(vq)) != NULL)
-                       rte_pktmbuf_free(buf);
+                       rte_pktmbuf_free_seg(buf);
                PMD_DRV_LOG(DEBUG, "freeing %s[%d] used and unused buf",
                "txq", i * 2 + 1);
        }
@@ -1291,10 +1291,15 @@ static int zxdh_scattered_rx(struct rte_eth_dev 
*eth_dev)
 static int32_t
 zxdh_set_rxtx_funcs(struct rte_eth_dev *eth_dev)
 {
+       uint64_t tx_offloads = eth_dev->data->dev_conf.txmode.offloads;
+
        eth_dev->tx_pkt_prepare = zxdh_xmit_pkts_prepare;
        eth_dev->data->scattered_rx = zxdh_scattered_rx(eth_dev);
 
-       eth_dev->tx_pkt_burst = &zxdh_xmit_pkts_packed;
+       if (!(tx_offloads & RTE_ETH_TX_OFFLOAD_MULTI_SEGS))
+               eth_dev->tx_pkt_burst = &zxdh_xmit_pkts_simple;
+       else
+               eth_dev->tx_pkt_burst = &zxdh_xmit_pkts_packed;
 
        if (eth_dev->data->scattered_rx)
                eth_dev->rx_pkt_burst = &zxdh_recv_pkts_packed;
diff --git a/drivers/net/zxdh/zxdh_rxtx.c b/drivers/net/zxdh/zxdh_rxtx.c
index 4723d4b1d2..e8f1cd65b0 100644
--- a/drivers/net/zxdh/zxdh_rxtx.c
+++ b/drivers/net/zxdh/zxdh_rxtx.c
@@ -114,6 +114,22 @@
                RTE_MBUF_F_TX_SEC_OFFLOAD |     \
                RTE_MBUF_F_TX_UDP_SEG)
 
+#if RTE_CACHE_LINE_SIZE == 128
+#define NEXT_CACHELINE_OFF_16B   8
+#define NEXT_CACHELINE_OFF_8B   16
+#elif RTE_CACHE_LINE_SIZE == 64
+#define NEXT_CACHELINE_OFF_16B   4
+#define NEXT_CACHELINE_OFF_8B    8
+#else
+#define NEXT_CACHELINE_OFF_16B  (RTE_CACHE_LINE_SIZE / 16)
+#define NEXT_CACHELINE_OFF_8B   (RTE_CACHE_LINE_SIZE / 8)
+#endif
+#define N_PER_LOOP  NEXT_CACHELINE_OFF_8B
+#define N_PER_LOOP_MASK (N_PER_LOOP - 1)
+
+#define rxq_get_vq(q) ((q)->vq)
+#define txq_get_vq(q) ((q)->vq)
+
 uint32_t zxdh_outer_l2_type[16] = {
        0,
        RTE_PTYPE_L2_ETHER,
@@ -201,43 +217,6 @@ uint32_t zxdh_inner_l4_type[16] = {
        0,
 };
 
-static void
-zxdh_xmit_cleanup_inorder_packed(struct zxdh_virtqueue *vq, int32_t num)
-{
-       uint16_t used_idx = 0;
-       uint16_t id       = 0;
-       uint16_t curr_id  = 0;
-       uint16_t free_cnt = 0;
-       uint16_t size     = vq->vq_nentries;
-       struct zxdh_vring_packed_desc *desc = vq->vq_packed.ring.desc;
-       struct zxdh_vq_desc_extra     *dxp  = NULL;
-
-       used_idx = vq->vq_used_cons_idx;
-       /* desc_is_used has a load-acquire or rte_io_rmb inside
-        * and wait for used desc in virtqueue.
-        */
-       while (num > 0 && desc_is_used(&desc[used_idx], vq)) {
-               id = desc[used_idx].id;
-               do {
-                       curr_id = used_idx;
-                       dxp = &vq->vq_descx[used_idx];
-                       used_idx += dxp->ndescs;
-                       free_cnt += dxp->ndescs;
-                       num -= dxp->ndescs;
-                       if (used_idx >= size) {
-                               used_idx -= size;
-                               vq->used_wrap_counter ^= 1;
-                       }
-                       if (dxp->cookie != NULL) {
-                               rte_pktmbuf_free(dxp->cookie);
-                               dxp->cookie = NULL;
-                       }
-               } while (curr_id != id);
-       }
-       vq->vq_used_cons_idx = used_idx;
-       vq->vq_free_cnt += free_cnt;
-}
-
 static inline uint16_t
 zxdh_get_mtu(struct zxdh_virtqueue *vq)
 {
@@ -334,7 +313,7 @@ zxdh_xmit_fill_net_hdr(struct zxdh_virtqueue *vq, struct 
rte_mbuf *cookie,
 }
 
 static inline void
-zxdh_enqueue_xmit_packed_fast(struct zxdh_virtnet_tx *txvq,
+zxdh_xmit_enqueue_push(struct zxdh_virtnet_tx *txvq,
                                                struct rte_mbuf *cookie)
 {
        struct zxdh_virtqueue *vq = txvq->vq;
@@ -345,7 +324,6 @@ zxdh_enqueue_xmit_packed_fast(struct zxdh_virtnet_tx *txvq,
        uint8_t hdr_len = vq->hw->dl_net_hdr_len;
        struct zxdh_vring_packed_desc *dp = &vq->vq_packed.ring.desc[id];
 
-       dxp->ndescs = 1;
        dxp->cookie = cookie;
        hdr = rte_pktmbuf_mtod_offset(cookie, struct zxdh_net_hdr_dl *, 
-hdr_len);
        zxdh_xmit_fill_net_hdr(vq, cookie, hdr);
@@ -362,52 +340,57 @@ zxdh_enqueue_xmit_packed_fast(struct zxdh_virtnet_tx 
*txvq,
 }
 
 static inline void
-zxdh_enqueue_xmit_packed(struct zxdh_virtnet_tx *txvq,
+zxdh_xmit_enqueue_append(struct zxdh_virtnet_tx *txvq,
                                                struct rte_mbuf *cookie,
                                                uint16_t needed)
 {
        struct zxdh_tx_region *txr = txvq->zxdh_net_hdr_mz->addr;
        struct zxdh_virtqueue *vq = txvq->vq;
-       uint16_t id = vq->vq_avail_idx;
-       struct zxdh_vq_desc_extra *dxp = &vq->vq_descx[id];
+       struct zxdh_vq_desc_extra *dep = &vq->vq_descx[0];
        uint16_t head_idx = vq->vq_avail_idx;
        uint16_t idx = head_idx;
        struct zxdh_vring_packed_desc *start_dp = vq->vq_packed.ring.desc;
        struct zxdh_vring_packed_desc *head_dp = &vq->vq_packed.ring.desc[idx];
        struct zxdh_net_hdr_dl *hdr = NULL;
-
-       uint16_t head_flags = cookie->next ? ZXDH_VRING_DESC_F_NEXT : 0;
+       uint16_t id = vq->vq_avail_idx;
+       struct zxdh_vq_desc_extra *dxp = &vq->vq_descx[id];
        uint8_t hdr_len = vq->hw->dl_net_hdr_len;
+       uint16_t head_flags = 0;
 
-       dxp->ndescs = needed;
-       dxp->cookie = cookie;
-       head_flags |= vq->cached_flags;
+       /*
+        * IMPORTANT: For multi-seg packets, we set the head descriptor's 
cookie to NULL
+        * and store each segment's mbuf in its corresponding 
vq_descx[idx].cookie.
+        * This is required for the per-descriptor mbuf free in 
zxdh_xmit_fast_flush()
+        * which uses rte_pktmbuf_free_seg() to free individual segments.
+        * Any code path that attempts to read vq_descx[head_id].cookie will 
see NULL
+        * and must handle this case appropriately.
+        */
+       dxp->cookie = NULL;
 
+       /* setup first tx ring slot to point to header stored in reserved 
region. */
        start_dp[idx].addr = txvq->zxdh_net_hdr_mem + 
RTE_PTR_DIFF(&txr[idx].tx_hdr, txr);
        start_dp[idx].len  = hdr_len;
-       head_flags |= ZXDH_VRING_DESC_F_NEXT;
+       start_dp[idx].id = idx;
+       head_flags |= vq->cached_flags | ZXDH_VRING_DESC_F_NEXT;
        hdr = (void *)&txr[idx].tx_hdr;
 
-       rte_prefetch1(hdr);
+       zxdh_xmit_fill_net_hdr(vq, cookie, hdr);
+
        idx++;
        if (idx >= vq->vq_nentries) {
                idx -= vq->vq_nentries;
                vq->cached_flags ^= ZXDH_VRING_PACKED_DESC_F_AVAIL_USED;
        }
 
-       zxdh_xmit_fill_net_hdr(vq, cookie, hdr);
-
        do {
                start_dp[idx].addr = rte_pktmbuf_iova(cookie);
                start_dp[idx].len  = cookie->data_len;
-               start_dp[idx].id = id;
-               if (likely(idx != head_idx)) {
-                       uint16_t flags = cookie->next ? ZXDH_VRING_DESC_F_NEXT 
: 0;
-
-                       flags |= vq->cached_flags;
-                       start_dp[idx].flags = flags;
-               }
+               start_dp[idx].id = idx;
 
+               dep[idx].cookie = cookie;
+               uint16_t flags = cookie->next ? ZXDH_VRING_DESC_F_NEXT : 0;
+               flags |= vq->cached_flags;
+               start_dp[idx].flags = flags;
                idx++;
                if (idx >= vq->vq_nentries) {
                        idx -= vq->vq_nentries;
@@ -417,7 +400,6 @@ zxdh_enqueue_xmit_packed(struct zxdh_virtnet_tx *txvq,
 
        vq->vq_free_cnt = (uint16_t)(vq->vq_free_cnt - needed);
        vq->vq_avail_idx = idx;
-
        zxdh_queue_store_flags_packed(head_dp, head_flags);
 }
 
@@ -456,7 +438,7 @@ zxdh_update_packet_stats(struct zxdh_virtnet_stats *stats, 
struct rte_mbuf *mbuf
 }
 
 static void
-zxdh_xmit_flush(struct zxdh_virtqueue *vq)
+zxdh_xmit_fast_flush(struct zxdh_virtqueue *vq)
 {
        uint16_t id       = 0;
        uint16_t curr_id  = 0;
@@ -472,20 +454,22 @@ zxdh_xmit_flush(struct zxdh_virtqueue *vq)
         * for a used descriptor in the virtqueue.
         */
        while (desc_is_used(&desc[used_idx], vq)) {
+               rte_prefetch0(&desc[used_idx + NEXT_CACHELINE_OFF_16B]);
                id = desc[used_idx].id;
                do {
+                       desc[used_idx].id = used_idx;
                        curr_id = used_idx;
                        dxp = &vq->vq_descx[used_idx];
-                       used_idx += dxp->ndescs;
-                       free_cnt += dxp->ndescs;
-                       if (used_idx >= size) {
-                               used_idx -= size;
-                               vq->used_wrap_counter ^= 1;
-                       }
                        if (dxp->cookie != NULL) {
-                               rte_pktmbuf_free(dxp->cookie);
+                               rte_pktmbuf_free_seg(dxp->cookie);
                                dxp->cookie = NULL;
                        }
+                       used_idx += 1;
+                       free_cnt += 1;
+                       if (unlikely(used_idx == size)) {
+                               used_idx = 0;
+                               vq->used_wrap_counter ^= 1;
+                       }
                } while (curr_id != id);
        }
        vq->vq_used_cons_idx = used_idx;
@@ -499,13 +483,12 @@ zxdh_xmit_pkts_packed(void *tx_queue, struct rte_mbuf 
**tx_pkts, uint16_t nb_pkt
        struct zxdh_virtqueue  *vq   = txvq->vq;
        uint16_t nb_tx = 0;
 
-       zxdh_xmit_flush(vq);
+       zxdh_xmit_fast_flush(vq);
 
        for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) {
                struct rte_mbuf *txm = tx_pkts[nb_tx];
                int32_t can_push     = 0;
                int32_t slots        = 0;
-               int32_t need         = 0;
 
                rte_prefetch0(txm);
                /* optimize ring usage */
@@ -522,26 +505,15 @@ zxdh_xmit_pkts_packed(void *tx_queue, struct rte_mbuf 
**tx_pkts, uint16_t nb_pkt
                 * default    => number of segments + 1
                 **/
                slots = txm->nb_segs + !can_push;
-               need = slots - vq->vq_free_cnt;
                /* Positive value indicates it need free vring descriptors */
-               if (unlikely(need > 0)) {
-                       zxdh_xmit_cleanup_inorder_packed(vq, need);
-                       need = slots - vq->vq_free_cnt;
-                       if (unlikely(need > 0)) {
-                               PMD_TX_LOG(ERR,
-                                               " No enough %d free tx 
descriptors to transmit."
-                                               "freecnt %d",
-                                               need,
-                                               vq->vq_free_cnt);
-                               break;
-                       }
-               }
+               if (unlikely(slots >  vq->vq_free_cnt))
+                       break;
 
                /* Enqueue Packet buffers */
                if (can_push)
-                       zxdh_enqueue_xmit_packed_fast(txvq, txm);
+                       zxdh_xmit_enqueue_push(txvq, txm);
                else
-                       zxdh_enqueue_xmit_packed(txvq, txm, slots);
+                       zxdh_xmit_enqueue_append(txvq, txm, slots);
                zxdh_update_packet_stats(&txvq->stats, txm);
        }
        txvq->stats.packets += nb_tx;
@@ -1083,3 +1055,204 @@ uint16_t zxdh_recv_single_pkts(void *rx_queue, struct 
rte_mbuf **rcv_pkts, uint1
        }
        return nb_rx;
 }
+
+static inline void pkt_padding(struct rte_mbuf *cookie, struct zxdh_hw *hw)
+{
+       uint16_t mtu_or_mss = 0;
+       uint16_t pkt_flag_lw16 = ZXDH_NO_IPID_UPDATE;
+       uint16_t l3_offset;
+       uint8_t pcode = ZXDH_PCODE_NO_IP_PKT_TYPE;
+       uint8_t l3_ptype = ZXDH_PI_L3TYPE_NOIP;
+       struct zxdh_pi_hdr *pi_hdr;
+       struct zxdh_pd_hdr_dl *pd_hdr;
+       struct zxdh_net_hdr_dl *net_hdr_dl = hw->net_hdr_dl;
+       uint8_t hdr_len = hw->dl_net_hdr_len;
+       uint16_t ol_flag = 0;
+       struct zxdh_net_hdr_dl *hdr;
+
+       hdr = (struct zxdh_net_hdr_dl *)rte_pktmbuf_prepend(cookie, hdr_len);
+       rte_memcpy(hdr, net_hdr_dl, hdr_len);
+
+       if (hw->has_tx_offload) {
+               pi_hdr = &hdr->pipd_hdr_dl.pi_hdr;
+               pd_hdr = &hdr->pipd_hdr_dl.pd_hdr;
+
+               pcode = ZXDH_PCODE_IP_PKT_TYPE;
+               if (cookie->ol_flags & RTE_MBUF_F_TX_IPV6)
+                       l3_ptype = ZXDH_PI_L3TYPE_IPV6;
+               else if (cookie->ol_flags & RTE_MBUF_F_TX_IPV4)
+                       l3_ptype = ZXDH_PI_L3TYPE_IP;
+               else
+                       pcode = ZXDH_PCODE_NO_IP_PKT_TYPE;
+
+               if (cookie->ol_flags & RTE_MBUF_F_TX_TCP_SEG) {
+                       mtu_or_mss = (cookie->tso_segsz >= ZXDH_MIN_MSS) ?
+                               cookie->tso_segsz : ZXDH_MIN_MSS;
+                       pi_hdr->pkt_flag_hi8  |= ZXDH_TX_TCPUDP_CKSUM_CAL;
+                       pkt_flag_lw16 |= ZXDH_NO_IP_FRAGMENT | 
ZXDH_TX_IP_CKSUM_CAL;
+                       pcode = ZXDH_PCODE_TCP_PKT_TYPE;
+               } else if (cookie->ol_flags & RTE_MBUF_F_TX_UDP_SEG) {
+                       mtu_or_mss = hw->eth_dev->data->mtu;
+                       mtu_or_mss = (mtu_or_mss >= ZXDH_MIN_MSS) ? mtu_or_mss 
: ZXDH_MIN_MSS;
+                       pkt_flag_lw16 |= ZXDH_TX_IP_CKSUM_CAL;
+                       pi_hdr->pkt_flag_hi8 |= ZXDH_NO_TCP_FRAGMENT | 
ZXDH_TX_TCPUDP_CKSUM_CAL;
+                       pcode = ZXDH_PCODE_UDP_PKT_TYPE;
+               } else {
+                       pkt_flag_lw16 |= ZXDH_NO_IP_FRAGMENT;
+                       pi_hdr->pkt_flag_hi8 |= ZXDH_NO_TCP_FRAGMENT;
+               }
+
+               if (cookie->ol_flags & RTE_MBUF_F_TX_IP_CKSUM)
+                       pkt_flag_lw16 |= ZXDH_TX_IP_CKSUM_CAL;
+
+               if ((cookie->ol_flags & RTE_MBUF_F_TX_UDP_CKSUM) == 
RTE_MBUF_F_TX_UDP_CKSUM) {
+                       pcode = ZXDH_PCODE_UDP_PKT_TYPE;
+                       pi_hdr->pkt_flag_hi8 |= ZXDH_TX_TCPUDP_CKSUM_CAL;
+               } else if ((cookie->ol_flags & RTE_MBUF_F_TX_TCP_CKSUM) ==
+                       RTE_MBUF_F_TX_TCP_CKSUM) {
+                       pcode = ZXDH_PCODE_TCP_PKT_TYPE;
+                       pi_hdr->pkt_flag_hi8 |= ZXDH_TX_TCPUDP_CKSUM_CAL;
+               }
+               pkt_flag_lw16 |= (mtu_or_mss >> ZXDH_MTU_MSS_UNIT_SHIFTBIT) & 
ZXDH_MTU_MSS_MASK;
+               pi_hdr->pkt_flag_lw16 = rte_be_to_cpu_16(pkt_flag_lw16);
+               pi_hdr->pkt_type = l3_ptype | ZXDH_PKT_FORM_CPU | pcode;
+
+               l3_offset = hdr_len + cookie->l2_len;
+               l3_offset += (cookie->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) ?
+                                       cookie->outer_l2_len + 
cookie->outer_l3_len : 0;
+               pi_hdr->l3_offset = rte_be_to_cpu_16(l3_offset);
+               pi_hdr->l4_offset = rte_be_to_cpu_16(l3_offset + 
cookie->l3_len);
+               if (cookie->ol_flags & RTE_MBUF_F_TX_OUTER_IP_CKSUM)
+                       ol_flag |= ZXDH_PD_OFFLOAD_OUTER_IPCSUM;
+       } else {
+               pd_hdr = &hdr->pd_hdr;
+       }
+
+       pd_hdr->dst_vfid = rte_be_to_cpu_16(cookie->port);
+
+       if (cookie->ol_flags & (RTE_MBUF_F_TX_VLAN | RTE_MBUF_F_TX_QINQ)) {
+               ol_flag |= ZXDH_PD_OFFLOAD_CVLAN_INSERT;
+               pd_hdr->cvlan_insert = rte_be_to_cpu_16(cookie->vlan_tci);
+               if (cookie->ol_flags & RTE_MBUF_F_TX_QINQ) {
+                       ol_flag |= ZXDH_PD_OFFLOAD_SVLAN_INSERT;
+                       pd_hdr->svlan_insert = 
rte_be_to_cpu_16(cookie->vlan_tci_outer);
+               }
+       }
+
+       pd_hdr->ol_flag = rte_be_to_cpu_16(ol_flag);
+}
+
+/*
+ * Populate N_PER_LOOP descriptors with data from N_PER_LOOP single-segment 
mbufs.
+ * Note: The simple transmit path (zxdh_xmit_pkts_simple) is selected only when
+ * RTE_ETH_TX_OFFLOAD_MULTI_SEGS is disabled, so all packets handled here are
+ * guaranteed to be single-segment.
+ */
+static inline void
+tx_bunch(struct zxdh_virtqueue *vq, volatile struct zxdh_vring_packed_desc 
*txdp,
+               struct rte_mbuf **pkts, uint16_t start_id)
+{
+       uint16_t flags = vq->cached_flags;
+       int i;
+       for (i = 0; i < N_PER_LOOP; ++i, ++txdp, ++pkts) {
+               /* write data to descriptor */
+               txdp->addr = rte_mbuf_data_iova(*pkts);
+               txdp->len = (*pkts)->data_len;
+               txdp->id = start_id + i;
+               txdp->flags = flags;
+       }
+}
+
+/* Populate 1 descriptor with data from 1 single-segment mbuf */
+static inline void
+tx1(struct zxdh_virtqueue *vq, volatile struct zxdh_vring_packed_desc *txdp,
+               struct rte_mbuf *pkts, uint16_t id)
+{
+       uint16_t flags = vq->cached_flags;
+       txdp->addr = rte_mbuf_data_iova(pkts);
+       txdp->len = pkts->data_len;
+       txdp->id = id;
+       txdp->flags = flags;
+}
+
+static void submit_to_backend_simple(struct zxdh_virtqueue  *vq,
+                       struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+       struct zxdh_hw *hw = vq->hw;
+       struct rte_mbuf *m = NULL;
+       uint16_t id =  vq->vq_avail_idx;
+       struct zxdh_vring_packed_desc *txdp = &vq->vq_packed.ring.desc[id];
+       struct zxdh_vq_desc_extra *dxp = &vq->vq_descx[id];
+       int mainpart, leftover;
+       int i, j;
+
+       /*
+        * Process most of the packets in chunks of N pkts.  Any
+        * leftover packets will get processed one at a time.
+        */
+       mainpart = (nb_pkts & ~N_PER_LOOP_MASK);
+       leftover = (nb_pkts & N_PER_LOOP_MASK);
+
+       for (i = 0; i < mainpart; i += N_PER_LOOP) {
+               rte_prefetch0(dxp + i);
+               rte_prefetch0(tx_pkts + i);
+               for (j = 0; j < N_PER_LOOP; ++j) {
+                       m  = *(tx_pkts + i + j);
+                       pkt_padding(m, hw);
+                       (dxp + i + j)->cookie = (void *)m;
+               }
+               /* write data to descriptor */
+               tx_bunch(vq, txdp + i, tx_pkts + i, id + i);
+       }
+
+       if (leftover > 0) {
+               rte_prefetch0(dxp + mainpart);
+               rte_prefetch0(tx_pkts + mainpart);
+
+               for (i = 0; i < leftover; ++i) {
+                       m =  *(tx_pkts + mainpart + i);
+                       pkt_padding(m, hw);
+                       (dxp + mainpart + i)->cookie = m;
+                       tx1(vq, txdp + mainpart + i, *(tx_pkts + mainpart + i), 
id + mainpart + i);
+               }
+       }
+}
+
+uint16_t zxdh_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts, 
uint16_t nb_pkts)
+{
+       struct zxdh_virtnet_tx *txvq = tx_queue;
+       struct zxdh_virtqueue  *vq   = txq_get_vq(txvq);
+       uint16_t nb_tx = 0, nb_tx_left;
+
+       zxdh_xmit_fast_flush(vq);
+
+       nb_pkts = (uint16_t)RTE_MIN(nb_pkts, vq->vq_free_cnt);
+       if (unlikely(nb_pkts == 0)) {
+               txvq->stats.idle++;
+               return 0;
+       }
+
+       nb_tx_left = nb_pkts;
+       if ((vq->vq_avail_idx + nb_pkts) >= vq->vq_nentries) {
+               nb_tx = vq->vq_nentries - vq->vq_avail_idx;
+               nb_tx_left = nb_pkts - nb_tx;
+               submit_to_backend_simple(vq, tx_pkts, nb_tx);
+               vq->vq_avail_idx = 0;
+               vq->cached_flags ^= ZXDH_VRING_PACKED_DESC_F_AVAIL_USED;
+
+               vq->vq_free_cnt  -= nb_tx;
+               tx_pkts += nb_tx;
+       }
+       if (nb_tx_left) {
+               submit_to_backend_simple(vq, tx_pkts, nb_tx_left);
+               vq->vq_avail_idx  += nb_tx_left;
+               vq->vq_free_cnt  -= nb_tx_left;
+       }
+
+       zxdh_queue_notify(vq);
+       txvq->stats.packets += nb_pkts;
+       for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++)
+               zxdh_update_packet_stats(&txvq->stats, tx_pkts[nb_tx]);
+
+       return nb_pkts;
+}
diff --git a/drivers/net/zxdh/zxdh_rxtx.h b/drivers/net/zxdh/zxdh_rxtx.h
index dba9567414..783fb456de 100644
--- a/drivers/net/zxdh/zxdh_rxtx.h
+++ b/drivers/net/zxdh/zxdh_rxtx.h
@@ -56,18 +56,19 @@ struct __rte_cache_aligned zxdh_virtnet_rx {
 
 struct __rte_cache_aligned zxdh_virtnet_tx {
        struct zxdh_virtqueue         *vq;
-
-       rte_iova_t                zxdh_net_hdr_mem; /* hdr for each xmit packet 
*/
-       uint16_t                  queue_id;           /* DPDK queue index. */
-       uint16_t                  port_id;            /* Device port 
identifier. */
+       const struct rte_memzone *zxdh_net_hdr_mz;  /* memzone to populate hdr. 
*/
+       rte_iova_t               zxdh_net_hdr_mem; /* hdr for each xmit packet 
*/
        struct zxdh_virtnet_stats      stats;
        const struct rte_memzone *mz;                 /* mem zone to populate 
TX ring. */
-       const struct rte_memzone *zxdh_net_hdr_mz;  /* memzone to populate hdr. 
*/
+       uint64_t offloads;
+       uint16_t                  queue_id;           /* DPDK queue index. */
+       uint16_t                  port_id;            /* Device port 
identifier. */
 };
 
 uint16_t zxdh_xmit_pkts_packed(void *tx_queue, struct rte_mbuf **tx_pkts, 
uint16_t nb_pkts);
 uint16_t zxdh_xmit_pkts_prepare(void *tx_queue, struct rte_mbuf **tx_pkts, 
uint16_t nb_pkts);
 uint16_t zxdh_recv_pkts_packed(void *rx_queue, struct rte_mbuf **rx_pkts, 
uint16_t nb_pkts);
 uint16_t zxdh_recv_single_pkts(void *rx_queue, struct rte_mbuf **rcv_pkts, 
uint16_t nb_pkts);
+uint16_t zxdh_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts, 
uint16_t nb_pkts);
 
 #endif  /* ZXDH_RXTX_H */
-- 
2.27.0

Reply via email to