@@ -8,6 +8,26 @@ endif
sources = files(
'xsc_ethdev.c',
+ 'xsc_dev.c',
+ 'xsc_utils.c',
)
+libnames = ['ibverbs']
+foreach libname:libnames
+ lib = dependency('lib' + libname, method : 'pkg-config')
+ if lib.found()
+ ext_deps += lib
+ else
+ build = false
+ reason = 'missing dependency, "' + lib + '"'
+ subdir_done()
+ endif
+endforeach
+lib = dependency('libxscale', required: false, method : 'pkg-config')
+if lib.found()
+ ext_deps += lib
+ cflags += '-DHAVE_XSC_DV_PROVIDER=1'
+else
+ cflags += '-DHAVE_XSC_DV_PROVIDER=0'
+endif
@@ -8,5 +8,28 @@
#define XSC_PCI_VENDOR_ID 0x1f67
#define XSC_PCI_DEV_ID_MS 0x1111
+enum xsc_nic_mode {
+ XSC_NIC_MODE_LEGACY,
+ XSC_NIC_MODE_SWITCHDEV,
+ XSC_NIC_MODE_SOC,
+};
+
+enum xsc_pph_type {
+ XSC_PPH_NONE = 0,
+ XSC_RX_PPH = 0x1,
+ XSC_TX_PPH = 0x2,
+ XSC_VFREP_PPH = 0x4,
+ XSC_UPLINK_PPH = 0x8,
+};
+
+enum xsc_flow_mode {
+ XSC_FLOW_OFF_HW_ONLY,
+ XSC_FLOW_ON_HW_ONLY,
+ XSC_FLOW_ON_HW_FIRST,
+ XSC_FLOW_HOTSPOT,
+ XSC_FLOW_MODE_NULL = 7,
+ XSC_FLOW_MODE_MAX,
+};
+
#endif /* XSC_DEFS_H_ */
new file mode 100644
@@ -0,0 +1,162 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2024 Yunsilicon Technology Co., Ltd.
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <sys/mman.h>
+
+#include <rte_pci.h>
+#include <rte_bus_pci.h>
+#include <rte_malloc.h>
+#include <rte_kvargs.h>
+
+#include "xsc_log.h"
+#include "xsc_defs.h"
+#include "xsc_dev.h"
+#include "xsc_utils.h"
+
+#define XSC_DEV_DEF_FLOW_MODE XSC_FLOW_MODE_NULL
+#define XSC_DEV_CTRL_FILE_FMT "/dev/yunsilicon/port_ctrl_" PCI_PRI_FMT
+
+static
+void xsc_dev_args_parse(struct xsc_dev *dev, struct rte_devargs *devargs)
+{
+ struct rte_kvargs *kvlist;
+ struct xsc_devargs *xdevargs = &dev->devargs;
+ const char *tmp;
+
+ kvlist = rte_kvargs_parse(devargs->args, NULL);
+ if (kvlist == NULL)
+ return;
+
+ tmp = rte_kvargs_get(kvlist, XSC_PPH_MODE_ARG);
+ if (tmp != NULL)
+ xdevargs->pph_mode = atoi(tmp);
+ else
+ xdevargs->pph_mode = XSC_PPH_NONE;
+ tmp = rte_kvargs_get(kvlist, XSC_NIC_MODE_ARG);
+ if (tmp != NULL)
+ xdevargs->nic_mode = atoi(tmp);
+ else
+ xdevargs->nic_mode = XSC_NIC_MODE_LEGACY;
+ tmp = rte_kvargs_get(kvlist, XSC_FLOW_MODE_ARG);
+ if (tmp != NULL)
+ xdevargs->flow_mode = atoi(tmp);
+ else
+ xdevargs->flow_mode = XSC_DEV_DEF_FLOW_MODE;
+
+ rte_kvargs_free(kvlist);
+}
+
+static int
+xsc_dev_open(struct xsc_dev *dev, struct rte_pci_device *pci_dev)
+{
+ struct ibv_device *ib_dev;
+ char ctrl_file[PATH_MAX];
+ struct rte_pci_addr *pci_addr = &pci_dev->addr;
+ int ret;
+
+ ib_dev = xsc_get_ibv_device(&pci_dev->addr);
+ if (ib_dev == NULL) {
+ PMD_DRV_LOG(ERR, "Could not get ibv device");
+ return -ENODEV;
+ }
+
+ dev->ibv_ctx = ibv_open_device(ib_dev);
+ if (dev->ibv_ctx == NULL) {
+ PMD_DRV_LOG(ERR, "Could not open ibv device: %s", ib_dev->name);
+ return -ENODEV;
+ }
+
+ dev->ibv_pd = ibv_alloc_pd(dev->ibv_ctx);
+ if (dev->ibv_pd == NULL) {
+ PMD_DRV_LOG(ERR, "Failed to create pd:%s", ib_dev->name);
+ ret = -EINVAL;
+ goto alloc_pd_fail;
+ }
+
+ strcpy(dev->ibv_name, ib_dev->name);
+
+ snprintf(ctrl_file, PATH_MAX, XSC_DEV_CTRL_FILE_FMT,
+ pci_addr->domain, pci_addr->bus, pci_addr->devid, pci_addr->function);
+
+ ret = open(ctrl_file, O_RDWR);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "Failed to open file: (%s) ", ctrl_file);
+ goto open_ctrl_file_fail;
+ }
+ dev->ctrl_fd = ret;
+
+ dev->bar_len = pci_dev->mem_resource[0].len;
+ dev->bar_addr = mmap(NULL, dev->bar_len, PROT_READ | PROT_WRITE,
+ MAP_SHARED, dev->ctrl_fd, 0);
+ if (dev->bar_addr == MAP_FAILED) {
+ PMD_DRV_LOG(ERR, "Failed to mmap file: (%s) ", ctrl_file);
+ ret = -EINVAL;
+ goto mmap_fail;
+ }
+
+ return 0;
+
+mmap_fail:
+ close(dev->ctrl_fd);
+open_ctrl_file_fail:
+ ibv_dealloc_pd(dev->ibv_pd);
+alloc_pd_fail:
+ ibv_close_device(dev->ibv_ctx);
+
+ return ret;
+}
+
+static void
+xsc_dev_close(struct xsc_dev *dev)
+{
+ munmap(dev->bar_addr, dev->bar_len);
+ close(dev->ctrl_fd);
+ ibv_close_device(dev->ibv_ctx);
+}
+
+int
+xsc_dev_init(struct rte_pci_device *pci_dev, struct xsc_dev **dev)
+{
+ struct xsc_dev *d;
+ int ret;
+
+ PMD_INIT_FUNC_TRACE();
+
+ d = rte_zmalloc(NULL, sizeof(*d), RTE_CACHE_LINE_SIZE);
+ if (d == NULL) {
+ PMD_DRV_LOG(ERR, "Failed to alloc memory for xsc_dev");
+ return -ENOMEM;
+ }
+
+ xsc_dev_args_parse(d, pci_dev->device.devargs);
+
+ ret = xsc_dev_open(d, pci_dev);
+ if (ret) {
+ PMD_DRV_LOG(ERR, "Failed to open xsc device");
+ goto dev_open_fail;
+ }
+
+ d->pci_dev = pci_dev;
+ *dev = d;
+
+ return 0;
+
+dev_open_fail:
+ rte_free(d);
+ return ret;
+}
+
+void
+xsc_dev_uninit(struct xsc_dev *dev)
+{
+ PMD_INIT_FUNC_TRACE();
+
+ xsc_dev_close(dev);
+ rte_free(dev);
+}
new file mode 100644
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2024 Yunsilicon Technology Co., Ltd.
+ */
+
+#ifndef _XSC_DEV_H_
+#define _XSC_DEV_H_
+
+#include <infiniband/verbs.h>
+
+#define XSC_PPH_MODE_ARG "pph_mode"
+#define XSC_NIC_MODE_ARG "nic_mode"
+#define XSC_FLOW_MODE_ARG "flow_mode"
+
+struct xsc_devargs {
+ int nic_mode;
+ int flow_mode;
+ int pph_mode;
+};
+
+struct xsc_dev {
+ struct rte_pci_device *pci_dev;
+ struct xsc_devargs devargs;
+ struct ibv_context *ibv_ctx;
+ struct ibv_pd *ibv_pd;
+ char ibv_name[IBV_SYSFS_NAME_MAX];
+ void *bar_addr;
+ uint64_t bar_len;
+ int ctrl_fd;
+};
+
+int xsc_dev_init(struct rte_pci_device *pci_dev, struct xsc_dev **dev);
+void xsc_dev_uninit(struct xsc_dev *dev);
+
+#endif /* _XSC_DEV_H_ */
@@ -6,27 +6,38 @@
#include "xsc_log.h"
#include "xsc_defs.h"
+#include "xsc_dev.h"
#include "xsc_ethdev.h"
static int
xsc_ethdev_init(struct rte_eth_dev *eth_dev)
{
struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(eth_dev);
+ int ret;
PMD_INIT_FUNC_TRACE();
priv->eth_dev = eth_dev;
priv->pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
+ ret = xsc_dev_init(priv->pci_dev, &priv->xdev);
+ if (ret) {
+ PMD_DRV_LOG(ERR, "Failed to initialize xsc device");
+ return ret;
+ }
+
return 0;
}
static int
xsc_ethdev_uninit(struct rte_eth_dev *eth_dev)
{
- RTE_SET_USED(eth_dev);
+ struct xsc_ethdev_priv *priv = TO_XSC_ETHDEV_PRIV(eth_dev);
+
PMD_INIT_FUNC_TRACE();
+ xsc_dev_uninit(priv->xdev);
+
return 0;
}
@@ -75,8 +86,17 @@ static struct rte_pci_driver xsc_ethdev_pci_driver = {
.remove = xsc_ethdev_pci_remove,
};
+RTE_INIT(xsc_pmd_init)
+{
+ ibv_fork_init();
+}
+
RTE_PMD_REGISTER_PCI(net_xsc, xsc_ethdev_pci_driver);
RTE_PMD_REGISTER_PCI_TABLE(net_xsc, xsc_ethdev_pci_id_map);
+RTE_PMD_REGISTER_PARAM_STRING(net_xsc,
+ XSC_PPH_MODE_ARG "=<x>"
+ XSC_NIC_MODE_ARG "=<x>"
+ XSC_FLOW_MODE_ARG "=<x>");
RTE_LOG_REGISTER_SUFFIX(xsc_logtype_init, init, NOTICE);
RTE_LOG_REGISTER_SUFFIX(xsc_logtype_driver, driver, NOTICE);
@@ -8,6 +8,7 @@
struct xsc_ethdev_priv {
struct rte_eth_dev *eth_dev;
struct rte_pci_device *pci_dev;
+ struct xsc_dev *xdev;
};
#define TO_XSC_ETHDEV_PRIV(dev) \
new file mode 100644
@@ -0,0 +1,96 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2024 Yunsilicon Technology Co., Ltd.
+ */
+
+#include <stddef.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+#include "xsc_log.h"
+#include "xsc_utils.h"
+
+static int
+xsc_get_ibdev_pci_addr(const char *dev_path, struct rte_pci_addr *pci_addr)
+{
+ FILE *file;
+ char line[32];
+ char path[PATH_MAX];
+ int ret = -ENOENT;
+
+ sprintf(path, "%s/device/uevent", dev_path);
+
+ file = fopen(path, "rb");
+ if (file == NULL) {
+ PMD_DRV_LOG(ERR, "Failed to open file: (%s) ", path);
+ return ret;
+ }
+ while (fgets(line, sizeof(line), file) == line) {
+ size_t len = strlen(line);
+
+ /* Truncate long lines. */
+ if (len == (sizeof(line) - 1)) {
+ while (line[(len - 1)] != '\n') {
+ int n = fgetc(file);
+
+ if (n == EOF)
+ goto out;
+ line[(len - 1)] = n;
+ }
+ /* No match for long lines. */
+ continue;
+ }
+ /* Extract information. */
+ if (sscanf(line,
+ "PCI_SLOT_NAME=%04x:%hhx:%hhx.%hhx",
+ &pci_addr->domain,
+ &pci_addr->bus,
+ &pci_addr->devid,
+ &pci_addr->function) == 4) {
+ ret = 0;
+ break;
+ }
+ }
+out:
+ fclose(file);
+ return ret;
+}
+
+struct ibv_device *
+xsc_get_ibv_device(const struct rte_pci_addr *addr)
+{
+ int ibv_num, i;
+ struct ibv_device **ibv_list;
+ struct ibv_device *ibv_match = NULL;
+ struct rte_pci_addr ibv_pci_addr;
+
+ ibv_list = ibv_get_device_list(&ibv_num);
+ if (ibv_list == NULL)
+ return NULL;
+
+ for (i = 0; i < ibv_num; i++) {
+ if (xsc_get_ibdev_pci_addr(ibv_list[i]->ibdev_path, &ibv_pci_addr) != 0)
+ continue;
+ if (rte_pci_addr_cmp(addr, &ibv_pci_addr) != 0)
+ continue;
+ ibv_match = ibv_list[i];
+ PMD_DRV_LOG(DEBUG, "Finding device \"name:%s, %s, path:%s, %s\"..",
+ ibv_list[i]->name, ibv_list[i]->dev_name,
+ ibv_list[i]->dev_path, ibv_list[i]->ibdev_path);
+ break;
+ }
+ ibv_free_device_list(ibv_list);
+
+ if (ibv_match == NULL) {
+ PMD_DRV_LOG(WARNING,
+ "No Verbs device matches PCI device " PCI_PRI_FMT,
+ addr->domain, addr->bus, addr->devid, addr->function);
+ }
+
+ return ibv_match;
+}
new file mode 100644
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2024 Yunsilicon Technology Co., Ltd.
+ */
+
+#ifndef _XSC_UTILS_H_
+#define _XSC_UTILS_H_
+
+#include <infiniband/verbs.h>
+
+#include <ethdev_pci.h>
+
+struct ibv_device *xsc_get_ibv_device(const struct rte_pci_addr *addr);
+
+#endif /* _XSC_UTILS_H_ */