From: Kyo Liu <kyo.liu@nebula-matrix.com>
To: kyo.liu@nebula-matrix.com, dev@dpdk.org
Cc: Dimon Zhao <dimon.zhao@nebula-matrix.com>,
Leon Yu <leon.yu@nebula-matrix.com>,
Sam Chen <sam.chen@nebula-matrix.com>
Subject: [PATCH v1 11/17] net/nbl: add nbl coexistence mode for nbl
Date: Thu, 12 Jun 2025 08:58:32 +0000 [thread overview]
Message-ID: <20250612085840.729830-12-kyo.liu@nebula-matrix.com> (raw)
In-Reply-To: <20250612085840.729830-1-kyo.liu@nebula-matrix.com>
NBL device support coexistence mode
Signed-off-by: Kyo Liu <kyo.liu@nebula-matrix.com>
---
drivers/net/nbl/nbl_common/nbl_userdev.c | 744 +++++++++++++++++-
drivers/net/nbl/nbl_common/nbl_userdev.h | 11 +
drivers/net/nbl/nbl_core.c | 3 +-
drivers/net/nbl/nbl_core.h | 1 -
drivers/net/nbl/nbl_ethdev.c | 6 +
drivers/net/nbl/nbl_hw/nbl_channel.c | 185 ++++-
drivers/net/nbl/nbl_hw/nbl_channel.h | 11 +
.../nbl_hw_leonis/nbl_phy_leonis_snic.c | 2 +-
drivers/net/nbl/nbl_include/nbl_def_common.h | 65 +-
drivers/net/nbl/nbl_include/nbl_include.h | 2 +
10 files changed, 1019 insertions(+), 11 deletions(-)
diff --git a/drivers/net/nbl/nbl_common/nbl_userdev.c b/drivers/net/nbl/nbl_common/nbl_userdev.c
index 87b943ccd7..26643c862b 100644
--- a/drivers/net/nbl/nbl_common/nbl_userdev.c
+++ b/drivers/net/nbl/nbl_common/nbl_userdev.c
@@ -3,15 +3,720 @@
*/
#include "nbl_userdev.h"
+#include <rte_vfio.h>
-int nbl_pci_map_device(struct nbl_adapter *adapter)
+#define NBL_USERDEV_EVENT_CLB_NAME "nbl_userspace_mem_event_clb"
+#define NBL_USERDEV_BAR0_SIZE 65536
+#define NBL_USERDEV_DMA_LIMIT 0xFFFFFFFFFFFF
+
+/* Size of the buffer to receive kernel messages */
+#define NBL_NL_BUF_SIZE (32 * 1024)
+/* Send buffer size for the Netlink socket */
+#define NBL_SEND_BUF_SIZE 32768
+/* Receive buffer size for the Netlink socket */
+#define NBL_RECV_BUF_SIZE 32768
+
+struct nbl_userdev_map_record {
+ TAILQ_ENTRY(nbl_userdev_map_record) next;
+ u64 vaddr;
+ u64 iova;
+ u64 len;
+};
+
+static int nbl_default_container = -1;
+static int nbl_group_count;
+
+TAILQ_HEAD(nbl_adapter_list_head, nbl_adapter);
+static struct nbl_adapter_list_head nbl_adapter_list =
+ TAILQ_HEAD_INITIALIZER(nbl_adapter_list);
+
+TAILQ_HEAD(nbl_userdev_map_record_head, nbl_userdev_map_record);
+static struct nbl_userdev_map_record_head nbl_map_list =
+ TAILQ_HEAD_INITIALIZER(nbl_map_list);
+
+static int
+nbl_userdev_dma_mem_map(int devfd, uint64_t vaddr, uint64_t iova, uint64_t len)
{
- struct rte_pci_device *pci_dev = adapter->pci_dev;
+ struct nbl_dev_user_dma_map dma_map;
int ret = 0;
- ret = rte_pci_map_device(pci_dev);
+ memset(&dma_map, 0, sizeof(dma_map));
+ dma_map.argsz = sizeof(struct nbl_dev_user_dma_map);
+ dma_map.vaddr = vaddr;
+ dma_map.size = len;
+ dma_map.iova = iova;
+ dma_map.flags = NBL_DEV_USER_DMA_MAP_FLAG_READ |
+ NBL_DEV_USER_DMA_MAP_FLAG_WRITE;
+
+ ret = ioctl(devfd, NBL_DEV_USER_MAP_DMA, &dma_map);
+ if (ret) {
+ /**
+ * In case the mapping was already done EEXIST will be
+ * returned from kernel.
+ */
+ if (errno == EEXIST) {
+ NBL_LOG(ERR,
+ "nbl container Memory segment is already mapped,skipping");
+ ret = 0;
+ } else {
+ NBL_LOG(ERR,
+ "nbl container cannot set up DMA remapping,error %i (%s), ret %d",
+ errno, strerror(errno), ret);
+ }
+ }
+
+ return ret;
+}
+
+static int
+nbl_vfio_dma_mem_map(int vfio_container_fd, uint64_t vaddr, uint64_t len, int do_map)
+{
+ struct vfio_iommu_type1_dma_map dma_map;
+ struct vfio_iommu_type1_dma_unmap dma_unmap;
+ int ret;
+
+ if (do_map != 0) {
+ memset(&dma_map, 0, sizeof(dma_map));
+ dma_map.argsz = sizeof(struct vfio_iommu_type1_dma_map);
+ dma_map.vaddr = vaddr;
+ dma_map.size = len;
+ dma_map.iova = vaddr;
+ dma_map.flags = VFIO_DMA_MAP_FLAG_READ |
+ VFIO_DMA_MAP_FLAG_WRITE;
+
+ ret = ioctl(vfio_container_fd, VFIO_IOMMU_MAP_DMA, &dma_map);
+ if (ret) {
+ /**
+ * In case the mapping was already done EEXIST will be
+ * returned from kernel.
+ */
+ if (errno == EEXIST) {
+ NBL_LOG(ERR,
+ "Memory segment is already mapped, skipping");
+ } else {
+ NBL_LOG(ERR,
+ "cannot set up DMA remapping,error %i (%s)",
+ errno, strerror(errno));
+ return -1;
+ }
+ }
+ } else {
+ memset(&dma_unmap, 0, sizeof(dma_unmap));
+ dma_unmap.argsz = sizeof(struct vfio_iommu_type1_dma_unmap);
+ dma_unmap.size = len;
+ dma_unmap.iova = vaddr;
+
+ ret = ioctl(vfio_container_fd, VFIO_IOMMU_UNMAP_DMA, &dma_unmap);
+ if (ret) {
+ NBL_LOG(ERR, "cannot clear DMA remapping, error %i (%s)",
+ errno, strerror(errno));
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+vfio_map_contig(const struct rte_memseg_list *msl, const struct rte_memseg *ms,
+ size_t len, void *arg)
+{
+ struct nbl_userdev_map_record *record;
+ int *vfio_container_fd = arg;
+ int ret;
+
+ if (msl->external)
+ return 0;
+
+ ret = nbl_vfio_dma_mem_map(*vfio_container_fd, ms->addr_64, len, 1);
+ if (ret)
+ return ret;
+
+ record = malloc(sizeof(*record));
+ if (!record)
+ return -ENOMEM;
+
+ record->vaddr = ms->addr_64;
+ record->iova = ms->iova;
+ record->len = len;
+ TAILQ_INSERT_TAIL(&nbl_map_list, record, next);
+
+ return 0;
+}
+
+static int
+vfio_map(const struct rte_memseg_list *msl, const struct rte_memseg *ms, void *arg)
+{
+ struct nbl_userdev_map_record *record;
+ int *vfio_container_fd = arg;
+ int ret;
+
+ /* skip external memory that isn't a heap */
+ if (msl->external && !msl->heap)
+ return 0;
+
+ /* skip any segments with invalid IOVA addresses */
+ if (ms->iova == RTE_BAD_IOVA)
+ return 0;
+
+ /* if IOVA mode is VA, we've already mapped the internal segments */
+ if (!msl->external && rte_eal_iova_mode() == RTE_IOVA_VA)
+ return 0;
+
+ ret = nbl_vfio_dma_mem_map(*vfio_container_fd, ms->addr_64, ms->len, 1);
if (ret)
- NBL_LOG(ERR, "device %s uio or vfio map failed", pci_dev->device.name);
+ return ret;
+
+ record = malloc(sizeof(*record));
+ if (!record)
+ return -ENOMEM;
+
+ record->vaddr = ms->addr_64;
+ record->iova = ms->iova;
+ record->len = ms->len;
+ TAILQ_INSERT_TAIL(&nbl_map_list, record, next);
+
+ return 0;
+}
+
+static int nbl_userdev_vfio_dma_map(int vfio_container_fd)
+{
+ if (rte_eal_iova_mode() == RTE_IOVA_VA) {
+ /* with IOVA as VA mode, we can get away with mapping contiguous
+ * chunks rather than going page-by-page.
+ */
+ int ret = rte_memseg_contig_walk(vfio_map_contig,
+ &vfio_container_fd);
+ if (ret)
+ return ret;
+ /* we have to continue the walk because we've skipped the
+ * external segments during the config walk.
+ */
+ }
+ return rte_memseg_walk(vfio_map, &vfio_container_fd);
+}
+
+static int nbl_userdev_dma_map(struct nbl_adapter *adapter)
+{
+ struct nbl_common_info *common = &adapter->common;
+ struct nbl_userdev_map_record *record;
+ rte_iova_t iova;
+
+ rte_mcfg_mem_read_lock();
+ TAILQ_FOREACH(record, &nbl_map_list, next) {
+ iova = record->iova;
+ if (common->dma_set_msb)
+ iova |= (1UL << common->dma_limit_msb);
+ nbl_userdev_dma_mem_map(common->devfd, record->vaddr, iova, record->len);
+ }
+ TAILQ_INSERT_TAIL(&nbl_adapter_list, adapter, next);
+ rte_mcfg_mem_read_unlock();
+
+ return 0;
+}
+
+static void *nbl_userdev_mmap(int devfd, __rte_unused int bar_index, size_t size)
+{
+ void *addr;
+
+ addr = rte_mem_map(NULL, size, RTE_PROT_READ | RTE_PROT_WRITE,
+ RTE_MAP_SHARED, devfd, 0);
+ if (!addr)
+ NBL_LOG(ERR, "usermap mmap bar failed");
+
+ return addr;
+}
+
+static int nbl_userdev_add_record(u64 vaddr, u64 iova, u64 len)
+{
+ struct nbl_userdev_map_record *record;
+ struct nbl_adapter *adapter;
+ u64 dma_iova;
+ int ret;
+
+ record = malloc(sizeof(*record));
+ if (!record)
+ return -ENOMEM;
+
+ ret = nbl_vfio_dma_mem_map(nbl_default_container, vaddr, len, 1);
+ if (ret) {
+ free(record);
+ return ret;
+ }
+
+ record->iova = iova;
+ record->len = len;
+ record->vaddr = vaddr;
+
+ TAILQ_INSERT_TAIL(&nbl_map_list, record, next);
+ TAILQ_FOREACH(adapter, &nbl_adapter_list, next) {
+ dma_iova = record->iova;
+ if (adapter->common.dma_set_msb)
+ dma_iova |= (1UL << adapter->common.dma_limit_msb);
+ nbl_userdev_dma_mem_map(adapter->common.devfd, record->vaddr,
+ dma_iova, record->len);
+ }
+
+ return 0;
+}
+
+static int nbl_userdev_free_record(u64 vaddr, u64 iova __rte_unused, u64 len __rte_unused)
+{
+ struct nbl_userdev_map_record *record, *tmp_record;
+
+ RTE_TAILQ_FOREACH_SAFE(record, &nbl_map_list, next, tmp_record) {
+ if (record->vaddr != vaddr)
+ continue;
+ nbl_vfio_dma_mem_map(nbl_default_container, vaddr, record->len, 0);
+ TAILQ_REMOVE(&nbl_map_list, record, next);
+ free(record);
+ }
+
+ return 0;
+}
+
+static void nbl_userdev_dma_free(void)
+{
+ struct nbl_userdev_map_record *record, *tmp_record;
+
+ RTE_TAILQ_FOREACH_SAFE(record, &nbl_map_list, next, tmp_record) {
+ TAILQ_REMOVE(&nbl_map_list, record, next);
+ free(record);
+ }
+}
+
+static void
+nbl_userdev_mem_event_callback(enum rte_mem_event type, const void *addr, size_t len,
+ void *arg __rte_unused)
+{
+ rte_iova_t iova_start, iova_expected;
+ struct rte_memseg_list *msl;
+ struct rte_memseg *ms;
+ size_t cur_len = 0;
+ u64 va_start;
+ u64 vfio_va;
+
+ if (!nbl_group_count)
+ return;
+
+ msl = rte_mem_virt2memseg_list(addr);
+
+ /* for IOVA as VA mode, no need to care for IOVA addresses */
+ if (rte_eal_iova_mode() == RTE_IOVA_VA && msl->external == 0) {
+ vfio_va = (u64)(uintptr_t)addr;
+ if (type == RTE_MEM_EVENT_ALLOC)
+ nbl_userdev_add_record(vfio_va, vfio_va, len);
+ else
+ nbl_userdev_free_record(vfio_va, vfio_va, len);
+ return;
+ }
+
+ /* memsegs are contiguous in memory */
+ ms = rte_mem_virt2memseg(addr, msl);
+
+ /* This memory is not guaranteed to be contiguous, but it still could
+ * be, or it could have some small contiguous chunks. Since the number
+ * of VFIO mappings is limited, and VFIO appears to not concatenate
+ * adjacent mappings, we have to do this ourselves.
+ * So, find contiguous chunks, then map them.
+ */
+ va_start = ms->addr_64;
+ iova_start = ms->iova;
+ iova_expected = ms->iova;
+ while (cur_len < len) {
+ bool new_contig_area = ms->iova != iova_expected;
+ bool last_seg = (len - cur_len) == ms->len;
+ bool skip_last = false;
+
+ /* only do mappings when current contiguous area ends */
+ if (new_contig_area) {
+ if (type == RTE_MEM_EVENT_ALLOC)
+ nbl_userdev_add_record(va_start, iova_start,
+ iova_expected - iova_start);
+ else
+ nbl_userdev_free_record(va_start, iova_start,
+ iova_expected - iova_start);
+ va_start = ms->addr_64;
+ iova_start = ms->iova;
+ }
+ /* some memory segments may have invalid IOVA */
+ if (ms->iova == RTE_BAD_IOVA) {
+ NBL_LOG(INFO, "Memory segment at %p has bad IOVA, skipping",
+ ms->addr);
+ skip_last = true;
+ }
+ iova_expected = ms->iova + ms->len;
+ cur_len += ms->len;
+ ++ms;
+
+ /* don't count previous segment, and don't attempt to
+ * dereference a potentially invalid pointer.
+ */
+ if (skip_last && !last_seg) {
+ iova_expected = ms->iova;
+ iova_start = ms->iova;
+ va_start = ms->addr_64;
+ } else if (!skip_last && last_seg) {
+ /* this is the last segment and we're not skipping */
+ if (type == RTE_MEM_EVENT_ALLOC)
+ nbl_userdev_add_record(va_start, iova_start,
+ iova_expected - iova_start);
+ else
+ nbl_userdev_free_record(va_start, iova_start,
+ iova_expected - iova_start);
+ }
+ }
+}
+
+static int nbl_mdev_map_device(struct nbl_adapter *adapter)
+{
+ const struct rte_pci_device *pci_dev = adapter->pci_dev;
+ struct nbl_common_info *common = &adapter->common;
+ char dev_name[RTE_DEV_NAME_MAX_LEN] = {0};
+ char pathname[PATH_MAX];
+ struct vfio_device_info device_info = { .argsz = sizeof(device_info) };
+ struct vfio_group_status group_status = {
+ .argsz = sizeof(group_status)
+ };
+ u64 dma_limit = NBL_USERDEV_DMA_LIMIT;
+ int ret, container_create = 0, container_set = 0;
+ int vfio_group_fd, container = nbl_default_container;
+
+ rte_pci_device_name(&pci_dev->addr, dev_name, RTE_DEV_NAME_MAX_LEN);
+ snprintf(pathname, sizeof(pathname),
+ "%s/%s/", rte_pci_get_sysfs_path(), dev_name);
+
+ ret = rte_vfio_get_group_num(pathname, dev_name, &common->iommu_group_num);
+ if (ret <= 0) {
+ NBL_LOG(INFO, "nbl vfio group number failed");
+ return -1;
+ }
+
+ NBL_LOG(INFO, "nbl vfio group number %d", common->iommu_group_num);
+ /* vfio_container */
+ if (nbl_default_container < 0) {
+ container = rte_vfio_container_create();
+ container_create = 1;
+
+ if (container < 0) {
+ NBL_LOG(ERR, "nbl vfio container create failed");
+ return -1;
+ }
+ }
+
+ NBL_LOG(INFO, "nbl vfio container %d", container);
+ vfio_group_fd = rte_vfio_container_group_bind(container, common->iommu_group_num);
+ if (vfio_group_fd < 0) {
+ NBL_LOG(ERR, "nbl vfio group bind failed, %d", vfio_group_fd);
+ goto free_container;
+ }
+
+ /* check if the group is viable */
+ ret = ioctl(vfio_group_fd, VFIO_GROUP_GET_STATUS, &group_status);
+ if (ret) {
+ NBL_LOG(ERR, "%s cannot get group status,error %i (%s)", dev_name,
+ errno, strerror(errno));
+ goto free_group;
+ } else if (!(group_status.flags & VFIO_GROUP_FLAGS_VIABLE)) {
+ NBL_LOG(ERR, "%s VFIO group is not viable!", dev_name);
+ goto free_group;
+ }
+
+ if (!(group_status.flags & VFIO_GROUP_FLAGS_CONTAINER_SET)) {
+ /* add group to a container */
+ ret = ioctl(vfio_group_fd, VFIO_GROUP_SET_CONTAINER, &container);
+ if (ret) {
+ NBL_LOG(ERR, "%s cannot add VFIO group to container, error %i (%s)",
+ dev_name, errno, strerror(errno));
+ goto free_group;
+ }
+
+ nbl_group_count++;
+ container_set = 1;
+ /* set an IOMMU type for container */
+
+ if (container_create || nbl_group_count == 1) {
+ if (ioctl(container, VFIO_CHECK_EXTENSION, VFIO_TYPE1v2_IOMMU)) {
+ ret = ioctl(container, VFIO_SET_IOMMU, VFIO_TYPE1v2_IOMMU);
+ if (ret) {
+ NBL_LOG(ERR, "Failed to setup VFIO iommu");
+ goto unset_container;
+ }
+ } else {
+ NBL_LOG(ERR, "No supported IOMMU available");
+ goto unset_container;
+ }
+
+ rte_mcfg_mem_read_lock();
+ ret = nbl_userdev_vfio_dma_map(container);
+ if (ret) {
+ rte_mcfg_mem_read_unlock();
+ NBL_LOG(WARNING, "nbl vfio container dma map failed, %d", ret);
+ goto free_dma_map;
+ }
+ ret = rte_mem_event_callback_register(NBL_USERDEV_EVENT_CLB_NAME,
+ nbl_userdev_mem_event_callback, NULL);
+ rte_mcfg_mem_read_unlock();
+ if (ret && rte_errno != ENOTSUP) {
+ NBL_LOG(WARNING, "nbl vfio mem event register callback failed, %d",
+ ret);
+ goto free_dma_map;
+ }
+ }
+ }
+
+ /* get a file descriptor for the device */
+ common->devfd = ioctl(vfio_group_fd, VFIO_GROUP_GET_DEVICE_FD, dev_name);
+ if (common->devfd < 0) {
+ /* if we cannot get a device fd, this implies a problem with
+ * the VFIO group or the container not having IOMMU configured.
+ */
+
+ NBL_LOG(WARNING, "Getting a vfio_dev_fd for %s failed, %d",
+ dev_name, common->devfd);
+ goto unregister_mem_event;
+ }
+
+ if (container_create)
+ nbl_default_container = container;
+
+ common->specific_dma = true;
+ if (rte_eal_iova_mode() == RTE_IOVA_PA)
+ common->dma_set_msb = true;
+ ioctl(common->devfd, NBL_DEV_USER_GET_DMA_LIMIT, &dma_limit);
+ common->dma_limit_msb = rte_fls_u64(dma_limit) - 1;
+ if (common->dma_limit_msb < 38) {
+ NBL_LOG(ERR, "iommu dma limit msb %u, low 3-level page table",
+ common->dma_limit_msb);
+ goto close_fd;
+ }
+
+ nbl_userdev_dma_map(adapter);
+
+ return 0;
+
+close_fd:
+ close(common->devfd);
+unregister_mem_event:
+ if (nbl_group_count == 1) {
+ rte_mcfg_mem_read_lock();
+ rte_mem_event_callback_unregister(NBL_USERDEV_EVENT_CLB_NAME, NULL);
+ rte_mcfg_mem_read_unlock();
+ }
+free_dma_map:
+ if (nbl_group_count == 1) {
+ rte_mcfg_mem_read_lock();
+ nbl_userdev_dma_free();
+ rte_mcfg_mem_read_unlock();
+ }
+unset_container:
+ if (container_set) {
+ ioctl(vfio_group_fd, VFIO_GROUP_UNSET_CONTAINER, &container);
+ nbl_group_count--;
+ }
+free_group:
+ close(vfio_group_fd);
+ rte_vfio_clear_group(vfio_group_fd);
+free_container:
+ if (container_create)
+ rte_vfio_container_destroy(container);
+ return -1;
+}
+
+static int nbl_mdev_unmap_device(struct nbl_adapter *adapter)
+{
+ struct nbl_common_info *common = &adapter->common;
+ int vfio_group_fd, ret;
+
+ close(common->devfd);
+ rte_mcfg_mem_read_lock();
+ vfio_group_fd = rte_vfio_container_group_bind(nbl_default_container,
+ common->iommu_group_num);
+ NBL_LOG(INFO, "close vfio_group_fd %d", vfio_group_fd);
+ ret = ioctl(vfio_group_fd, VFIO_GROUP_UNSET_CONTAINER, &nbl_default_container);
+ if (ret)
+ NBL_LOG(ERR, "unset container, error %i (%s) %d",
+ errno, strerror(errno), ret);
+ nbl_group_count--;
+ ret = rte_vfio_container_group_unbind(nbl_default_container, common->iommu_group_num);
+ if (ret)
+ NBL_LOG(ERR, "vfio container group unbind failed %d", ret);
+ if (!nbl_group_count) {
+ rte_mem_event_callback_unregister(NBL_USERDEV_EVENT_CLB_NAME, NULL);
+ nbl_userdev_dma_free();
+ }
+ rte_mcfg_mem_read_unlock();
+
+ return 0;
+}
+
+static int nbl_userdev_get_ifindex(int devfd)
+{
+ int ifindex = -1, ret;
+
+ ret = ioctl(devfd, NBL_DEV_USER_GET_IFINDEX, &ifindex);
+ if (ret)
+ NBL_LOG(ERR, "get ifindex failed %d", ret);
+
+ NBL_LOG(INFO, "get ifindex %d", ifindex);
+
+ return ifindex;
+}
+
+static int nbl_userdev_nl_init(int protocol)
+{
+ int fd;
+ int sndbuf_size = NBL_SEND_BUF_SIZE;
+ int rcvbuf_size = NBL_RECV_BUF_SIZE;
+ struct sockaddr_nl local = {
+ .nl_family = AF_NETLINK,
+ };
+ int ret;
+
+ fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, protocol);
+ if (fd == -1) {
+ rte_errno = errno;
+ return -rte_errno;
+ }
+ ret = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf_size, sizeof(int));
+ if (ret == -1) {
+ rte_errno = errno;
+ goto error;
+ }
+ ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf_size, sizeof(int));
+ if (ret == -1) {
+ rte_errno = errno;
+ goto error;
+ }
+ ret = bind(fd, (struct sockaddr *)&local, sizeof(local));
+ if (ret == -1) {
+ rte_errno = errno;
+ goto error;
+ }
+ return fd;
+error:
+ close(fd);
+ return -rte_errno;
+}
+
+int nbl_userdev_port_config(struct nbl_adapter *adapter, int start)
+{
+ struct nbl_common_info *common = &adapter->common;
+ int ret;
+
+ if (NBL_IS_NOT_COEXISTENCE(common))
+ return 0;
+
+ if (common->isolate)
+ return 0;
+
+ ret = ioctl(common->devfd, NBL_DEV_USER_SWITCH_NETWORK, &start);
+ if (ret) {
+ NBL_LOG(ERR, "userspace switch network ret %d", ret);
+ return ret;
+ }
+
+ common->curr_network = start;
+ return ret;
+}
+
+int nbl_userdev_port_isolate(struct nbl_adapter *adapter, int set, struct rte_flow_error *error)
+{
+ struct nbl_common_info *common = &adapter->common;
+ int ret = 0, stat = !set;
+
+ if (NBL_IS_NOT_COEXISTENCE(common)) {
+ /* special use for isolate: offload mode ignore isolate when pf is in vfio/uio */
+ rte_flow_error_set(error, EREMOTEIO,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "nbl isolate switch failed.");
+ return -EREMOTEIO;
+ }
+
+ if (common->curr_network != stat)
+ ret = ioctl(common->devfd, NBL_DEV_USER_SWITCH_NETWORK, &stat);
+
+ if (ret) {
+ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "nbl isolate switch failed.");
+ return ret;
+ }
+
+ common->curr_network = !set;
+ common->isolate = set;
+
+ return ret;
+}
+
+int nbl_pci_map_device(struct nbl_adapter *adapter)
+{
+ struct rte_pci_device *pci_dev = adapter->pci_dev;
+ const struct rte_pci_addr *loc = &pci_dev->addr;
+ struct nbl_common_info *common = &adapter->common;
+ char pathname[PATH_MAX];
+ int ret = 0, fd;
+ enum rte_iova_mode iova_mode;
+ size_t bar_size = NBL_USERDEV_BAR0_SIZE;
+
+ NBL_USERDEV_INIT_COMMON(common);
+ iova_mode = rte_eal_iova_mode();
+ if (iova_mode == RTE_IOVA_PA) {
+ /* check iommu disable */
+ snprintf(pathname, sizeof(pathname),
+ "/dev/nbl_userdev/" PCI_PRI_FMT, loc->domain,
+ loc->bus, loc->devid, loc->function);
+ common->devfd = open(pathname, O_RDWR);
+ if (common->devfd >= 0)
+ goto mmap;
+
+ NBL_LOG(INFO, "%s char device open failed", pci_dev->device.name);
+ }
+
+ /* check iommu translate mode */
+ ret = nbl_mdev_map_device(adapter);
+ if (ret) {
+ ret = rte_pci_map_device(pci_dev);
+ if (ret)
+ NBL_LOG(ERR, "uio/vfio %s map device failed", pci_dev->device.name);
+ return ret;
+ }
+
+mmap:
+ fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
+ if (fd < 0) {
+ NBL_LOG(ERR, "nbl userdev get event fd failed");
+ ret = -1;
+ goto close_fd;
+ }
+
+ ret = ioctl(common->devfd, NBL_DEV_USER_SET_EVENTFD, &fd);
+ if (ret) {
+ NBL_LOG(ERR, "nbl userdev set event fd failed");
+ goto close_eventfd;
+ }
+
+ common->eventfd = fd;
+ ioctl(common->devfd, NBL_DEV_USER_GET_BAR_SIZE, &bar_size);
+
+ if (!ret) {
+ pci_dev->mem_resource[0].addr = nbl_userdev_mmap(common->devfd, 0, bar_size);
+ pci_dev->mem_resource[0].phys_addr = 0;
+ pci_dev->mem_resource[0].len = bar_size;
+ pci_dev->mem_resource[2].addr = 0;
+
+ common->ifindex = nbl_userdev_get_ifindex(common->devfd);
+ common->nl_socket_route = nbl_userdev_nl_init(NETLINK_ROUTE);
+ }
+
+ return ret;
+
+close_eventfd:
+ close(fd);
+close_fd:
+ if (common->specific_dma)
+ nbl_mdev_unmap_device(adapter);
+ else
+ close(common->devfd);
return ret;
}
@@ -19,6 +724,35 @@ int nbl_pci_map_device(struct nbl_adapter *adapter)
void nbl_pci_unmap_device(struct nbl_adapter *adapter)
{
struct rte_pci_device *pci_dev = adapter->pci_dev;
+ struct nbl_common_info *common = &adapter->common;
+
+ if (NBL_IS_NOT_COEXISTENCE(common))
+ return rte_pci_unmap_device(pci_dev);
+
+ rte_mem_unmap(pci_dev->mem_resource[0].addr, pci_dev->mem_resource[0].len);
+ ioctl(common->devfd, NBL_DEV_USER_CLEAR_EVENTFD, 0);
+ close(common->eventfd);
+ close(common->nl_socket_route);
+
+ if (!common->specific_dma) {
+ close(common->devfd);
+ return;
+ }
+
+ nbl_mdev_unmap_device(adapter);
+}
+
+int nbl_userdev_get_iova_mode(const struct rte_pci_device *dev)
+{
+ char pathname[PATH_MAX];
+ const struct rte_pci_addr *loc = &dev->addr;
+
+ snprintf(pathname, sizeof(pathname),
+ "/dev/nbl_userdev/" PCI_PRI_FMT, loc->domain,
+ loc->bus, loc->devid, loc->function);
+
+ if (!access(pathname, F_OK))
+ return RTE_IOVA_PA;
- return rte_pci_unmap_device(pci_dev);
+ return RTE_IOVA_DC;
}
diff --git a/drivers/net/nbl/nbl_common/nbl_userdev.h b/drivers/net/nbl/nbl_common/nbl_userdev.h
index 11cc29999c..2221e19c67 100644
--- a/drivers/net/nbl/nbl_common/nbl_userdev.h
+++ b/drivers/net/nbl/nbl_common/nbl_userdev.h
@@ -6,5 +6,16 @@
#define _NBL_USERDEV_H_
#include "nbl_ethdev.h"
+#include "nbl_common.h"
+
+#define NBL_USERDEV_INIT_COMMON(common) do { \
+ typeof(common) _comm = (common); \
+ _comm->devfd = -1; \
+ _comm->eventfd = -1; \
+ _comm->specific_dma = false; \
+ _comm->dma_set_msb = false; \
+ _comm->ifindex = -1; \
+ _comm->nl_socket_route = -1; \
+} while (0)
#endif
diff --git a/drivers/net/nbl/nbl_core.c b/drivers/net/nbl/nbl_core.c
index f4ddc9e219..4a7b03a01f 100644
--- a/drivers/net/nbl/nbl_core.c
+++ b/drivers/net/nbl/nbl_core.c
@@ -29,10 +29,11 @@ static void nbl_init_func_caps(const struct rte_pci_device *pci_dev, struct nbl_
int nbl_core_init(struct nbl_adapter *adapter, struct rte_eth_dev *eth_dev)
{
- const struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
+ struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
const struct nbl_product_core_ops *product_base_ops = NULL;
int ret = 0;
+ adapter->pci_dev = pci_dev;
nbl_init_func_caps(pci_dev, &adapter->caps);
product_base_ops = nbl_core_get_product_ops(adapter->caps.product_type);
diff --git a/drivers/net/nbl/nbl_core.h b/drivers/net/nbl/nbl_core.h
index bdf31e15da..997544b112 100644
--- a/drivers/net/nbl/nbl_core.h
+++ b/drivers/net/nbl/nbl_core.h
@@ -51,7 +51,6 @@
#define NBL_IS_NOT_COEXISTENCE(common) ({ typeof(common) _common = (common); \
_common->nl_socket_route < 0 || \
_common->ifindex < 0; })
-
struct nbl_core {
void *phy_mgt;
void *res_mgt;
diff --git a/drivers/net/nbl/nbl_ethdev.c b/drivers/net/nbl/nbl_ethdev.c
index 90b1487567..e7694988ce 100644
--- a/drivers/net/nbl/nbl_ethdev.c
+++ b/drivers/net/nbl/nbl_ethdev.c
@@ -108,6 +108,11 @@ static int nbl_pci_remove(struct rte_pci_device *pci_dev)
return rte_eth_dev_pci_generic_remove(pci_dev, nbl_eth_dev_uninit);
}
+static int nbl_pci_get_iova_mode(const struct rte_pci_device *dev)
+{
+ return nbl_userdev_get_iova_mode(dev);
+}
+
static const struct rte_pci_id pci_id_nbl_map[] = {
{ RTE_PCI_DEVICE(NBL_VENDOR_ID, NBL_DEVICE_ID_M18110) },
{ RTE_PCI_DEVICE(NBL_VENDOR_ID, NBL_DEVICE_ID_M18110_LX) },
@@ -136,6 +141,7 @@ static struct rte_pci_driver nbl_pmd = {
RTE_PCI_DRV_PROBE_AGAIN,
.probe = nbl_pci_probe,
.remove = nbl_pci_remove,
+ .get_iova_mode = nbl_pci_get_iova_mode,
};
RTE_PMD_REGISTER_PCI(net_nbl, nbl_pmd);
diff --git a/drivers/net/nbl/nbl_hw/nbl_channel.c b/drivers/net/nbl/nbl_hw/nbl_channel.c
index 09f1870ed0..c8998ae3e5 100644
--- a/drivers/net/nbl/nbl_hw/nbl_channel.c
+++ b/drivers/net/nbl/nbl_hw/nbl_channel.c
@@ -575,6 +575,181 @@ static struct nbl_channel_ops chan_ops = {
.set_state = nbl_chan_set_state,
};
+static int nbl_chan_userdev_send_msg(void *priv, struct nbl_chan_send_info *chan_send)
+{
+ struct nbl_channel_mgt *chan_mgt = (struct nbl_channel_mgt *)priv;
+ struct nbl_common_info *common = NBL_CHAN_MGT_TO_COMMON(chan_mgt);
+ struct nbl_dev_user_channel_msg msg;
+ uint32_t *result;
+ int ret;
+
+ if (chan_mgt->state)
+ return -EIO;
+
+ msg.msg_type = chan_send->msg_type;
+ msg.dst_id = chan_send->dstid;
+ msg.arg_len = chan_send->arg_len;
+ msg.ack = chan_send->ack;
+ msg.ack_length = chan_send->resp_len;
+ rte_memcpy(&msg.data, chan_send->arg, chan_send->arg_len);
+
+ ret = ioctl(common->devfd, NBL_DEV_USER_CHANNEL, &msg);
+ if (ret) {
+ NBL_LOG(ERR, "user mailbox failed, type %u, ret %d", msg.msg_type, ret);
+ return -1;
+ }
+
+ /* 4bytes align */
+ result = (uint32_t *)RTE_PTR_ALIGN(((unsigned char *)msg.data) + chan_send->arg_len, 4);
+ rte_memcpy(chan_send->resp, result, RTE_MIN(chan_send->resp_len, msg.ack_length));
+
+ return msg.ack_err;
+}
+
+static int nbl_chan_userdev_send_ack(void *priv, struct nbl_chan_ack_info *chan_ack)
+{
+ struct nbl_channel_mgt *chan_mgt = (struct nbl_channel_mgt *)priv;
+ struct nbl_chan_send_info chan_send;
+ u32 *tmp;
+ u32 len = 3 * sizeof(u32) + chan_ack->data_len;
+
+ tmp = rte_zmalloc("nbl_chan_send_tmp", len, 0);
+ if (!tmp) {
+ NBL_LOG(ERR, "Chan send ack data malloc failed");
+ return -ENOMEM;
+ }
+
+ tmp[0] = chan_ack->msg_type;
+ tmp[1] = chan_ack->msgid;
+ tmp[2] = (u32)chan_ack->err;
+ if (chan_ack->data && chan_ack->data_len)
+ memcpy(&tmp[3], chan_ack->data, chan_ack->data_len);
+
+ NBL_CHAN_SEND(chan_send, chan_ack->dstid, NBL_CHAN_MSG_ACK, tmp, len, NULL, 0, 0);
+ nbl_chan_userdev_send_msg(chan_mgt, &chan_send);
+ rte_free(tmp);
+
+ return 0;
+}
+
+static void nbl_chan_userdev_eventfd_handler(void *cn_arg)
+{
+ size_t page_size = rte_mem_page_size();
+ char *bak_buf = malloc(page_size);
+ struct nbl_channel_mgt *chan_mgt = (struct nbl_channel_mgt *)cn_arg;
+ union nbl_chan_info *chan_info = NBL_CHAN_MGT_TO_CHAN_INFO(chan_mgt);
+ char *data = (char *)chan_info->userdev.shm_msg_ring + 8;
+ char *payload;
+ u64 buf;
+ int nbytes __rte_unused;
+ u32 total_len;
+ u32 *head = (u32 *)chan_info->userdev.shm_msg_ring;
+ u32 *tail = (u32 *)chan_info->userdev.shm_msg_ring + 1, tmp_tail;
+ u32 shmmsgbuf_size = page_size - 8;
+
+ if (!bak_buf) {
+ NBL_LOG(ERR, "nbl chan handler malloc failed");
+ return;
+ }
+ tmp_tail = *tail;
+ nbytes = read(chan_info->userdev.eventfd, &buf, sizeof(buf));
+
+ while (*head != tmp_tail) {
+ total_len = *(u32 *)(data + tmp_tail);
+ if (tmp_tail + total_len > shmmsgbuf_size) {
+ u32 copy_len;
+
+ copy_len = shmmsgbuf_size - tmp_tail;
+ memcpy(bak_buf, data + tmp_tail, copy_len);
+ memcpy(bak_buf + copy_len, data, total_len - copy_len);
+ payload = bak_buf;
+
+ } else {
+ payload = (data + tmp_tail);
+ }
+
+ nbl_chan_recv_msg(chan_mgt, payload + 4);
+ tmp_tail += total_len;
+ if (tmp_tail >= shmmsgbuf_size)
+ tmp_tail -= shmmsgbuf_size;
+ }
+
+ free(bak_buf);
+ *tail = tmp_tail;
+}
+
+static int nbl_chan_userdev_setup_queue(void *priv)
+{
+ size_t page_size = rte_mem_page_size();
+ struct nbl_channel_mgt *chan_mgt = (struct nbl_channel_mgt *)priv;
+ union nbl_chan_info *chan_info = NBL_CHAN_MGT_TO_CHAN_INFO(chan_mgt);
+ struct nbl_common_info *common = NBL_CHAN_MGT_TO_COMMON(chan_mgt);
+ int ret;
+
+ if (common->devfd < 0 || common->eventfd < 0)
+ return -EINVAL;
+
+ chan_info->userdev.eventfd = common->eventfd;
+ chan_info->userdev.intr_handle.fd = common->eventfd;
+ chan_info->userdev.intr_handle.type = RTE_INTR_HANDLE_EXT;
+
+ ret = rte_intr_callback_register(&chan_info->userdev.intr_handle,
+ nbl_chan_userdev_eventfd_handler, chan_mgt);
+
+ if (ret) {
+ NBL_LOG(ERR, "channel userdev event handler register failed, %d", ret);
+ return ret;
+ }
+
+ chan_info->userdev.shm_msg_ring = rte_mem_map(NULL, page_size,
+ RTE_PROT_READ | RTE_PROT_WRITE,
+ RTE_MAP_SHARED, common->devfd,
+ NBL_DEV_USER_INDEX_TO_OFFSET
+ (NBL_DEV_SHM_MSG_RING_INDEX));
+ if (!chan_info->userdev.shm_msg_ring) {
+ rte_intr_callback_unregister(&chan_info->userdev.intr_handle,
+ nbl_chan_userdev_eventfd_handler, chan_mgt);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int nbl_chan_userdev_teardown_queue(void *priv)
+{
+ struct nbl_channel_mgt *chan_mgt = (struct nbl_channel_mgt *)priv;
+ union nbl_chan_info *chan_info = NBL_CHAN_MGT_TO_CHAN_INFO(chan_mgt);
+
+ rte_mem_unmap(chan_info->userdev.shm_msg_ring, rte_mem_page_size());
+ rte_intr_callback_unregister(&chan_info->userdev.intr_handle,
+ nbl_chan_userdev_eventfd_handler, chan_mgt);
+
+ return 0;
+}
+
+static int nbl_chan_userdev_register_msg(void *priv, uint16_t msg_type, nbl_chan_resp func,
+ void *callback_priv)
+{
+ struct nbl_channel_mgt *chan_mgt = (struct nbl_channel_mgt *)priv;
+ struct nbl_common_info *common = NBL_CHAN_MGT_TO_COMMON(chan_mgt);
+ int ret, type;
+
+ type = msg_type;
+ nbl_chan_register_msg(priv, msg_type, func, callback_priv);
+ ret = ioctl(common->devfd, NBL_DEV_USER_SET_LISTENER, &type);
+
+ return ret;
+}
+
+static struct nbl_channel_ops userdev_ops = {
+ .send_msg = nbl_chan_userdev_send_msg,
+ .send_ack = nbl_chan_userdev_send_ack,
+ .register_msg = nbl_chan_userdev_register_msg,
+ .setup_queue = nbl_chan_userdev_setup_queue,
+ .teardown_queue = nbl_chan_userdev_teardown_queue,
+ .set_state = nbl_chan_set_state,
+};
+
static int nbl_chan_setup_chan_mgt(struct nbl_adapter *adapter,
struct nbl_channel_mgt_leonis **chan_mgt_leonis)
{
@@ -594,7 +769,7 @@ static int nbl_chan_setup_chan_mgt(struct nbl_adapter *adapter,
goto alloc_mailbox_fail;
NBL_CHAN_MGT_TO_CHAN_INFO(&(*chan_mgt_leonis)->chan_mgt) = mailbox;
-
+ NBL_CHAN_MGT_TO_COMMON(&(*chan_mgt_leonis)->chan_mgt) = &adapter->common;
return 0;
alloc_mailbox_fail:
@@ -619,11 +794,17 @@ static void nbl_chan_remove_ops(struct nbl_channel_ops_tbl **chan_ops_tbl)
static int nbl_chan_setup_ops(struct nbl_channel_ops_tbl **chan_ops_tbl,
struct nbl_channel_mgt_leonis *chan_mgt_leonis)
{
+ struct nbl_common_info *common;
+
*chan_ops_tbl = rte_zmalloc("nbl_chan_ops_tbl", sizeof(struct nbl_channel_ops_tbl), 0);
if (!*chan_ops_tbl)
return -ENOMEM;
- NBL_CHAN_OPS_TBL_TO_OPS(*chan_ops_tbl) = &chan_ops;
+ common = NBL_CHAN_MGT_TO_COMMON(&chan_mgt_leonis->chan_mgt);
+ if (NBL_IS_NOT_COEXISTENCE(common))
+ NBL_CHAN_OPS_TBL_TO_OPS(*chan_ops_tbl) = &chan_ops;
+ else
+ NBL_CHAN_OPS_TBL_TO_OPS(*chan_ops_tbl) = &userdev_ops;
NBL_CHAN_OPS_TBL_TO_PRIV(*chan_ops_tbl) = chan_mgt_leonis;
chan_mgt_leonis->chan_mgt.msg_handler[NBL_CHAN_MSG_ACK].func = nbl_chan_recv_ack_msg;
diff --git a/drivers/net/nbl/nbl_hw/nbl_channel.h b/drivers/net/nbl/nbl_hw/nbl_channel.h
index df2222d995..a6ba9fcd71 100644
--- a/drivers/net/nbl/nbl_hw/nbl_channel.h
+++ b/drivers/net/nbl/nbl_hw/nbl_channel.h
@@ -7,6 +7,10 @@
#include "nbl_ethdev.h"
+#define NBL_CHAN_MAX_PAGE_SIZE (64 * 1024)
+
+#define NBL_CHAN_MGT_TO_COMMON(chan_mgt) ((chan_mgt)->common)
+#define NBL_CHAN_MGT_TO_DEV(chan_mgt) NBL_COMMON_TO_DEV(NBL_CHAN_MGT_TO_COMMON(chan_mgt))
#define NBL_CHAN_MGT_TO_PHY_OPS_TBL(chan_mgt) ((chan_mgt)->phy_ops_tbl)
#define NBL_CHAN_MGT_TO_PHY_OPS(chan_mgt) (NBL_CHAN_MGT_TO_PHY_OPS_TBL(chan_mgt)->ops)
#define NBL_CHAN_MGT_TO_PHY_PRIV(chan_mgt) (NBL_CHAN_MGT_TO_PHY_OPS_TBL(chan_mgt)->priv)
@@ -90,6 +94,12 @@ union nbl_chan_info {
struct nbl_work work;
} mailbox;
+
+ struct {
+ struct rte_intr_handle intr_handle;
+ void *shm_msg_ring;
+ int eventfd;
+ } userdev;
};
struct nbl_chan_msg_handler {
@@ -99,6 +109,7 @@ struct nbl_chan_msg_handler {
struct nbl_channel_mgt {
uint32_t mode;
+ struct nbl_common_info *common;
struct nbl_phy_ops_tbl *phy_ops_tbl;
union nbl_chan_info *chan_info;
struct nbl_chan_msg_handler msg_handler[NBL_CHAN_MSG_MAX];
diff --git a/drivers/net/nbl/nbl_hw/nbl_hw_leonis/nbl_phy_leonis_snic.c b/drivers/net/nbl/nbl_hw/nbl_hw_leonis/nbl_phy_leonis_snic.c
index 9ed375bc1e..bfb86455ae 100644
--- a/drivers/net/nbl/nbl_hw/nbl_hw_leonis/nbl_phy_leonis_snic.c
+++ b/drivers/net/nbl/nbl_hw/nbl_hw_leonis/nbl_phy_leonis_snic.c
@@ -177,7 +177,7 @@ int nbl_phy_init_leonis_snic(void *p)
struct nbl_phy_mgt *phy_mgt;
struct nbl_phy_ops_tbl **phy_ops_tbl;
struct nbl_adapter *adapter = (struct nbl_adapter *)p;
- struct rte_pci_device *pci_dev = adapter->pci_dev;
+ const struct rte_pci_device *pci_dev = adapter->pci_dev;
int ret = 0;
phy_mgt_leonis_snic = (struct nbl_phy_mgt_leonis_snic **)&NBL_ADAPTER_TO_PHY_MGT(adapter);
diff --git a/drivers/net/nbl/nbl_include/nbl_def_common.h b/drivers/net/nbl/nbl_include/nbl_def_common.h
index 0b87c3003d..795679576e 100644
--- a/drivers/net/nbl/nbl_include/nbl_def_common.h
+++ b/drivers/net/nbl/nbl_include/nbl_def_common.h
@@ -24,6 +24,67 @@
#define NBL_TWO_ETHERNET_MAX_MAC_NUM (512)
#define NBL_FOUR_ETHERNET_MAX_MAC_NUM (1024)
+#define NBL_DEV_USER_TYPE ('n')
+#define NBL_DEV_USER_DATA_LEN (2044)
+
+#define NBL_DEV_USER_PCI_OFFSET_SHIFT 40
+#define NBL_DEV_USER_OFFSET_TO_INDEX(off) ((off) >> NBL_DEV_USER_PCI_OFFSET_SHIFT)
+#define NBL_DEV_USER_INDEX_TO_OFFSET(index) ((u64)(index) << NBL_DEV_USER_PCI_OFFSET_SHIFT)
+#define NBL_DEV_SHM_MSG_RING_INDEX (6)
+
+struct nbl_dev_user_channel_msg {
+ u16 msg_type;
+ u16 dst_id;
+ u32 arg_len;
+ u32 ack_err;
+ u16 ack_length;
+ u16 ack;
+ u32 data[NBL_DEV_USER_DATA_LEN];
+};
+
+#define NBL_DEV_USER_CHANNEL _IO(NBL_DEV_USER_TYPE, 0)
+
+struct nbl_dev_user_dma_map {
+ uint32_t argsz;
+ uint32_t flags;
+#define NBL_DEV_USER_DMA_MAP_FLAG_READ (RTE_BIT64(0)) /* readable from device */
+#define NBL_DEV_USER_DMA_MAP_FLAG_WRITE (RTE_BIT64(1)) /* writable from device */
+ uint64_t vaddr; /* Process virtual address */
+ uint64_t iova; /* IO virtual address */
+ uint64_t size; /* Size of mapping (bytes) */
+};
+
+#define NBL_DEV_USER_MAP_DMA _IO(NBL_DEV_USER_TYPE, 1)
+
+struct nbl_dev_user_dma_unmap {
+ uint32_t argsz;
+ uint32_t flags;
+ uint64_t vaddr; /* Process virtual address */
+ uint64_t iova; /* IO virtual address */
+ uint64_t size; /* Size of mapping (bytes) */
+};
+
+#define NBL_DEV_USER_UNMAP_DMA _IO(NBL_DEV_USER_TYPE, 2)
+
+#define NBL_KERNEL_NETWORK 0
+#define NBL_USER_NETWORK 1
+
+#define NBL_DEV_USER_SWITCH_NETWORK _IO(NBL_DEV_USER_TYPE, 3)
+#define NBL_DEV_USER_GET_IFINDEX _IO(NBL_DEV_USER_TYPE, 4)
+
+struct nbl_dev_user_link_stat {
+ u8 state;
+ u8 flush;
+};
+
+#define NBL_DEV_USER_SET_EVENTFD _IO(NBL_DEV_USER_TYPE, 5)
+#define NBL_DEV_USER_CLEAR_EVENTFD _IO(NBL_DEV_USER_TYPE, 6)
+#define NBL_DEV_USER_SET_LISTENER _IO(NBL_DEV_USER_TYPE, 7)
+#define NBL_DEV_USER_GET_BAR_SIZE _IO(NBL_DEV_USER_TYPE, 8)
+#define NBL_DEV_USER_GET_DMA_LIMIT _IO(NBL_DEV_USER_TYPE, 9)
+#define NBL_DEV_USER_SET_PROMISC_MODE _IO(NBL_DEV_USER_TYPE, 10)
+#define NBL_DEV_USER_SET_MCAST_MODE _IO(NBL_DEV_USER_TYPE, 11)
+
struct nbl_dma_mem {
void *va;
uint64_t pa;
@@ -49,7 +110,9 @@ int nbl_thread_add_work(struct nbl_work *work);
void nbl_thread_del_work(struct nbl_work *work);
struct nbl_adapter;
+int nbl_userdev_port_config(struct nbl_adapter *adapter, int start);
+int nbl_userdev_port_isolate(struct nbl_adapter *adapter, int set, struct rte_flow_error *error);
int nbl_pci_map_device(struct nbl_adapter *adapter);
void nbl_pci_unmap_device(struct nbl_adapter *adapter);
-
+int nbl_userdev_get_iova_mode(const struct rte_pci_device *dev);
#endif
diff --git a/drivers/net/nbl/nbl_include/nbl_include.h b/drivers/net/nbl/nbl_include/nbl_include.h
index 44d157d2a7..55ab7ac8bd 100644
--- a/drivers/net/nbl/nbl_include/nbl_include.h
+++ b/drivers/net/nbl/nbl_include/nbl_include.h
@@ -44,6 +44,8 @@
#include <rte_common.h>
#include <rte_thread.h>
#include <rte_stdatomic.h>
+#include <rte_eal_paging.h>
+#include <eal_interrupts.h>
#include "nbl_logs.h"
--
2.43.0
next prev parent reply other threads:[~2025-06-12 9:00 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-12 8:58 [PATCH v1 00/17] NBL PMD for Nebulamatrix NICs Kyo Liu
2025-06-12 8:58 ` [PATCH v1 01/17] net/nbl: add doc and minimum nbl build framework Kyo Liu
2025-06-12 8:58 ` [PATCH v1 02/17] net/nbl: add simple probe/remove and log module Kyo Liu
2025-06-12 17:49 ` Stephen Hemminger
2025-06-13 2:32 ` 回复:[PATCH " Kyo.Liu
2025-06-12 8:58 ` [PATCH v1 03/17] net/nbl: add PHY layer definitions and implementation Kyo Liu
2025-06-12 8:58 ` [PATCH v1 04/17] net/nbl: add Channel " Kyo Liu
2025-06-12 8:58 ` [PATCH v1 05/17] net/nbl: add Resource " Kyo Liu
2025-06-12 8:58 ` [PATCH v1 06/17] net/nbl: add Dispatch " Kyo Liu
2025-06-12 8:58 ` [PATCH v1 07/17] net/nbl: add Dev " Kyo Liu
2025-06-12 8:58 ` [PATCH v1 08/17] net/nbl: add complete device init and uninit functionality Kyo Liu
2025-06-12 8:58 ` [PATCH v1 09/17] net/nbl: add uio and vfio mode for nbl Kyo Liu
2025-06-12 8:58 ` [PATCH v1 10/17] net/nbl: bus/pci: introduce get_iova_mode for pci dev Kyo Liu
2025-06-12 17:40 ` Stephen Hemminger
2025-06-13 2:28 ` 回复:[PATCH " Kyo.Liu
2025-06-13 7:35 ` [PATCH " David Marchand
2025-06-13 15:21 ` 回复:[PATCH " Stephen Hemminger
2025-06-12 8:58 ` Kyo Liu [this message]
2025-06-12 8:58 ` [PATCH v1 12/17] net/nbl: add nbl ethdev configuration Kyo Liu
2025-06-12 8:58 ` [PATCH v1 13/17] net/nbl: add nbl device rxtx queue setup and release ops Kyo Liu
2025-06-12 8:58 ` [PATCH v1 14/17] net/nbl: add nbl device start and stop ops Kyo Liu
2025-06-12 8:58 ` [PATCH v1 15/17] net/nbl: add nbl device tx and rx burst Kyo Liu
2025-06-12 8:58 ` [PATCH v1 16/17] net/nbl: add nbl device xstats and stats Kyo Liu
2025-06-12 8:58 ` [PATCH v1 17/17] net/nbl: nbl device support set mtu and promisc Kyo Liu
2025-06-12 17:35 ` [PATCH v1 00/17] NBL PMD for Nebulamatrix NICs Stephen Hemminger
2025-06-12 17:44 ` Stephen Hemminger
2025-06-13 2:31 ` 回复:[PATCH " Kyo.Liu
2025-06-12 17:46 ` [PATCH " Stephen Hemminger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250612085840.729830-12-kyo.liu@nebula-matrix.com \
--to=kyo.liu@nebula-matrix.com \
--cc=dev@dpdk.org \
--cc=dimon.zhao@nebula-matrix.com \
--cc=leon.yu@nebula-matrix.com \
--cc=sam.chen@nebula-matrix.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).