dev start/stop implementations, start/stop the rx/tx queues.<br /> <br />Signed-off-by: Junlong Wang <wang.junlong1@zte.com.cn> <br />---<br /> doc/guides/nics/features/zxdh.ini |  2 +<br /> doc/guides/nics/zxdh.rst          |  2 +<br /> drivers/net/zxdh/zxdh_ethdev.c    | 71 ++++++++++++++++++++++++<br /> drivers/net/zxdh/zxdh_pci.c       | 21 +++++++<br /> drivers/net/zxdh/zxdh_pci.h       |  1 +<br /> drivers/net/zxdh/zxdh_queue.c     | 91 +++++++++++++++++++++++++++++++<br /> drivers/net/zxdh/zxdh_queue.h     | 69 +++++++++++++++++++++++<br /> drivers/net/zxdh/zxdh_rxtx.h      | 14 ++---<br /> 8 files changed, 263 insertions(+), 8 deletions(-)<br /> <br />diff --git a/doc/guides/nics/features/zxdh.ini b/doc/guides/nics/features/zxdh.ini<br />index 05c8091ed7..7b72be5f25 100644<br />--- a/doc/guides/nics/features/zxdh.ini<br />+++ b/doc/guides/nics/features/zxdh.ini<br />@@ -7,3 +7,5 @@<br /> Linux                = Y<br /> x86-64               = Y<br /> ARMv8                = Y<br />+SR-IOV               = Y<br />+Multiprocess aware   = Y<br />diff --git a/doc/guides/nics/zxdh.rst b/doc/guides/nics/zxdh.rst<br />index 2144753d75..eb970a888f 100644<br />--- a/doc/guides/nics/zxdh.rst<br />+++ b/doc/guides/nics/zxdh.rst<br />@@ -18,6 +18,8 @@ Features<br /> Features of the ZXDH PMD are:<br />  <br /> - Multi arch support: x86_64, ARMv8.<br />+- Multiple queues for TX and RX<br />+- SR-IOV VF<br />  <br />  <br /> Driver compilation and testing<br />diff --git a/drivers/net/zxdh/zxdh_ethdev.c b/drivers/net/zxdh/zxdh_ethdev.c<br />index 521d7ed433..6e603b967e 100644<br />--- a/drivers/net/zxdh/zxdh_ethdev.c<br />+++ b/drivers/net/zxdh/zxdh_ethdev.c<br />@@ -899,12 +899,40 @@ zxdh_tables_uninit(struct rte_eth_dev *dev)<br />     return ret;<br /> }<br />  <br />+static int<br />+zxdh_dev_stop(struct rte_eth_dev *dev)<br />+{<br />+    uint16_t i;<br />+    int ret;<br />+<br />+    if (dev->data->dev_started == 0)<br />+        return 0;<br />+<br />+    ret = zxdh_intr_disable(dev);<br />+    if (ret) {<br />+        PMD_DRV_LOG(ERR, "intr disable failed");<br />+        return ret;<br />+    }<br />+    for (i = 0; i < dev->data->nb_rx_queues; i++)<br />+        dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;<br />+    for (i = 0; i < dev->data->nb_tx_queues; i++)<br />+        dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;<br />+<br />+    return 0;<br />+}<br />+<br /> static int<br /> zxdh_dev_close(struct rte_eth_dev *dev)<br /> {<br />     struct zxdh_hw *hw = dev->data->dev_private;<br />     int ret = 0;<br />  <br />+    ret = zxdh_dev_stop(dev);<br />+    if (ret != 0) {<br />+        PMD_DRV_LOG(ERR, " stop port %s failed.", dev->device->name);<br />+        return -1;<br />+    }<br />+<br />     ret = zxdh_tables_uninit(dev);<br />     if (ret != 0) {<br />         PMD_DRV_LOG(ERR, "%s :tables uninit %s failed ", __func__, dev->device->name);<br />@@ -928,9 +956,52 @@ zxdh_dev_close(struct rte_eth_dev *dev)<br />     return ret;<br /> }<br />  <br />+static int<br />+zxdh_dev_start(struct rte_eth_dev *dev)<br />+{<br />+    struct zxdh_hw *hw = dev->data->dev_private;<br />+    struct zxdh_virtqueue *vq;<br />+    int32_t ret;<br />+    uint16_t logic_qidx;<br />+    uint16_t i;<br />+<br />+    for (i = 0; i < dev->data->nb_rx_queues; i++) {<br />+        logic_qidx = 2 * i + ZXDH_RQ_QUEUE_IDX;<br />+        ret = zxdh_dev_rx_queue_setup_finish(dev, logic_qidx);<br />+        if (ret < 0)<br />+            return ret;<br />+    }<br />+    ret = zxdh_intr_enable(dev);<br />+    if (ret) {<br />+        PMD_DRV_LOG(ERR, "interrupt enable failed");<br />+        return -EINVAL;<br />+    }<br />+<br />+    for (i = 0; i < dev->data->nb_rx_queues; i++) {<br />+        logic_qidx = 2 * i + ZXDH_RQ_QUEUE_IDX;<br />+        vq = hw->vqs[logic_qidx];<br />+        /* Flush the old packets */<br />+        zxdh_queue_rxvq_flush(vq);<br />+        zxdh_queue_notify(vq);<br />+    }<br />+    for (i = 0; i < dev->data->nb_tx_queues; i++) {<br />+        logic_qidx = 2 * i + ZXDH_TQ_QUEUE_IDX;<br />+        vq = hw->vqs[logic_qidx];<br />+        zxdh_queue_notify(vq);<br />+    }<br />+    for (i = 0; i < dev->data->nb_rx_queues; i++)<br />+        dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;<br />+    for (i = 0; i < dev->data->nb_tx_queues; i++)<br />+        dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;<br />+<br />+    return 0;<br />+}<br />+<br /> /* dev_ops for zxdh, bare necessities for basic operation */<br /> static const struct eth_dev_ops zxdh_eth_dev_ops = {<br />     .dev_configure             = zxdh_dev_configure,<br />+    .dev_start                 = zxdh_dev_start,<br />+    .dev_stop                 = zxdh_dev_stop,<br />     .dev_close                 = zxdh_dev_close,<br />     .dev_infos_get             = zxdh_dev_infos_get,<br />     .rx_queue_setup             = zxdh_dev_rx_queue_setup,<br />diff --git a/drivers/net/zxdh/zxdh_pci.c b/drivers/net/zxdh/zxdh_pci.c<br />index 250e67d560..6b2c4482b2 100644<br />--- a/drivers/net/zxdh/zxdh_pci.c<br />+++ b/drivers/net/zxdh/zxdh_pci.c<br />@@ -202,6 +202,26 @@ zxdh_del_queue(struct zxdh_hw *hw, struct zxdh_virtqueue *vq)<br />     rte_write16(0, &hw->common_cfg->queue_enable);<br /> }<br />  <br />+static void<br />+zxdh_notify_queue(struct zxdh_hw *hw, struct zxdh_virtqueue *vq)<br />+{<br />+    uint32_t notify_data = 0;<br />+<br />+    if (!zxdh_pci_with_feature(hw, ZXDH_F_NOTIFICATION_DATA)) {<br />+        rte_write16(vq->vq_queue_index, vq->notify_addr);<br />+        return;<br />+    }<br />+<br />+    notify_data = ((uint32_t)vq->vq_avail_idx << 16) | vq->vq_queue_index;<br />+    if (zxdh_pci_with_feature(hw, ZXDH_F_RING_PACKED) && <br />+            (vq->vq_packed.cached_flags & ZXDH_VRING_PACKED_DESC_F_AVAIL))<br />+        notify_data |= RTE_BIT32(31);<br />+<br />+    PMD_DRV_LOG(DEBUG, "queue:%d notify_data 0x%x notify_addr 0x%p",<br />+                 vq->vq_queue_index, notify_data, vq->notify_addr);<br />+    rte_write32(notify_data, vq->notify_addr);<br />+}<br />+<br /> const struct zxdh_pci_ops zxdh_dev_pci_ops = {<br />     .read_dev_cfg   = zxdh_read_dev_config,<br />     .write_dev_cfg  = zxdh_write_dev_config,<br />@@ -216,6 +236,7 @@ const struct zxdh_pci_ops zxdh_dev_pci_ops = {<br />     .set_queue_num  = zxdh_set_queue_num,<br />     .setup_queue    = zxdh_setup_queue,<br />     .del_queue      = zxdh_del_queue,<br />+    .notify_queue   = zxdh_notify_queue,<br /> };<br />  <br /> uint8_t<br />diff --git a/drivers/net/zxdh/zxdh_pci.h b/drivers/net/zxdh/zxdh_pci.h<br />index e3f13cb17d..5c5f72b90e 100644<br />--- a/drivers/net/zxdh/zxdh_pci.h<br />+++ b/drivers/net/zxdh/zxdh_pci.h<br />@@ -144,6 +144,7 @@ struct zxdh_pci_ops {<br />  <br />     int32_t  (*setup_queue)(struct zxdh_hw *hw, struct zxdh_virtqueue *vq);<br />     void     (*del_queue)(struct zxdh_hw *hw, struct zxdh_virtqueue *vq);<br />+    void     (*notify_queue)(struct zxdh_hw *hw, struct zxdh_virtqueue *vq);<br /> };<br />  <br /> struct zxdh_hw_internal {<br />diff --git a/drivers/net/zxdh/zxdh_queue.c b/drivers/net/zxdh/zxdh_queue.c<br />index af21f046ad..8c8f2605f6 100644<br />--- a/drivers/net/zxdh/zxdh_queue.c<br />+++ b/drivers/net/zxdh/zxdh_queue.c<br />@@ -274,3 +274,94 @@ zxdh_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)<br />     zxdh_queue_disable_intr(vq);<br />     return 0;<br /> }<br />+<br />+int32_t zxdh_enqueue_recv_refill_packed(struct zxdh_virtqueue *vq,<br />+            struct rte_mbuf **cookie, uint16_t num)<br />+{<br />+    struct zxdh_vring_packed_desc *start_dp = vq->vq_packed.ring.desc;<br />+    struct zxdh_hw *hw = vq->hw;<br />+    struct zxdh_vq_desc_extra *dxp;<br />+    uint16_t flags = vq->vq_packed.cached_flags;<br />+    int32_t i;<br />+    uint16_t idx;<br />+<br />+    for (i = 0; i < num; i++) {<br />+        idx = vq->vq_avail_idx;<br />+        dxp = &vq->vq_descx[idx];<br />+        dxp->cookie = (void *)cookie[i];<br />+        dxp->ndescs = 1;<br />+        /* rx pkt fill in data_off */<br />+        start_dp[idx].addr = rte_mbuf_iova_get(cookie[i]) + RTE_PKTMBUF_HEADROOM;<br />+        start_dp[idx].len = cookie[i]->buf_len - RTE_PKTMBUF_HEADROOM;<br />+        vq->vq_desc_head_idx = dxp->next;<br />+        if (vq->vq_desc_head_idx == ZXDH_VQ_RING_DESC_CHAIN_END)<br />+            vq->vq_desc_tail_idx = vq->vq_desc_head_idx;<br />+        zxdh_queue_store_flags_packed(&start_dp[idx], flags, hw->weak_barriers);<br />+        if (++vq->vq_avail_idx >= vq->vq_nentries) {<br />+            vq->vq_avail_idx -= vq->vq_nentries;<br />+            vq->vq_packed.cached_flags ^= ZXDH_VRING_PACKED_DESC_F_AVAIL_USED;<br />+            flags = vq->vq_packed.cached_flags;<br />+        }<br />+    }<br />+    vq->vq_free_cnt = (uint16_t)(vq->vq_free_cnt - num);<br />+    return 0;<br />+}<br />+<br />+int32_t zxdh_dev_rx_queue_setup_finish(struct rte_eth_dev *dev, uint16_t logic_qidx)<br />+{<br />+    struct zxdh_hw *hw = dev->data->dev_private;<br />+    struct zxdh_virtqueue *vq = hw->vqs[logic_qidx];<br />+    struct zxdh_virtnet_rx *rxvq = &vq->rxq;<br />+    uint16_t desc_idx;<br />+    int32_t error = 0;<br />+<br />+    /* Allocate blank mbufs for the each rx descriptor */<br />+    memset(&rxvq->fake_mbuf, 0, sizeof(rxvq->fake_mbuf));<br />+    for (desc_idx = 0; desc_idx < ZXDH_MBUF_BURST_SZ; desc_idx++)<br />+        vq->sw_ring[vq->vq_nentries + desc_idx] = &rxvq->fake_mbuf;<br />+<br />+    while (!zxdh_queue_full(vq)) {<br />+        uint16_t free_cnt = vq->vq_free_cnt;<br />+<br />+        free_cnt = RTE_MIN(ZXDH_MBUF_BURST_SZ, free_cnt);<br />+        struct rte_mbuf *new_pkts[free_cnt];<br />+<br />+        if (likely(rte_pktmbuf_alloc_bulk(rxvq->mpool, new_pkts, free_cnt) == 0)) {<br />+            error = zxdh_enqueue_recv_refill_packed(vq, new_pkts, free_cnt);<br />+            if (unlikely(error)) {<br />+                int32_t i;<br />+                for (i = 0; i < free_cnt; i++)<br />+                    rte_pktmbuf_free(new_pkts[i]);<br />+            }<br />+        } else {<br />+            PMD_DRV_LOG(ERR, "port %d rxq %d allocated bufs from %s failed",<br />+                hw->port_id, logic_qidx, rxvq->mpool->name);<br />+            break;<br />+        }<br />+    }<br />+    return 0;<br />+}<br />+<br />+void zxdh_queue_rxvq_flush(struct zxdh_virtqueue *vq)<br />+{<br />+    struct zxdh_vq_desc_extra *dxp = NULL;<br />+    uint16_t i = 0;<br />+    struct zxdh_vring_packed_desc *descs = vq->vq_packed.ring.desc;<br />+    int32_t cnt = 0;<br />+<br />+    i = vq->vq_used_cons_idx;<br />+    while (zxdh_desc_used(&descs[i], vq) && cnt++ < vq->vq_nentries) {<br />+        dxp = &vq->vq_descx[descs[i].id];<br />+        if (dxp->cookie != NULL) {<br />+            rte_pktmbuf_free(dxp->cookie);<br />+            dxp->cookie = NULL;<br />+        }<br />+        vq->vq_free_cnt++;<br />+        vq->vq_used_cons_idx++;<br />+        if (vq->vq_used_cons_idx >= vq->vq_nentries) {<br />+            vq->vq_used_cons_idx -= vq->vq_nentries;<br />+            vq->vq_packed.used_wrap_counter ^= 1;<br />+        }<br />+        i = vq->vq_used_cons_idx;<br />+    }<br />+}<br />diff --git a/drivers/net/zxdh/zxdh_queue.h b/drivers/net/zxdh/zxdh_queue.h<br />index 2f602d894f..6513aec3f0 100644<br />--- a/drivers/net/zxdh/zxdh_queue.h<br />+++ b/drivers/net/zxdh/zxdh_queue.h<br />@@ -25,6 +25,11 @@ enum { ZXDH_VTNET_RQ = 0, ZXDH_VTNET_TQ = 1 };<br /> #define ZXDH_VRING_DESC_F_WRITE           2<br /> /* This flag means the descriptor was made available by the driver */<br /> #define ZXDH_VRING_PACKED_DESC_F_AVAIL   (1 << (7))<br />+#define ZXDH_VRING_PACKED_DESC_F_USED    (1 << (15))<br />+<br />+/* Frequently used combinations */<br />+#define ZXDH_VRING_PACKED_DESC_F_AVAIL_USED \<br />+        (ZXDH_VRING_PACKED_DESC_F_AVAIL | ZXDH_VRING_PACKED_DESC_F_USED)<br />  <br /> #define ZXDH_RING_EVENT_FLAGS_ENABLE      0x0<br /> #define ZXDH_RING_EVENT_FLAGS_DISABLE     0x1<br />@@ -33,6 +38,9 @@ enum { ZXDH_VTNET_RQ = 0, ZXDH_VTNET_TQ = 1 };<br /> #define ZXDH_VQ_RING_DESC_CHAIN_END       32768<br /> #define ZXDH_QUEUE_DEPTH                  1024<br />  <br />+#define ZXDH_RQ_QUEUE_IDX                 0<br />+#define ZXDH_TQ_QUEUE_IDX                 1<br />+<br /> /*<br />  * ring descriptors: 16 bytes.<br />  * These can chain together via "next".<br />@@ -290,6 +298,63 @@ zxdh_mb(uint8_t weak_barriers)<br />         rte_mb();<br /> }<br />  <br />+static inline int32_t<br />+zxdh_queue_full(const struct zxdh_virtqueue *vq)<br />+{<br />+    return (vq->vq_free_cnt == 0);<br />+}<br />+<br />+static inline void<br />+zxdh_queue_store_flags_packed(struct zxdh_vring_packed_desc *dp,<br />+        uint16_t flags, uint8_t weak_barriers)<br />+    {<br />+    if (weak_barriers) {<br />+    #ifdef RTE_ARCH_X86_64<br />+        rte_io_wmb();<br />+        dp->flags = flags;<br />+    #else<br />+        rte_atomic_store_explicit(&dp->flags, flags, rte_memory_order_release);<br />+    #endif<br />+    } else {<br />+        rte_io_wmb();<br />+        dp->flags = flags;<br />+    }<br />+}<br />+<br />+static inline uint16_t<br />+zxdh_queue_fetch_flags_packed(struct zxdh_vring_packed_desc *dp,<br />+        uint8_t weak_barriers)<br />+    {<br />+    uint16_t flags;<br />+    if (weak_barriers) {<br />+    #ifdef RTE_ARCH_X86_64<br />+        flags = dp->flags;<br />+        rte_io_rmb();<br />+    #else<br />+        flags = rte_atomic_load_explicit(&dp->flags, rte_memory_order_acquire);<br />+    #endif<br />+    } else {<br />+        flags = dp->flags;<br />+        rte_io_rmb();<br />+    }<br />+<br />+    return flags;<br />+}<br />+<br />+static inline int32_t<br />+zxdh_desc_used(struct zxdh_vring_packed_desc *desc, struct zxdh_virtqueue *vq)<br />+{<br />+    uint16_t flags = zxdh_queue_fetch_flags_packed(desc, vq->hw->weak_barriers);<br />+    uint16_t used = !!(flags & ZXDH_VRING_PACKED_DESC_F_USED);<br />+    uint16_t avail = !!(flags & ZXDH_VRING_PACKED_DESC_F_AVAIL);<br />+    return avail == used && used == vq->vq_packed.used_wrap_counter;<br />+}<br />+<br />+static inline void zxdh_queue_notify(struct zxdh_virtqueue *vq)<br />+{<br />+    ZXDH_VTPCI_OPS(vq->hw)->notify_queue(vq->hw, vq);<br />+}<br />+<br /> struct rte_mbuf *zxdh_queue_detach_unused(struct zxdh_virtqueue *vq);<br /> int32_t zxdh_free_queues(struct rte_eth_dev *dev);<br /> int32_t zxdh_get_queue_type(uint16_t vtpci_queue_idx);<br />@@ -306,5 +371,9 @@ int32_t zxdh_dev_rx_queue_setup(struct rte_eth_dev *dev,<br />             struct rte_mempool *mp);<br /> int32_t zxdh_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id);<br /> int32_t zxdh_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id);<br />+int32_t zxdh_dev_rx_queue_setup_finish(struct rte_eth_dev *dev, uint16_t logic_qidx);<br />+void zxdh_queue_rxvq_flush(struct zxdh_virtqueue *vq);<br />+int32_t zxdh_enqueue_recv_refill_packed(struct zxdh_virtqueue *vq,<br />+            struct rte_mbuf **cookie, uint16_t num);<br />  <br /> #endif /* ZXDH_QUEUE_H */<br />diff --git a/drivers/net/zxdh/zxdh_rxtx.h b/drivers/net/zxdh/zxdh_rxtx.h<br />index de9353b223..8c7f734805 100644<br />--- a/drivers/net/zxdh/zxdh_rxtx.h<br />+++ b/drivers/net/zxdh/zxdh_rxtx.h<br />@@ -20,21 +20,19 @@ struct zxdh_virtnet_stats {<br />     uint64_t size_bins[8];<br /> };<br />  <br />-struct zxdh_virtnet_rx {<br />+struct __rte_cache_aligned zxdh_virtnet_rx {<br />     struct zxdh_virtqueue         *vq;<br />-<br />-    /* dummy mbuf, for wraparound when processing RX ring. */<br />-    struct rte_mbuf           fake_mbuf;<br />-<br />     uint64_t                  mbuf_initializer; /* value to init mbufs. */<br />     struct rte_mempool       *mpool;            /* mempool for mbuf allocation */<br />     uint16_t                  queue_id;         /* DPDK queue index. */<br />     uint16_t                  port_id;          /* Device port identifier. */<br />     struct zxdh_virtnet_stats      stats;<br />     const struct rte_memzone *mz;               /* mem zone to populate RX ring. */<br />-} __rte_packed;<br />+    /* dummy mbuf, for wraparound when processing RX ring. */<br />+    struct rte_mbuf           fake_mbuf;<br />+};<br />  <br />-struct zxdh_virtnet_tx {<br />+struct __rte_cache_aligned zxdh_virtnet_tx {<br />     struct zxdh_virtqueue         *vq;<br />     const struct rte_memzone *zxdh_net_hdr_mz;  /* memzone to populate hdr. */<br />     rte_iova_t                zxdh_net_hdr_mem; /* hdr for each xmit packet */<br />@@ -42,6 +40,6 @@ struct zxdh_virtnet_tx {<br />     uint16_t                  port_id;            /* Device port identifier. */<br />     struct zxdh_virtnet_stats      stats;<br />     const struct rte_memzone *mz;                 /* mem zone to populate TX ring. */<br />-} __rte_packed;<br />+};<br />  <br /> #endif  /* ZXDH_RXTX_H */<br />--  <br />2.27.0<br />