Introduce rawdev driver support for GDTC which
can help to connect two separate hosts with each other.
Signed-off-by: Yong Zhang <zhang.yong25@zte.com.cn>
---
.mailmap | 1 +
MAINTAINERS | 5 +
doc/guides/rawdevs/gdtc.rst | 35 ++++++
doc/guides/rawdevs/index.rst | 1 +
drivers/raw/gdtc/gdtc_rawdev.c | 195 +++++++++++++++++++++++++++++++++
drivers/raw/gdtc/gdtc_rawdev.h | 103 +++++++++++++++++
drivers/raw/gdtc/meson.build | 5 +
drivers/raw/meson.build | 1 +
8 files changed, 346 insertions(+)
create mode 100644 doc/guides/rawdevs/gdtc.rst
create mode 100644 drivers/raw/gdtc/gdtc_rawdev.c
create mode 100644 drivers/raw/gdtc/gdtc_rawdev.h
create mode 100644 drivers/raw/gdtc/meson.build
diff --git a/.mailmap b/.mailmap
index 4dbb8cf8a7..95ee83c6bf 100644
--- a/.mailmap
+++ b/.mailmap
@@ -1768,6 +1768,7 @@ Yu Wenjun <yuwenjun@cmss.chinamobile.com> <yuwenjun0x@163.com>
Yuying Zhang <yuying.zhang@intel.com>
Yu Zhang <zhangyu31@baidu.com>
Yvonne Yang <yvonnex.yang@intel.com>
+Yong Zhang <zhang.yong25@zte.com.cn>
Zalfresso-Jundzillo <marekx.zalfresso-jundzillo@intel.com>
Zbigniew Bodek <zbigniew.bodek@caviumnetworks.com>
Zengmo Gao <gaozengmo@jd.com>
diff --git a/MAINTAINERS b/MAINTAINERS
index f84ca3ea68..3c413f952b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1552,6 +1552,11 @@ M: Gagandeep Singh <g.singh@nxp.com>
F: drivers/raw/dpaa2_cmdif/
F: doc/guides/rawdevs/dpaa2_cmdif.rst
+ZTE GDTC
+M: Yong Zhang <zhang.yong25@zte.com.cn>
+F: drivers/raw/gdtc/
+F: doc/guides/rawdevs/gdtc.rst
+
Packet processing
-----------------
diff --git a/doc/guides/rawdevs/gdtc.rst b/doc/guides/rawdevs/gdtc.rst
new file mode 100644
index 0000000000..7e4e648c89
--- /dev/null
+++ b/doc/guides/rawdevs/gdtc.rst
@@ -0,0 +1,35 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+ Copyright 2024 ZTE Corporation
+
+GDTC Rawdev Driver
+======================
+
+The ``gdtc`` rawdev driver is an implementation of the rawdev API,
+that provides communication between two separate hosts.
+This is achieved via using the GDMA controller of Dinghai SoC,
+which can be configured through exposed MPF device.
+
+Device Setup
+-------------
+
+Using the GDTC PMD driver does not require the MPF device to bind
+additional user-space IO driver.
+
+Before performing actual data transmission, it is necessary to
+call ``rte_rawdev_queue_setup()`` to obtain an available queue ID.
+
+For data transfer, utilize the standard ``rte_rawdev_enqueue_buffers()`` API.
+The data transfer status can be queried via ``rte_rawdev_dequeue_buffers()``,
+which will return the number of successfully transferred data items.
+
+Initialization
+--------------
+
+The ``gdtc`` rawdev driver needs to work in IOVA PA mode.
+Consider using ``--iova-mode=pa`` in the EAL options.
+
+Platform Requirement
+~~~~~~~~~~~~~~~~~~~~
+
+This PMD is only supported on ZTE Neo Platforms:
+- Neo X510/X512
diff --git a/doc/guides/rawdevs/index.rst b/doc/guides/rawdevs/index.rst
index 8e07cf4d6c..2d8606d742 100644
--- a/doc/guides/rawdevs/index.rst
+++ b/doc/guides/rawdevs/index.rst
@@ -17,3 +17,4 @@ application through rawdev API.
dpaa2_cmdif
ifpga
ntb
+ gdtc
diff --git a/drivers/raw/gdtc/gdtc_rawdev.c b/drivers/raw/gdtc/gdtc_rawdev.c
new file mode 100644
index 0000000000..6f20ecdad6
--- /dev/null
+++ b/drivers/raw/gdtc/gdtc_rawdev.c
@@ -0,0 +1,195 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2024 ZTE Corporation
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <bus_pci_driver.h>
+#include <rte_atomic.h>
+#include <rte_common.h>
+#include <rte_dev.h>
+#include <rte_eal_paging.h>
+#include <rte_errno.h>
+#include <rte_lcore.h>
+#include <rte_log.h>
+#include <rte_malloc.h>
+#include <rte_memzone.h>
+#include <rte_pci.h>
+#include <rte_rawdev.h>
+#include <rte_rawdev_pmd.h>
+#include <rte_spinlock.h>
+#include <rte_branch_prediction.h>
+
+#include "gdtc_rawdev.h"
+
+/* Register offset */
+#define ZXDH_GDMA_BASE_OFFSET 0x100000
+
+#define ZXDH_GDMA_CHAN_SHIFT 0x80
+char zxdh_gdma_driver_name[] = "rawdev_zxdh_gdma";
+char dev_name[] = "zxdh_gdma";
+
+static inline struct zxdh_gdma_rawdev *
+zxdh_gdma_rawdev_get_priv(const struct rte_rawdev *rawdev)
+{
+ return rawdev->dev_private;
+}
+
+static const struct rte_rawdev_ops zxdh_gdma_rawdev_ops = {
+};
+
+static int
+zxdh_gdma_map_resource(struct rte_pci_device *dev)
+{
+ int fd = -1;
+ char devname[PATH_MAX];
+ void *mapaddr = NULL;
+ struct rte_pci_addr *loc;
+
+ loc = &dev->addr;
+ snprintf(devname, sizeof(devname), "%s/" PCI_PRI_FMT "/resource0",
+ rte_pci_get_sysfs_path(),
+ loc->domain, loc->bus, loc->devid,
+ loc->function);
+
+ fd = open(devname, O_RDWR);
+ if (fd < 0) {
+ ZXDH_PMD_LOG(ERR, "Cannot open %s: %s", devname, strerror(errno));
+ return -1;
+ }
+
+ /* Map the PCI memory resource of device */
+ mapaddr = rte_mem_map(NULL, (size_t)dev->mem_resource[0].len,
+ RTE_PROT_READ | RTE_PROT_WRITE,
+ RTE_MAP_SHARED, fd, 0);
+ if (mapaddr == NULL) {
+ ZXDH_PMD_LOG(ERR, "cannot map resource(%d, 0x%zx): %s (%p)",
+ fd, (size_t)dev->mem_resource[0].len,
+ rte_strerror(rte_errno), mapaddr);
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+ dev->mem_resource[0].addr = mapaddr;
+
+ return 0;
+}
+
+static void
+zxdh_gdma_unmap_resource(void *requested_addr, size_t size)
+{
+ if (requested_addr == NULL)
+ return;
+
+ /* Unmap the PCI memory resource of device */
+ if (rte_mem_unmap(requested_addr, size))
+ ZXDH_PMD_LOG(ERR, "cannot mem unmap(%p, %#zx): %s",
+ requested_addr, size, rte_strerror(rte_errno));
+ else
+ ZXDH_PMD_LOG(DEBUG, "PCI memory unmapped at %p", requested_addr);
+}
+
+static int
+zxdh_gdma_rawdev_probe(struct rte_pci_driver *pci_drv __rte_unused,
+ struct rte_pci_device *pci_dev)
+{
+ struct rte_rawdev *dev = NULL;
+ struct zxdh_gdma_rawdev *gdmadev = NULL;
+ struct zxdh_gdma_queue *queue = NULL;
+ uint8_t i = 0;
+ int ret;
+
+ if (pci_dev->mem_resource[0].phys_addr == 0) {
+ ZXDH_PMD_LOG(ERR, "PCI bar0 resource is invalid");
+ return -1;
+ }
+
+ ret = zxdh_gdma_map_resource(pci_dev);
+ if (ret != 0) {
+ ZXDH_PMD_LOG(ERR, "Failed to mmap pci device(%s)", pci_dev->name);
+ return -1;
+ }
+ ZXDH_PMD_LOG(INFO, "%s bar0 0x%"PRIx64" mapped at %p",
+ pci_dev->name, pci_dev->mem_resource[0].phys_addr,
+ pci_dev->mem_resource[0].addr);
+
+ dev = rte_rawdev_pmd_allocate(dev_name, sizeof(struct zxdh_gdma_rawdev), rte_socket_id());
+ if (dev == NULL) {
+ ZXDH_PMD_LOG(ERR, "Unable to allocate gdma rawdev");
+ goto err_out;
+ }
+ ZXDH_PMD_LOG(INFO, "Init %s on NUMA node %d, dev_id is %d",
+ dev_name, rte_socket_id(), dev->dev_id);
+
+ dev->dev_ops = &zxdh_gdma_rawdev_ops;
+ dev->device = &pci_dev->device;
+ dev->driver_name = zxdh_gdma_driver_name;
+ gdmadev = zxdh_gdma_rawdev_get_priv(dev);
+ gdmadev->device_state = ZXDH_GDMA_DEV_STOPPED;
+ gdmadev->rawdev = dev;
+ gdmadev->queue_num = ZXDH_GDMA_TOTAL_CHAN_NUM;
+ gdmadev->used_num = 0;
+ gdmadev->base_addr = (uintptr_t)pci_dev->mem_resource[0].addr + ZXDH_GDMA_BASE_OFFSET;
+
+ for (i = 0; i < ZXDH_GDMA_TOTAL_CHAN_NUM; i++) {
+ queue = &(gdmadev->vqs[i]);
+ queue->enable = 0;
+ queue->queue_size = ZXDH_GDMA_QUEUE_SIZE;
+ rte_spinlock_init(&(queue->enqueue_lock));
+ }
+
+ return 0;
+
+err_out:
+ zxdh_gdma_unmap_resource(pci_dev->mem_resource[0].addr,
+ (size_t)pci_dev->mem_resource[0].len);
+ return -1;
+}
+
+static int
+zxdh_gdma_rawdev_remove(struct rte_pci_device *pci_dev)
+{
+ struct rte_rawdev *dev = NULL;
+ int ret = 0;
+
+ dev = rte_rawdev_pmd_get_named_dev(dev_name);
+ if (dev == NULL)
+ return -EINVAL;
+
+ /* rte_rawdev_close is called by pmd_release */
+ ret = rte_rawdev_pmd_release(dev);
+ if (ret != 0) {
+ ZXDH_PMD_LOG(ERR, "Device cleanup failed");
+ return -1;
+ }
+
+ zxdh_gdma_unmap_resource(pci_dev->mem_resource[0].addr,
+ (size_t)pci_dev->mem_resource[0].len);
+
+ ZXDH_PMD_LOG(DEBUG, "rawdev %s remove done!", dev_name);
+
+ return ret;
+}
+
+static const struct rte_pci_id zxdh_gdma_rawdev_map[] = {
+ { RTE_PCI_DEVICE(ZXDH_GDMA_VENDORID, ZXDH_GDMA_DEVICEID) },
+ { .vendor_id = 0, /* sentinel */ },
+};
+
+static struct rte_pci_driver zxdh_gdma_rawdev_pmd = {
+ .id_table = zxdh_gdma_rawdev_map,
+ .drv_flags = 0,
+ .probe = zxdh_gdma_rawdev_probe,
+ .remove = zxdh_gdma_rawdev_remove,
+};
+
+RTE_PMD_REGISTER_PCI(zxdh_gdma_rawdev_pci_driver, zxdh_gdma_rawdev_pmd);
+RTE_PMD_REGISTER_PCI_TABLE(zxdh_gdma_rawdev_pci_driver, zxdh_gdma_rawdev_map);
+RTE_LOG_REGISTER_DEFAULT(zxdh_gdma_rawdev_logtype, NOTICE);
diff --git a/drivers/raw/gdtc/gdtc_rawdev.h b/drivers/raw/gdtc/gdtc_rawdev.h
new file mode 100644
index 0000000000..9f943c49c6
--- /dev/null
+++ b/drivers/raw/gdtc/gdtc_rawdev.h
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2024 ZTE Corporation
+ */
+
+#ifndef __GDTC_RAWDEV_H__
+#define __GDTC_RAWDEV_H__
+
+#include <stdint.h>
+#include <rte_log.h>
+#include <rte_common.h>
+#include <generic/rte_spinlock.h>
+
+extern int zxdh_gdma_rawdev_logtype;
+#define RTE_LOGTYPE_ZXDH_GDMA zxdh_gdma_rawdev_logtype
+
+#define ZXDH_PMD_LOG(level, ...) \
+ RTE_LOG_LINE_PREFIX(level, ZXDH_GDMA, \
+ "%s() line %u: ", __func__ RTE_LOG_COMMA __LINE__, __VA_ARGS__)
+
+#define ZXDH_GDMA_VENDORID 0x1cf2
+#define ZXDH_GDMA_DEVICEID 0x8044
+
+#define ZXDH_GDMA_TOTAL_CHAN_NUM 58
+#define ZXDH_GDMA_QUEUE_SIZE 16384
+#define ZXDH_GDMA_RING_SIZE 32768
+
+enum zxdh_gdma_device_state {
+ ZXDH_GDMA_DEV_RUNNING,
+ ZXDH_GDMA_DEV_STOPPED
+};
+
+struct zxdh_gdma_buff_desc {
+ uint32_t SrcAddr_L;
+ uint32_t DstAddr_L;
+ uint32_t Xpara;
+ uint32_t ZY_para;
+ uint32_t ZY_SrcStep;
+ uint32_t ZY_DstStep;
+ uint32_t ExtAddr;
+ uint32_t LLI_Addr_L;
+ uint32_t LLI_Addr_H;
+ uint32_t ChCont;
+ uint32_t LLI_User;
+ uint32_t ErrAddr;
+ uint32_t Control;
+ uint32_t SrcAddr_H;
+ uint32_t DstAddr_H;
+ uint32_t Reserved;
+};
+
+struct zxdh_gdma_job {
+ uint64_t src;
+ uint64_t dest;
+ uint32_t len;
+ uint32_t flags;
+ uint64_t cnxt;
+ uint16_t status;
+ uint16_t vq_id;
+ void *usr_elem;
+ uint8_t ep_id;
+ uint8_t pf_id;
+ uint16_t vf_id;
+};
+
+struct zxdh_gdma_queue {
+ uint8_t enable;
+ uint8_t is_txq;
+ uint16_t vq_id;
+ uint16_t queue_size;
+ /* 0:GDMA needs to be configured through the APB interface */
+ uint16_t flag;
+ uint32_t user;
+ uint16_t tc_cnt;
+ rte_spinlock_t enqueue_lock;
+ struct {
+ uint16_t avail_idx;
+ uint16_t last_avail_idx;
+ rte_iova_t ring_mem;
+ const struct rte_memzone *ring_mz;
+ struct zxdh_gdma_buff_desc *desc;
+ } ring;
+ struct {
+ uint16_t free_cnt;
+ uint16_t deq_cnt;
+ uint16_t pend_cnt;
+ uint16_t enq_idx;
+ uint16_t deq_idx;
+ uint16_t used_idx;
+ struct zxdh_gdma_job **job;
+ } sw_ring;
+};
+
+struct zxdh_gdma_rawdev {
+ struct rte_device *device;
+ struct rte_rawdev *rawdev;
+ uintptr_t base_addr;
+ uint8_t queue_num; /* total queue num */
+ uint8_t used_num; /* used queue num */
+ enum zxdh_gdma_device_state device_state;
+ struct zxdh_gdma_queue vqs[ZXDH_GDMA_TOTAL_CHAN_NUM];
+};
+
+#endif /* __GDTC_RAWDEV_H__ */
diff --git a/drivers/raw/gdtc/meson.build b/drivers/raw/gdtc/meson.build
new file mode 100644
index 0000000000..3e748ca58d
--- /dev/null
+++ b/drivers/raw/gdtc/meson.build
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2024 ZTE Corporation
+
+deps += ['rawdev', 'kvargs', 'mbuf', 'bus_pci']
+sources = files('gdtc_rawdev.c')
diff --git a/drivers/raw/meson.build b/drivers/raw/meson.build
index 54221643d5..9cc2cba9e1 100644
--- a/drivers/raw/meson.build
+++ b/drivers/raw/meson.build
@@ -13,5 +13,6 @@ drivers = [
'ifpga',
'ntb',
'skeleton',
+ 'gdtc',
]
std_deps = ['rawdev']
--
2.43.0