Skip to contentSkip to conversation

Introduce Microsoft Azure Network Adatper (MANA) PMD

PATCH Superseded [email protected] 5 participants 34 messages Aug 30, 2022 – Sep 7, 2022

Subsystems (2)

v6 of 10 Superseded Latest is v10 →

lore
Share & tools
lore
#0 lore raw

v6 cover Introduce Microsoft Azure Network Adatper (MANA) PMD

From: Long Li <[email protected]>

MANA is a network interface card to be used in the Azure cloud environment. MANA provides safe access to user memory through memory registration. It has IOMMU built into the hardware.

MANA uses IB verbs and RDMA layer to configure hardware resources. It requires the corresponding RDMA kernel-mode and user-mode drivers.

The MANA RDMA kernel-mode driver is being reviewed at:
https://patchwork.kernel.org/project/netdevbpf/cover/[email protected]/

The MANA RDMA user-mode driver is being reviewed at:
https://github.com/linux-rdma/rdma-core/pull/1177

Long Li (18):
net/mana: add basic driver, build environment and doc net/mana: add device configuration and stop net/mana: add function to report support ptypes net/mana: add link update
net/mana: add function for device removal interrupts net/mana: add device info
net/mana: add function to configure RSS net/mana: add function to configure RX queues net/mana: add function to configure TX queues net/mana: implement memory registration net/mana: implement the hardware layer operations net/mana: add function to start/stop TX queues net/mana: add function to start/stop RX queues net/mana: add function to receive packets net/mana: add function to send packets net/mana: add function to start/stop device net/mana: add function to report queue stats net/mana: add function to support RX interrupts

 MAINTAINERS                       |    6 +
 doc/guides/nics/features/mana.ini |   21 +
 doc/guides/nics/index.rst         |    1 +
 doc/guides/nics/mana.rst          |   66 ++
 drivers/net/mana/gdma.c           |  289 ++++++
 drivers/net/mana/mana.c           | 1449 +++++++++++++++++++++++++++++
 drivers/net/mana/mana.h           |  553 +++++++++++
 drivers/net/mana/meson.build      |   48 +
 drivers/net/mana/mp.c             |  323 +++++++
 drivers/net/mana/mr.c             |  324 +++++++
 drivers/net/mana/rx.c             |  519 +++++++++++
 drivers/net/mana/tx.c             |  405 ++++++++
 drivers/net/mana/version.map      |    3 +
 drivers/net/meson.build           |    1 +
 14 files changed, 4008 insertions(+)
 create mode 100644 doc/guides/nics/features/mana.ini
 create mode 100644 doc/guides/nics/mana.rst
 create mode 100644 drivers/net/mana/gdma.c
 create mode 100644 drivers/net/mana/mana.c
 create mode 100644 drivers/net/mana/mana.h
 create mode 100644 drivers/net/mana/meson.build
 create mode 100644 drivers/net/mana/mp.c
 create mode 100644 drivers/net/mana/mr.c
 create mode 100644 drivers/net/mana/rx.c
 create mode 100644 drivers/net/mana/tx.c
 create mode 100644 drivers/net/mana/version.map
Signature · 1 line
2.17.1
#1 lore raw

PATCH v6 1/18 net/mana: add basic driver, build environment and doc

From: Long Li <[email protected]>

MANA is a PCI device. It uses IB verbs to access hardware through the kernel RDMA layer. This patch introduces build environment and basic device probe functions.

---
Change log:
v2:
Fix typos.
Make the driver build only on x86-64 and Linux.
Remove unused header files.
Change port definition to uint16_t or uint8_t (for IB).
Use getline() in place of fgets() to read and truncate a line. v3:
Add meson build check for required functions from RDMA direct verb header file v4:
Remove extra "\n" in logging code.
Use "r" in place of "rb" in fopen() to read text files.

 MAINTAINERS                       |   6 +
 doc/guides/nics/features/mana.ini |  10 +
 doc/guides/nics/index.rst         |   1 +
 doc/guides/nics/mana.rst          |  66 +++
 drivers/net/mana/mana.c           | 704 ++++++++++++++++++++++++++++++
 drivers/net/mana/mana.h           | 210 +++++++++
 drivers/net/mana/meson.build      |  44 ++
 drivers/net/mana/mp.c             | 235 ++++++++++
 drivers/net/mana/version.map      |   3 +
 drivers/net/meson.build           |   1 +
 10 files changed, 1280 insertions(+)
 create mode 100644 doc/guides/nics/features/mana.ini
 create mode 100644 doc/guides/nics/mana.rst
 create mode 100644 drivers/net/mana/mana.c
 create mode 100644 drivers/net/mana/mana.h
 create mode 100644 drivers/net/mana/meson.build
 create mode 100644 drivers/net/mana/mp.c
 create mode 100644 drivers/net/mana/version.map
MAINTAINERS +6 -0
index 18d9edaf88..b8bda48a33 100644
@@ -837,6 +837,12 @@ F: buildtools/options-ibverbs-static.sh
 F: doc/guides/nics/mlx5.rst
 F: doc/guides/nics/features/mlx5.ini
 
+Microsoft mana
+M: Long Li <[email protected]>
+F: drivers/net/mana
+F: doc/guides/nics/mana.rst
+F: doc/guides/nics/features/mana.ini
+
 Microsoft vdev_netvsc - EXPERIMENTAL
 M: Matan Azrad <[email protected]>
 F: drivers/net/vdev_netvsc/
doc/guides/nics/features/mana.ini new file +10 -0
new file mode 100644
index 0000000000..b92a27374c
@@ -0,0 +1,10 @@
+;
+; Supported features of the 'mana' network poll mode driver.
+;
+; Refer to default.ini for the full list of available PMD features.
+;
+[Features]
+Linux                = Y
+Multiprocess aware   = Y
+Usage doc            = Y
+x86-64               = Y
doc/guides/nics/index.rst +1 -0
index 1c94caccea..2725d1d9f0 100644
@@ -41,6 +41,7 @@ Network Interface Controller Drivers
     intel_vf
     kni
     liquidio
+    mana
     memif
     mlx4
     mlx5
doc/guides/nics/mana.rst new file +66 -0

66 lines not on this page · raw message

drivers/net/mana/mana.c new file +704 -0

704 lines not on this page · raw message

drivers/net/mana/mana.h new file +210 -0

210 lines not on this page · raw message

drivers/net/mana/meson.build new file +44 -0

44 lines not on this page · raw message

drivers/net/mana/mp.c new file +235 -0

235 lines not on this page · raw message

drivers/net/mana/version.map new file +3 -0
new file mode 100644
index 0000000000..c2e0723b4c
@@ -0,0 +1,3 @@
+DPDK_22 {
+	local: *;
+};
drivers/net/meson.build +1 -0
index 2355d1cde8..0b111a6ebb 100644
@@ -34,6 +34,7 @@ drivers = [
         'ixgbe',
         'kni',
         'liquidio',
+        'mana',
         'memif',
         'mlx4',
         'mlx5',
Signature · 1 line
2.17.1
#2 lore raw

Re: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

Quoted 210 lines · 在 2022/8/31 6:51, [email protected] 写道:

From: Long Li <[email protected]>

MANA is a PCI device. It uses IB verbs to access hardware through the kernel RDMA layer. This patch introduces build environment and basic device probe functions.

---
Change log:
v2:
Fix typos.
Make the driver build only on x86-64 and Linux.
Remove unused header files.
Change port definition to uint16_t or uint8_t (for IB).
Use getline() in place of fgets() to read and truncate a line. v3:
Add meson build check for required functions from RDMA direct verb header file v4:
Remove extra "\n" in logging code.
Use "r" in place of "rb" in fopen() to read text files.

[snip]

drivers/net/mana/mana.c new file +188 -0
+
+static int mana_pci_probe_mac(struct rte_pci_driver *pci_drv __rte_unused,
+			      struct rte_pci_device *pci_dev,
+			      struct rte_ether_addr *mac_addr)
+{
+	struct ibv_device **ibv_list;
+	int ibv_idx;
+	struct ibv_context *ctx;
+	struct ibv_device_attr_ex dev_attr;
+	int num_devices;
+	int ret = 0;
+	uint8_t port;
+	struct mana_priv *priv = NULL;
+	struct rte_eth_dev *eth_dev = NULL;
+	bool found_port;
+
+	ibv_list = ibv_get_device_list(&num_devices);
+	for (ibv_idx = 0; ibv_idx < num_devices; ibv_idx++) {
+		struct ibv_device *ibdev = ibv_list[ibv_idx];
+		struct rte_pci_addr pci_addr;
+
+		DRV_LOG(INFO, "Probe device name %s dev_name %s ibdev_path %s",
+			ibdev->name, ibdev->dev_name, ibdev->ibdev_path);
+
+		if (mana_ibv_device_to_pci_addr(ibdev, &pci_addr))
+			continue;
+
+		/* Ignore if this IB device is not this PCI device */
+		if (pci_dev->addr.domain != pci_addr.domain ||
+		    pci_dev->addr.bus != pci_addr.bus ||
+		    pci_dev->addr.devid != pci_addr.devid ||
+		    pci_dev->addr.function != pci_addr.function)
+			continue;
+
+		ctx = ibv_open_device(ibdev);
+		if (!ctx) {
+			DRV_LOG(ERR, "Failed to open IB device %s",
+				ibdev->name);
+			continue;
+		}
+
+		ret = ibv_query_device_ex(ctx, NULL, &dev_attr);
+		DRV_LOG(INFO, "dev_attr.orig_attr.phys_port_cnt %u",
+			dev_attr.orig_attr.phys_port_cnt);
+		found_port = false;
+
+		for (port = 1; port <= dev_attr.orig_attr.phys_port_cnt;
+		     port++) {
+			struct ibv_parent_domain_init_attr attr = {};
+			struct rte_ether_addr addr;
+			char address[64];
+			char name[RTE_ETH_NAME_MAX_LEN];
+
+			ret = get_port_mac(ibdev, port, &addr);
+			if (ret)
+				continue;
+
+			if (mac_addr && !rte_is_same_ether_addr(&addr, mac_addr))
+				continue;
+
+			rte_ether_format_addr(address, sizeof(address), &addr);
+			DRV_LOG(INFO, "device located port %u address %s",
+				port, address);
+			found_port = true;
+
+			priv = rte_zmalloc_socket(NULL, sizeof(*priv),
+						  RTE_CACHE_LINE_SIZE,
+						  SOCKET_ID_ANY);
+			if (!priv) {
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			snprintf(name, sizeof(name), "%s_port%d",
+				 pci_dev->device.name, port);
+
+			if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
+				int fd;
+
+				eth_dev = rte_eth_dev_attach_secondary(name);
+				if (!eth_dev) {
+					DRV_LOG(ERR, "Can't attach to dev %s",
+						name);
+					ret = -ENOMEM;
+					goto failed;
+				}
+
+				eth_dev->device = &pci_dev->device;
+				eth_dev->dev_ops = &mana_dev_sec_ops;
+				ret = mana_proc_priv_init(eth_dev);
+				if (ret)
+					goto failed;
+				priv->process_priv = eth_dev->process_private;
+
+				/* Get the IB FD from the primary process */
+				fd = mana_mp_req_verbs_cmd_fd(eth_dev);
+				if (fd < 0) {
+					DRV_LOG(ERR, "Failed to get FD %d", fd);
+					ret = -ENODEV;
+					goto failed;
+				}
+
+				ret = mana_map_doorbell_secondary(eth_dev, fd);
+				if (ret) {
+					DRV_LOG(ERR, "Failed secondary map %d",
+						fd);
+					goto failed;
+				}
+
+				/* fd is no not used after mapping doorbell */
+				close(fd);
+
+				rte_spinlock_lock(&mana_shared_data->lock);
+				mana_shared_data->secondary_cnt++;
+				mana_local_data.secondary_cnt++;
+				rte_spinlock_unlock(&mana_shared_data->lock);
+
+				rte_eth_copy_pci_info(eth_dev, pci_dev);
+				rte_eth_dev_probing_finish(eth_dev);
+
+				/* Impossible to have more than one port
+				 * matching a MAC address
+				 */
+				continue;
+			}
+
+			eth_dev = rte_eth_dev_allocate(name);
+			if (!eth_dev) {
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			eth_dev->data->mac_addrs =
+				rte_calloc("mana_mac", 1,
+					   sizeof(struct rte_ether_addr), 0);
+			if (!eth_dev->data->mac_addrs) {
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			rte_ether_addr_copy(&addr, eth_dev->data->mac_addrs);
+
+			priv->ib_pd = ibv_alloc_pd(ctx);
+			if (!priv->ib_pd) {
+				DRV_LOG(ERR, "ibv_alloc_pd failed port %d", port);
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			/* Create a parent domain with the port number */
+			attr.pd = priv->ib_pd;
+			attr.comp_mask = IBV_PARENT_DOMAIN_INIT_ATTR_PD_CONTEXT;
+			attr.pd_context = (void *)(uint64_t)port;
+			priv->ib_parent_pd = ibv_alloc_parent_domain(ctx, &attr);
+			if (!priv->ib_parent_pd) {
+				DRV_LOG(ERR,
+					"ibv_alloc_parent_domain failed port %d",
+					port);
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			priv->ib_ctx = ctx;
+			priv->port_id = eth_dev->data->port_id;
+			priv->dev_port = port;
+			eth_dev->data->dev_private = priv;
+			priv->dev_data = eth_dev->data;
+
+			priv->max_rx_queues = dev_attr.orig_attr.max_qp;
+			priv->max_tx_queues = dev_attr.orig_attr.max_qp;
+
+			priv->max_rx_desc =
+				RTE_MIN(dev_attr.orig_attr.max_qp_wr,
+					dev_attr.orig_attr.max_cqe);
+			priv->max_tx_desc =
+				RTE_MIN(dev_attr.orig_attr.max_qp_wr,
+					dev_attr.orig_attr.max_cqe);
+
+			priv->max_send_sge = dev_attr.orig_attr.max_sge;
+			priv->max_recv_sge = dev_attr.orig_attr.max_sge;
+
+			priv->max_mr = dev_attr.orig_attr.max_mr;
+			priv->max_mr_size = dev_attr.orig_attr.max_mr_size;
+
+			DRV_LOG(INFO, "dev %s max queues %d desc %d sge %d",
+				name, priv->max_rx_queues, priv->max_rx_desc,
+				priv->max_send_sge);
+

drivers/net/mana/mana.c line 547

Quoted 10 lines
drivers/net/mana/mana.c new file +10 -0
+			rte_spinlock_lock(&mana_shared_data->lock);
+			mana_shared_data->primary_cnt++;
+			rte_spinlock_unlock(&mana_shared_data->lock);
+
+			eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_RMV;
+
+			eth_dev->device = &pci_dev->device;
+			eth_dev->data->dev_flags |=
+				RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
+

Please do not use the temporary macro. Please review this patch:

f30e69b41f94 ("ethdev: add device flag to bypass auto-filled queue xstats")

This patch requires that per queue statistics are filled in .xstats_get() by PMD.

Quoted 45 lines
drivers/net/mana/mana.c new file +43 -0
+			DRV_LOG(INFO, "device %s at port %u",
+				name, eth_dev->data->port_id);
+
+			eth_dev->rx_pkt_burst = mana_rx_burst_removed;
+			eth_dev->tx_pkt_burst = mana_tx_burst_removed;
+			eth_dev->dev_ops = &mana_dev_ops;
+
+			rte_eth_copy_pci_info(eth_dev, pci_dev);
+			rte_eth_dev_probing_finish(eth_dev);
+		}
+
+		/* Secondary process doesn't need an ibv_ctx. It maps the
+		 * doorbell pages using the IB cmd_fd passed from the primary
+		 * process and send messages to primary process for memory
+		 * registartions.
+		 */
+		if (!found_port || rte_eal_process_type() == RTE_PROC_SECONDARY)
+			ibv_close_device(ctx);
+	}
+
+	ibv_free_device_list(ibv_list);
+	return 0;
+
+failed:
+	/* Free the resource for the port failed */
+	if (priv) {
+		if (priv->ib_parent_pd)
+			ibv_dealloc_pd(priv->ib_parent_pd);
+
+		if (priv->ib_pd)
+			ibv_dealloc_pd(priv->ib_pd);
+	}
+
+	if (eth_dev)
+		rte_eth_dev_release_port(eth_dev);
+
+	rte_free(priv);
+
+	ibv_close_device(ctx);
+	ibv_free_device_list(ibv_list);
+
+	return ret;
+}
[snip]
#3 lore raw

RE: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

Quoted 253 lines

Subject: Re: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

Quoted 23 lines · 在 2022/8/31 6:51, [email protected] 写道:

From: Long Li <[email protected]>

MANA is a PCI device. It uses IB verbs to access hardware through the kernel RDMA layer. This patch introduces build environment and basic device probe functions.

---
Change log:
v2:
Fix typos.
Make the driver build only on x86-64 and Linux.
Remove unused header files.
Change port definition to uint16_t or uint8_t (for IB). Use getline() in place of fgets() to read and truncate a line. v3:
Add meson build check for required functions from RDMA direct verb header file
v4:
Remove extra "\n" in logging code.
Use "r" in place of "rb" in fopen() to read text files.

[snip]

Review

Quoted 2 lines
(quoted diff) +2 -0
+
+static int mana_pci_probe_mac(struct rte_pci_driver *pci_drv

__rte_unused,

Quoted 9 lines
drivers/net/mana/mana.c new file +9 -0
+			      struct rte_pci_device *pci_dev,
+			      struct rte_ether_addr *mac_addr) {
+	struct ibv_device **ibv_list;
+	int ibv_idx;
+	struct ibv_context *ctx;
+	struct ibv_device_attr_ex dev_attr;
+	int num_devices;
+	int ret = 0;
+	uint8_t port;

drivers/net/mana/mana.c

Quoted 10 lines
drivers/net/mana/mana.c new file +10 -0
+	struct mana_priv *priv = NULL;
+	struct rte_eth_dev *eth_dev = NULL;
+	bool found_port;
+
+	ibv_list = ibv_get_device_list(&num_devices);
+	for (ibv_idx = 0; ibv_idx < num_devices; ibv_idx++) {
+		struct ibv_device *ibdev = ibv_list[ibv_idx];
+		struct rte_pci_addr pci_addr;
+
+		DRV_LOG(INFO, "Probe device name %s dev_name %s

ibdev_path %s",

Quoted 27 lines
(quoted diff) +1 -0
+			ibdev->name, ibdev->dev_name, ibdev-

ibdev_path);

drivers/net/mana/mana.c new file +25 -0
+
+		if (mana_ibv_device_to_pci_addr(ibdev, &pci_addr))
+			continue;
+
+		/* Ignore if this IB device is not this PCI device */
+		if (pci_dev->addr.domain != pci_addr.domain ||
+		    pci_dev->addr.bus != pci_addr.bus ||
+		    pci_dev->addr.devid != pci_addr.devid ||
+		    pci_dev->addr.function != pci_addr.function)
+			continue;
+
+		ctx = ibv_open_device(ibdev);
+		if (!ctx) {
+			DRV_LOG(ERR, "Failed to open IB device %s",
+				ibdev->name);
+			continue;
+		}
+
+		ret = ibv_query_device_ex(ctx, NULL, &dev_attr);
+		DRV_LOG(INFO, "dev_attr.orig_attr.phys_port_cnt %u",
+			dev_attr.orig_attr.phys_port_cnt);
+		found_port = false;
+
+		for (port = 1; port <= dev_attr.orig_attr.phys_port_cnt;
+		     port++) {

drivers/net/mana/mana.c

Quoted 10 lines
drivers/net/mana/mana.c new file +10 -0
+			struct ibv_parent_domain_init_attr attr = {};
+			struct rte_ether_addr addr;
+			char address[64];
+			char name[RTE_ETH_NAME_MAX_LEN];
+
+			ret = get_port_mac(ibdev, port, &addr);
+			if (ret)
+				continue;
+
+			if (mac_addr && !rte_is_same_ether_addr(&addr,

mac_addr))

drivers/net/mana/mana.c

Quoted 3 lines
drivers/net/mana/mana.c new file +3 -0
+				continue;
+
+			rte_ether_format_addr(address, sizeof(address),

&addr);

Review

Quoted 1 line
(quoted diff) +1 -0
+			DRV_LOG(INFO, "device located port %u address

%s",

Quoted 5 lines
drivers/net/mana/mana.c new file +5 -0
+				port, address);
+			found_port = true;
+
+			priv = rte_zmalloc_socket(NULL, sizeof(*priv),
+						  RTE_CACHE_LINE_SIZE,

drivers/net/mana/mana.c

Quoted 10 lines
drivers/net/mana/mana.c new file +10 -0
+						  SOCKET_ID_ANY);
+			if (!priv) {
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			snprintf(name, sizeof(name), "%s_port%d",
+				 pci_dev->device.name, port);
+
+			if (rte_eal_process_type() ==

RTE_PROC_SECONDARY) {

drivers/net/mana/mana.c

Quoted 3 lines
drivers/net/mana/mana.c new file +3 -0
+				int fd;
+
+				eth_dev =

rte_eth_dev_attach_secondary(name);

Review

Quoted 2 lines
(quoted diff) +2 -0
+				if (!eth_dev) {
+					DRV_LOG(ERR, "Can't attach to dev

%s",

Quoted 12 lines
drivers/net/mana/mana.c new file +11 -0
+						name);
+					ret = -ENOMEM;
+					goto failed;
+				}
+
+				eth_dev->device = &pci_dev->device;
+				eth_dev->dev_ops = &mana_dev_sec_ops;
+				ret = mana_proc_priv_init(eth_dev);
+				if (ret)
+					goto failed;
+				priv->process_priv = eth_dev-

process_private;

drivers/net/mana/mana.c

Quoted 3 lines
drivers/net/mana/mana.c new file +3 -0
+
+				/* Get the IB FD from the primary process */
+				fd =

mana_mp_req_verbs_cmd_fd(eth_dev);

Review

Quoted 2 lines
(quoted diff) +2 -0
+				if (fd < 0) {
+					DRV_LOG(ERR, "Failed to get FD %d",

fd);

drivers/net/mana/mana.c

Quoted 5 lines
drivers/net/mana/mana.c new file +5 -0
+					ret = -ENODEV;
+					goto failed;
+				}
+
+				ret =

mana_map_doorbell_secondary(eth_dev, fd);

Review

Quoted 2 lines
(quoted diff) +2 -0
+				if (ret) {
+					DRV_LOG(ERR, "Failed secondary

map %d",

Quoted 39 lines
drivers/net/mana/mana.c new file +8 -0
+						fd);
+					goto failed;
+				}
+
+				/* fd is no not used after mapping doorbell */
+				close(fd);
+
+				rte_spinlock_lock(&mana_shared_data-

lock);

drivers/net/mana/mana.c new file +3 -0
+				mana_shared_data->secondary_cnt++;
+				mana_local_data.secondary_cnt++;
+				rte_spinlock_unlock(&mana_shared_data-

lock);

drivers/net/mana/mana.c new file +25 -0
+
+				rte_eth_copy_pci_info(eth_dev, pci_dev);
+				rte_eth_dev_probing_finish(eth_dev);
+
+				/* Impossible to have more than one port
+				 * matching a MAC address
+				 */
+				continue;
+			}
+
+			eth_dev = rte_eth_dev_allocate(name);
+			if (!eth_dev) {
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			eth_dev->data->mac_addrs =
+				rte_calloc("mana_mac", 1,
+					   sizeof(struct rte_ether_addr), 0);
+			if (!eth_dev->data->mac_addrs) {
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			rte_ether_addr_copy(&addr, eth_dev->data-

mac_addrs);

drivers/net/mana/mana.c

Quoted 4 lines
drivers/net/mana/mana.c new file +4 -0
+
+			priv->ib_pd = ibv_alloc_pd(ctx);
+			if (!priv->ib_pd) {
+				DRV_LOG(ERR, "ibv_alloc_pd failed port %d",

port);

drivers/net/mana/mana.c

Quoted 7 lines
drivers/net/mana/mana.c new file +7 -0
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			/* Create a parent domain with the port number */
+			attr.pd = priv->ib_pd;
+			attr.comp_mask =

IBV_PARENT_DOMAIN_INIT_ATTR_PD_CONTEXT;

Review

Quoted 2 lines
(quoted diff) +2 -0
+			attr.pd_context = (void *)(uint64_t)port;
+			priv->ib_parent_pd = ibv_alloc_parent_domain(ctx,

&attr);

drivers/net/mana/mana.c

Quoted 3 lines
drivers/net/mana/mana.c new file +3 -0
+			if (!priv->ib_parent_pd) {
+				DRV_LOG(ERR,
+					"ibv_alloc_parent_domain failed port

%d",

Quoted 16 lines
drivers/net/mana/mana.c new file +16 -0
+					port);
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			priv->ib_ctx = ctx;
+			priv->port_id = eth_dev->data->port_id;
+			priv->dev_port = port;
+			eth_dev->data->dev_private = priv;
+			priv->dev_data = eth_dev->data;
+
+			priv->max_rx_queues = dev_attr.orig_attr.max_qp;
+			priv->max_tx_queues = dev_attr.orig_attr.max_qp;
+
+			priv->max_rx_desc =
+				RTE_MIN(dev_attr.orig_attr.max_qp_wr,

drivers/net/mana/mana.c

Quoted 10 lines
drivers/net/mana/mana.c new file +10 -0
+					dev_attr.orig_attr.max_cqe);
+			priv->max_tx_desc =
+				RTE_MIN(dev_attr.orig_attr.max_qp_wr,
+					dev_attr.orig_attr.max_cqe);
+
+			priv->max_send_sge = dev_attr.orig_attr.max_sge;
+			priv->max_recv_sge = dev_attr.orig_attr.max_sge;
+
+			priv->max_mr = dev_attr.orig_attr.max_mr;
+			priv->max_mr_size =

dev_attr.orig_attr.max_mr_size;

Review

Quoted 2 lines
(quoted diff) +2 -0
+
+			DRV_LOG(INFO, "dev %s max queues %d desc %d

sge %d",

drivers/net/mana/mana.c line 545

Quoted 9 lines
(quoted diff) +1 -0
+				name, priv->max_rx_queues, priv-

max_rx_desc,

drivers/net/mana/mana.c new file +7 -0
+				priv->max_send_sge);
+
+			rte_spinlock_lock(&mana_shared_data->lock);
+			mana_shared_data->primary_cnt++;
+			rte_spinlock_unlock(&mana_shared_data->lock);
+
+			eth_dev->data->dev_flags |=

RTE_ETH_DEV_INTR_RMV;

drivers/net/mana/mana.c line 547

Quoted 5 lines
drivers/net/mana/mana.c new file +5 -0
+
+			eth_dev->device = &pci_dev->device;
+			eth_dev->data->dev_flags |=
+				RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
+

Please do not use the temporary macro. Please review this patch:

Quoted 4 lines

f30e69b41f94 ("ethdev: add device flag to bypass auto-filled queue xstats")

This patch requires that per queue statistics are filled in .xstats_get() by PMD.

Thanks for pointing this out.

It seems some PMDs are still depending on this flag for xstats.

MANA doesn't implement xstats_get() currently, this flag is useful. Is it okay to keep using this flag before it's finally the time to remove it from all PMDs, or when MANA implements xstats?

#4 lore raw

Re: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

Quoted 254 lines · Long Li
Quoted 254 lines

Subject: Re: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

Quoted 23 lines · 在 2022/8/31 6:51, [email protected] 写道:

From: Long Li <[email protected]>

MANA is a PCI device. It uses IB verbs to access hardware through the kernel RDMA layer. This patch introduces build environment and basic device probe functions.

---
Change log:
v2:
Fix typos.
Make the driver build only on x86-64 and Linux.
Remove unused header files.
Change port definition to uint16_t or uint8_t (for IB). Use getline() in place of fgets() to read and truncate a line. v3:
Add meson build check for required functions from RDMA direct verb header file
v4:
Remove extra "\n" in logging code.
Use "r" in place of "rb" in fopen() to read text files.

[snip]

Review

Quoted 2 lines
(quoted diff) +2 -0
+
+static int mana_pci_probe_mac(struct rte_pci_driver *pci_drv

__rte_unused,

Quoted 9 lines
drivers/net/mana/mana.c new file +9 -0
+			      struct rte_pci_device *pci_dev,
+			      struct rte_ether_addr *mac_addr) {
+	struct ibv_device **ibv_list;
+	int ibv_idx;
+	struct ibv_context *ctx;
+	struct ibv_device_attr_ex dev_attr;
+	int num_devices;
+	int ret = 0;
+	uint8_t port;

drivers/net/mana/mana.c

Quoted 10 lines
drivers/net/mana/mana.c new file +10 -0
+	struct mana_priv *priv = NULL;
+	struct rte_eth_dev *eth_dev = NULL;
+	bool found_port;
+
+	ibv_list = ibv_get_device_list(&num_devices);
+	for (ibv_idx = 0; ibv_idx < num_devices; ibv_idx++) {
+		struct ibv_device *ibdev = ibv_list[ibv_idx];
+		struct rte_pci_addr pci_addr;
+
+		DRV_LOG(INFO, "Probe device name %s dev_name %s

ibdev_path %s",

Quoted 27 lines
(quoted diff) +1 -0
+			ibdev->name, ibdev->dev_name, ibdev-

ibdev_path);

drivers/net/mana/mana.c new file +25 -0
+
+		if (mana_ibv_device_to_pci_addr(ibdev, &pci_addr))
+			continue;
+
+		/* Ignore if this IB device is not this PCI device */
+		if (pci_dev->addr.domain != pci_addr.domain ||
+		    pci_dev->addr.bus != pci_addr.bus ||
+		    pci_dev->addr.devid != pci_addr.devid ||
+		    pci_dev->addr.function != pci_addr.function)
+			continue;
+
+		ctx = ibv_open_device(ibdev);
+		if (!ctx) {
+			DRV_LOG(ERR, "Failed to open IB device %s",
+				ibdev->name);
+			continue;
+		}
+
+		ret = ibv_query_device_ex(ctx, NULL, &dev_attr);
+		DRV_LOG(INFO, "dev_attr.orig_attr.phys_port_cnt %u",
+			dev_attr.orig_attr.phys_port_cnt);
+		found_port = false;
+
+		for (port = 1; port <= dev_attr.orig_attr.phys_port_cnt;
+		     port++) {

drivers/net/mana/mana.c

Quoted 10 lines
drivers/net/mana/mana.c new file +10 -0
+			struct ibv_parent_domain_init_attr attr = {};
+			struct rte_ether_addr addr;
+			char address[64];
+			char name[RTE_ETH_NAME_MAX_LEN];
+
+			ret = get_port_mac(ibdev, port, &addr);
+			if (ret)
+				continue;
+
+			if (mac_addr && !rte_is_same_ether_addr(&addr,

mac_addr))

drivers/net/mana/mana.c

Quoted 3 lines
drivers/net/mana/mana.c new file +3 -0
+				continue;
+
+			rte_ether_format_addr(address, sizeof(address),

&addr);

Review

Quoted 1 line
(quoted diff) +1 -0
+			DRV_LOG(INFO, "device located port %u address

%s",

Quoted 5 lines
drivers/net/mana/mana.c new file +5 -0
+				port, address);
+			found_port = true;
+
+			priv = rte_zmalloc_socket(NULL, sizeof(*priv),
+						  RTE_CACHE_LINE_SIZE,

drivers/net/mana/mana.c

Quoted 10 lines
drivers/net/mana/mana.c new file +10 -0
+						  SOCKET_ID_ANY);
+			if (!priv) {
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			snprintf(name, sizeof(name), "%s_port%d",
+				 pci_dev->device.name, port);
+
+			if (rte_eal_process_type() ==

RTE_PROC_SECONDARY) {

drivers/net/mana/mana.c

Quoted 3 lines
drivers/net/mana/mana.c new file +3 -0
+				int fd;
+
+				eth_dev =

rte_eth_dev_attach_secondary(name);

Review

Quoted 2 lines
(quoted diff) +2 -0
+				if (!eth_dev) {
+					DRV_LOG(ERR, "Can't attach to dev

%s",

Quoted 12 lines
drivers/net/mana/mana.c new file +11 -0
+						name);
+					ret = -ENOMEM;
+					goto failed;
+				}
+
+				eth_dev->device = &pci_dev->device;
+				eth_dev->dev_ops = &mana_dev_sec_ops;
+				ret = mana_proc_priv_init(eth_dev);
+				if (ret)
+					goto failed;
+				priv->process_priv = eth_dev-

process_private;

drivers/net/mana/mana.c

Quoted 3 lines
drivers/net/mana/mana.c new file +3 -0
+
+				/* Get the IB FD from the primary process */
+				fd =

mana_mp_req_verbs_cmd_fd(eth_dev);

Review

Quoted 2 lines
(quoted diff) +2 -0
+				if (fd < 0) {
+					DRV_LOG(ERR, "Failed to get FD %d",

fd);

drivers/net/mana/mana.c

Quoted 5 lines
drivers/net/mana/mana.c new file +5 -0
+					ret = -ENODEV;
+					goto failed;
+				}
+
+				ret =

mana_map_doorbell_secondary(eth_dev, fd);

Review

Quoted 2 lines
(quoted diff) +2 -0
+				if (ret) {
+					DRV_LOG(ERR, "Failed secondary

map %d",

Quoted 39 lines
drivers/net/mana/mana.c new file +8 -0
+						fd);
+					goto failed;
+				}
+
+				/* fd is no not used after mapping doorbell */
+				close(fd);
+
+				rte_spinlock_lock(&mana_shared_data-

lock);

drivers/net/mana/mana.c new file +3 -0
+				mana_shared_data->secondary_cnt++;
+				mana_local_data.secondary_cnt++;
+				rte_spinlock_unlock(&mana_shared_data-

lock);

drivers/net/mana/mana.c new file +25 -0
+
+				rte_eth_copy_pci_info(eth_dev, pci_dev);
+				rte_eth_dev_probing_finish(eth_dev);
+
+				/* Impossible to have more than one port
+				 * matching a MAC address
+				 */
+				continue;
+			}
+
+			eth_dev = rte_eth_dev_allocate(name);
+			if (!eth_dev) {
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			eth_dev->data->mac_addrs =
+				rte_calloc("mana_mac", 1,
+					   sizeof(struct rte_ether_addr), 0);
+			if (!eth_dev->data->mac_addrs) {
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			rte_ether_addr_copy(&addr, eth_dev->data-

mac_addrs);

drivers/net/mana/mana.c

Quoted 4 lines
drivers/net/mana/mana.c new file +4 -0
+
+			priv->ib_pd = ibv_alloc_pd(ctx);
+			if (!priv->ib_pd) {
+				DRV_LOG(ERR, "ibv_alloc_pd failed port %d",

port);

drivers/net/mana/mana.c

Quoted 7 lines
drivers/net/mana/mana.c new file +7 -0
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			/* Create a parent domain with the port number */
+			attr.pd = priv->ib_pd;
+			attr.comp_mask =

IBV_PARENT_DOMAIN_INIT_ATTR_PD_CONTEXT;

Review

Quoted 2 lines
(quoted diff) +2 -0
+			attr.pd_context = (void *)(uint64_t)port;
+			priv->ib_parent_pd = ibv_alloc_parent_domain(ctx,

&attr);

drivers/net/mana/mana.c

Quoted 3 lines
drivers/net/mana/mana.c new file +3 -0
+			if (!priv->ib_parent_pd) {
+				DRV_LOG(ERR,
+					"ibv_alloc_parent_domain failed port

%d",

Quoted 16 lines
drivers/net/mana/mana.c new file +16 -0
+					port);
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			priv->ib_ctx = ctx;
+			priv->port_id = eth_dev->data->port_id;
+			priv->dev_port = port;
+			eth_dev->data->dev_private = priv;
+			priv->dev_data = eth_dev->data;
+
+			priv->max_rx_queues = dev_attr.orig_attr.max_qp;
+			priv->max_tx_queues = dev_attr.orig_attr.max_qp;
+
+			priv->max_rx_desc =
+				RTE_MIN(dev_attr.orig_attr.max_qp_wr,

drivers/net/mana/mana.c

Quoted 10 lines
drivers/net/mana/mana.c new file +10 -0
+					dev_attr.orig_attr.max_cqe);
+			priv->max_tx_desc =
+				RTE_MIN(dev_attr.orig_attr.max_qp_wr,
+					dev_attr.orig_attr.max_cqe);
+
+			priv->max_send_sge = dev_attr.orig_attr.max_sge;
+			priv->max_recv_sge = dev_attr.orig_attr.max_sge;
+
+			priv->max_mr = dev_attr.orig_attr.max_mr;
+			priv->max_mr_size =

dev_attr.orig_attr.max_mr_size;

Review

Quoted 2 lines
(quoted diff) +2 -0
+
+			DRV_LOG(INFO, "dev %s max queues %d desc %d

sge %d",

drivers/net/mana/mana.c line 545

Quoted 9 lines
(quoted diff) +1 -0
+				name, priv->max_rx_queues, priv-

max_rx_desc,

drivers/net/mana/mana.c new file +7 -0
+				priv->max_send_sge);
+
+			rte_spinlock_lock(&mana_shared_data->lock);
+			mana_shared_data->primary_cnt++;
+			rte_spinlock_unlock(&mana_shared_data->lock);
+
+			eth_dev->data->dev_flags |=

RTE_ETH_DEV_INTR_RMV;

drivers/net/mana/mana.c line 547

Quoted 5 lines
drivers/net/mana/mana.c new file +5 -0
+
+			eth_dev->device = &pci_dev->device;
+			eth_dev->data->dev_flags |=
+				RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
+

Please do not use the temporary macro. Please review this patch:

f30e69b41f94 ("ethdev: add device flag to bypass auto-filled queue xstats")

Quoted 7 lines
Quoted 2 lines

This patch requires that per queue statistics are filled in .xstats_get() by PMD.

Thanks for pointing this out.

It seems some PMDs are still depending on this flag for xstats.

MANA doesn't implement xstats_get() currently, this flag is useful. Is it okay to keep using this flag before it's finally the time to remove it from all PMDs, or when MANA implements xstats?

Yes, your xstats doesn't implement now. Per queue stats should be filled in xstats API, and the stats API cannot see per queue stats, so stats API in driver shouldn't fill it(suggest that delete it from patch 17/18).

I guess this flag can be removed if PMD does not support xstats.

Quoted 2 lines
#5 lore raw

RE: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

Quoted 266 lines

Subject: Re: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

Quoted 261 lines · Long Li
Quoted 252 lines

Subject: Re: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

Quoted 23 lines · 在 2022/8/31 6:51, [email protected] 写道:

From: Long Li <[email protected]>

MANA is a PCI device. It uses IB verbs to access hardware through the kernel RDMA layer. This patch introduces build environment and basic device probe functions.

---
Change log:
v2:
Fix typos.
Make the driver build only on x86-64 and Linux.
Remove unused header files.
Change port definition to uint16_t or uint8_t (for IB). Use getline() in place of fgets() to read and truncate a line. v3:
Add meson build check for required functions from RDMA direct verb header file
v4:
Remove extra "\n" in logging code.
Use "r" in place of "rb" in fopen() to read text files.

[snip]

Review

Quoted 2 lines
(quoted diff) +2 -0
+
+static int mana_pci_probe_mac(struct rte_pci_driver *pci_drv

__rte_unused,

Quoted 9 lines
drivers/net/mana/mana.c new file +9 -0
+			      struct rte_pci_device *pci_dev,
+			      struct rte_ether_addr *mac_addr) {
+	struct ibv_device **ibv_list;
+	int ibv_idx;
+	struct ibv_context *ctx;
+	struct ibv_device_attr_ex dev_attr;
+	int num_devices;
+	int ret = 0;
+	uint8_t port;

drivers/net/mana/mana.c

Quoted 10 lines
drivers/net/mana/mana.c new file +10 -0
+	struct mana_priv *priv = NULL;
+	struct rte_eth_dev *eth_dev = NULL;
+	bool found_port;
+
+	ibv_list = ibv_get_device_list(&num_devices);
+	for (ibv_idx = 0; ibv_idx < num_devices; ibv_idx++) {
+		struct ibv_device *ibdev = ibv_list[ibv_idx];
+		struct rte_pci_addr pci_addr;
+
+		DRV_LOG(INFO, "Probe device name %s dev_name %s

ibdev_path %s",

Quoted 27 lines
(quoted diff) +1 -0
+			ibdev->name, ibdev->dev_name, ibdev-

ibdev_path);

drivers/net/mana/mana.c new file +25 -0
+
+		if (mana_ibv_device_to_pci_addr(ibdev, &pci_addr))
+			continue;
+
+		/* Ignore if this IB device is not this PCI device */
+		if (pci_dev->addr.domain != pci_addr.domain ||
+		    pci_dev->addr.bus != pci_addr.bus ||
+		    pci_dev->addr.devid != pci_addr.devid ||
+		    pci_dev->addr.function != pci_addr.function)
+			continue;
+
+		ctx = ibv_open_device(ibdev);
+		if (!ctx) {
+			DRV_LOG(ERR, "Failed to open IB device %s",
+				ibdev->name);
+			continue;
+		}
+
+		ret = ibv_query_device_ex(ctx, NULL, &dev_attr);
+		DRV_LOG(INFO, "dev_attr.orig_attr.phys_port_cnt %u",
+			dev_attr.orig_attr.phys_port_cnt);
+		found_port = false;
+
+		for (port = 1; port <= dev_attr.orig_attr.phys_port_cnt;
+		     port++) {

drivers/net/mana/mana.c

Quoted 10 lines
drivers/net/mana/mana.c new file +10 -0
+			struct ibv_parent_domain_init_attr attr = {};
+			struct rte_ether_addr addr;
+			char address[64];
+			char name[RTE_ETH_NAME_MAX_LEN];
+
+			ret = get_port_mac(ibdev, port, &addr);
+			if (ret)
+				continue;
+
+			if (mac_addr && !rte_is_same_ether_addr(&addr,

mac_addr))

drivers/net/mana/mana.c

Quoted 3 lines
drivers/net/mana/mana.c new file +3 -0
+				continue;
+
+			rte_ether_format_addr(address, sizeof(address),

&addr);

Review

Quoted 1 line
(quoted diff) +1 -0
+			DRV_LOG(INFO, "device located port %u address

%s",

Quoted 5 lines
drivers/net/mana/mana.c new file +5 -0
+				port, address);
+			found_port = true;
+
+			priv = rte_zmalloc_socket(NULL, sizeof(*priv),
+						  RTE_CACHE_LINE_SIZE,

drivers/net/mana/mana.c

Quoted 10 lines
drivers/net/mana/mana.c new file +10 -0
+						  SOCKET_ID_ANY);
+			if (!priv) {
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			snprintf(name, sizeof(name), "%s_port%d",
+				 pci_dev->device.name, port);
+
+			if (rte_eal_process_type() ==

RTE_PROC_SECONDARY) {

drivers/net/mana/mana.c

Quoted 3 lines
drivers/net/mana/mana.c new file +3 -0
+				int fd;
+
+				eth_dev =

rte_eth_dev_attach_secondary(name);

Review

Quoted 2 lines
(quoted diff) +2 -0
+				if (!eth_dev) {
+					DRV_LOG(ERR, "Can't attach to dev

%s",

Quoted 12 lines
drivers/net/mana/mana.c new file +11 -0
+						name);
+					ret = -ENOMEM;
+					goto failed;
+				}
+
+				eth_dev->device = &pci_dev->device;
+				eth_dev->dev_ops = &mana_dev_sec_ops;
+				ret = mana_proc_priv_init(eth_dev);
+				if (ret)
+					goto failed;
+				priv->process_priv = eth_dev-

process_private;

drivers/net/mana/mana.c

Quoted 3 lines
drivers/net/mana/mana.c new file +3 -0
+
+				/* Get the IB FD from the primary process */
+				fd =

mana_mp_req_verbs_cmd_fd(eth_dev);

Review

Quoted 2 lines
(quoted diff) +2 -0
+				if (fd < 0) {
+					DRV_LOG(ERR, "Failed to get FD %d",

fd);

drivers/net/mana/mana.c

Quoted 5 lines
drivers/net/mana/mana.c new file +5 -0
+					ret = -ENODEV;
+					goto failed;
+				}
+
+				ret =

mana_map_doorbell_secondary(eth_dev, fd);

Review

Quoted 2 lines
(quoted diff) +2 -0
+				if (ret) {
+					DRV_LOG(ERR, "Failed secondary

map %d",

Quoted 39 lines
drivers/net/mana/mana.c new file +8 -0
+						fd);
+					goto failed;
+				}
+
+				/* fd is no not used after mapping doorbell */
+				close(fd);
+
+				rte_spinlock_lock(&mana_shared_data-

lock);

drivers/net/mana/mana.c new file +3 -0
+				mana_shared_data->secondary_cnt++;
+				mana_local_data.secondary_cnt++;
+				rte_spinlock_unlock(&mana_shared_data-

lock);

drivers/net/mana/mana.c new file +25 -0
+
+				rte_eth_copy_pci_info(eth_dev, pci_dev);
+				rte_eth_dev_probing_finish(eth_dev);
+
+				/* Impossible to have more than one port
+				 * matching a MAC address
+				 */
+				continue;
+			}
+
+			eth_dev = rte_eth_dev_allocate(name);
+			if (!eth_dev) {
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			eth_dev->data->mac_addrs =
+				rte_calloc("mana_mac", 1,
+					   sizeof(struct rte_ether_addr), 0);
+			if (!eth_dev->data->mac_addrs) {
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			rte_ether_addr_copy(&addr, eth_dev->data-

mac_addrs);

drivers/net/mana/mana.c

Quoted 4 lines
drivers/net/mana/mana.c new file +4 -0
+
+			priv->ib_pd = ibv_alloc_pd(ctx);
+			if (!priv->ib_pd) {
+				DRV_LOG(ERR, "ibv_alloc_pd failed port %d",

port);

drivers/net/mana/mana.c

Quoted 7 lines
drivers/net/mana/mana.c new file +7 -0
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			/* Create a parent domain with the port number */
+			attr.pd = priv->ib_pd;
+			attr.comp_mask =

IBV_PARENT_DOMAIN_INIT_ATTR_PD_CONTEXT;

Review

Quoted 2 lines
(quoted diff) +2 -0
+			attr.pd_context = (void *)(uint64_t)port;
+			priv->ib_parent_pd = ibv_alloc_parent_domain(ctx,

&attr);

drivers/net/mana/mana.c

Quoted 3 lines
drivers/net/mana/mana.c new file +3 -0
+			if (!priv->ib_parent_pd) {
+				DRV_LOG(ERR,
+					"ibv_alloc_parent_domain failed port

%d",

Quoted 16 lines
drivers/net/mana/mana.c new file +16 -0
+					port);
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			priv->ib_ctx = ctx;
+			priv->port_id = eth_dev->data->port_id;
+			priv->dev_port = port;
+			eth_dev->data->dev_private = priv;
+			priv->dev_data = eth_dev->data;
+
+			priv->max_rx_queues = dev_attr.orig_attr.max_qp;
+			priv->max_tx_queues = dev_attr.orig_attr.max_qp;
+
+			priv->max_rx_desc =
+				RTE_MIN(dev_attr.orig_attr.max_qp_wr,

drivers/net/mana/mana.c

Quoted 10 lines
drivers/net/mana/mana.c new file +10 -0
+					dev_attr.orig_attr.max_cqe);
+			priv->max_tx_desc =
+				RTE_MIN(dev_attr.orig_attr.max_qp_wr,
+					dev_attr.orig_attr.max_cqe);
+
+			priv->max_send_sge = dev_attr.orig_attr.max_sge;
+			priv->max_recv_sge = dev_attr.orig_attr.max_sge;
+
+			priv->max_mr = dev_attr.orig_attr.max_mr;
+			priv->max_mr_size =

dev_attr.orig_attr.max_mr_size;

Review

Quoted 2 lines
(quoted diff) +2 -0
+
+			DRV_LOG(INFO, "dev %s max queues %d desc %d

sge %d",

drivers/net/mana/mana.c line 545

Quoted 9 lines
(quoted diff) +1 -0
+				name, priv->max_rx_queues, priv-

max_rx_desc,

drivers/net/mana/mana.c new file +7 -0
+				priv->max_send_sge);
+
+			rte_spinlock_lock(&mana_shared_data->lock);
+			mana_shared_data->primary_cnt++;
+			rte_spinlock_unlock(&mana_shared_data->lock);
+
+			eth_dev->data->dev_flags |=

RTE_ETH_DEV_INTR_RMV;

drivers/net/mana/mana.c line 547

Quoted 5 lines
drivers/net/mana/mana.c new file +5 -0
+
+			eth_dev->device = &pci_dev->device;
+			eth_dev->data->dev_flags |=
+				RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
+

Please do not use the temporary macro. Please review this patch:

Quoted 5 lines

f30e69b41f94 ("ethdev: add device flag to bypass auto-filled queue xstats")

This patch requires that per queue statistics are filled in .xstats_get() by PMD.

Thanks for pointing this out.

It seems some PMDs are still depending on this flag for xstats.

Quoted 10 lines
Quoted 1 line

MANA doesn't implement xstats_get() currently, this flag is useful. Is it

okay to keep using this flag before it's finally the time to remove it from all PMDs, or when MANA implements xstats?
Yes, your xstats doesn't implement now. Per queue stats should be filled in xstats API, and the stats API cannot see per queue stats, so stats API in driver shouldn't fill it(suggest that delete it from patch 17/18).

I guess this flag can be removed if PMD does not support xstats.

Quoted 2 lines

I don't understand your suggestion. An application can call rte_eth_stats_get() to get port stats, and this will call into stats_get() in the driver, as implemented in patch 17/18.

When flag RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS is set, an application can also use rte_eth_xstats_get() to get port stats even the driver doesn't implement xstats_get().

#6 lore raw

Re: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

Quoted 273 lines · Long Li
Quoted 273 lines

Subject: Re: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

Quoted 255 lines · Long Li
Quoted 255 lines

Subject: Re: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

Quoted 23 lines · 在 2022/8/31 6:51, [email protected] 写道:

From: Long Li <[email protected]>

MANA is a PCI device. It uses IB verbs to access hardware through the kernel RDMA layer. This patch introduces build environment and basic device probe functions.

---
Change log:
v2:
Fix typos.
Make the driver build only on x86-64 and Linux.
Remove unused header files.
Change port definition to uint16_t or uint8_t (for IB). Use getline() in place of fgets() to read and truncate a line. v3:
Add meson build check for required functions from RDMA direct verb header file
v4:
Remove extra "\n" in logging code.
Use "r" in place of "rb" in fopen() to read text files.

[snip]

Review

Quoted 2 lines
(quoted diff) +2 -0
+
+static int mana_pci_probe_mac(struct rte_pci_driver *pci_drv

__rte_unused,

Quoted 9 lines
drivers/net/mana/mana.c new file +9 -0
+			      struct rte_pci_device *pci_dev,
+			      struct rte_ether_addr *mac_addr) {
+	struct ibv_device **ibv_list;
+	int ibv_idx;
+	struct ibv_context *ctx;
+	struct ibv_device_attr_ex dev_attr;
+	int num_devices;
+	int ret = 0;
+	uint8_t port;

drivers/net/mana/mana.c

Quoted 10 lines
drivers/net/mana/mana.c new file +10 -0
+	struct mana_priv *priv = NULL;
+	struct rte_eth_dev *eth_dev = NULL;
+	bool found_port;
+
+	ibv_list = ibv_get_device_list(&num_devices);
+	for (ibv_idx = 0; ibv_idx < num_devices; ibv_idx++) {
+		struct ibv_device *ibdev = ibv_list[ibv_idx];
+		struct rte_pci_addr pci_addr;
+
+		DRV_LOG(INFO, "Probe device name %s dev_name %s

ibdev_path %s",

Quoted 27 lines
(quoted diff) +1 -0
+			ibdev->name, ibdev->dev_name, ibdev-

ibdev_path);

drivers/net/mana/mana.c new file +25 -0
+
+		if (mana_ibv_device_to_pci_addr(ibdev, &pci_addr))
+			continue;
+
+		/* Ignore if this IB device is not this PCI device */
+		if (pci_dev->addr.domain != pci_addr.domain ||
+		    pci_dev->addr.bus != pci_addr.bus ||
+		    pci_dev->addr.devid != pci_addr.devid ||
+		    pci_dev->addr.function != pci_addr.function)
+			continue;
+
+		ctx = ibv_open_device(ibdev);
+		if (!ctx) {
+			DRV_LOG(ERR, "Failed to open IB device %s",
+				ibdev->name);
+			continue;
+		}
+
+		ret = ibv_query_device_ex(ctx, NULL, &dev_attr);
+		DRV_LOG(INFO, "dev_attr.orig_attr.phys_port_cnt %u",
+			dev_attr.orig_attr.phys_port_cnt);
+		found_port = false;
+
+		for (port = 1; port <= dev_attr.orig_attr.phys_port_cnt;
+		     port++) {

drivers/net/mana/mana.c

Quoted 10 lines
drivers/net/mana/mana.c new file +10 -0
+			struct ibv_parent_domain_init_attr attr = {};
+			struct rte_ether_addr addr;
+			char address[64];
+			char name[RTE_ETH_NAME_MAX_LEN];
+
+			ret = get_port_mac(ibdev, port, &addr);
+			if (ret)
+				continue;
+
+			if (mac_addr && !rte_is_same_ether_addr(&addr,

mac_addr))

drivers/net/mana/mana.c

Quoted 3 lines
drivers/net/mana/mana.c new file +3 -0
+				continue;
+
+			rte_ether_format_addr(address, sizeof(address),

&addr);

Review

Quoted 1 line
(quoted diff) +1 -0
+			DRV_LOG(INFO, "device located port %u address

%s",

Quoted 5 lines
drivers/net/mana/mana.c new file +5 -0
+				port, address);
+			found_port = true;
+
+			priv = rte_zmalloc_socket(NULL, sizeof(*priv),
+						  RTE_CACHE_LINE_SIZE,

drivers/net/mana/mana.c

Quoted 10 lines
drivers/net/mana/mana.c new file +10 -0
+						  SOCKET_ID_ANY);
+			if (!priv) {
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			snprintf(name, sizeof(name), "%s_port%d",
+				 pci_dev->device.name, port);
+
+			if (rte_eal_process_type() ==

RTE_PROC_SECONDARY) {

drivers/net/mana/mana.c

Quoted 3 lines
drivers/net/mana/mana.c new file +3 -0
+				int fd;
+
+				eth_dev =

rte_eth_dev_attach_secondary(name);

Review

Quoted 2 lines
(quoted diff) +2 -0
+				if (!eth_dev) {
+					DRV_LOG(ERR, "Can't attach to dev

%s",

Quoted 12 lines
drivers/net/mana/mana.c new file +11 -0
+						name);
+					ret = -ENOMEM;
+					goto failed;
+				}
+
+				eth_dev->device = &pci_dev->device;
+				eth_dev->dev_ops = &mana_dev_sec_ops;
+				ret = mana_proc_priv_init(eth_dev);
+				if (ret)
+					goto failed;
+				priv->process_priv = eth_dev-

process_private;

drivers/net/mana/mana.c

Quoted 3 lines
drivers/net/mana/mana.c new file +3 -0
+
+				/* Get the IB FD from the primary process */
+				fd =

mana_mp_req_verbs_cmd_fd(eth_dev);

Review

Quoted 2 lines
(quoted diff) +2 -0
+				if (fd < 0) {
+					DRV_LOG(ERR, "Failed to get FD %d",

fd);

drivers/net/mana/mana.c

Quoted 5 lines
drivers/net/mana/mana.c new file +5 -0
+					ret = -ENODEV;
+					goto failed;
+				}
+
+				ret =

mana_map_doorbell_secondary(eth_dev, fd);

Review

Quoted 2 lines
(quoted diff) +2 -0
+				if (ret) {
+					DRV_LOG(ERR, "Failed secondary

map %d",

Quoted 39 lines
drivers/net/mana/mana.c new file +8 -0
+						fd);
+					goto failed;
+				}
+
+				/* fd is no not used after mapping doorbell */
+				close(fd);
+
+				rte_spinlock_lock(&mana_shared_data-

lock);

drivers/net/mana/mana.c new file +3 -0
+				mana_shared_data->secondary_cnt++;
+				mana_local_data.secondary_cnt++;
+				rte_spinlock_unlock(&mana_shared_data-

lock);

drivers/net/mana/mana.c new file +25 -0
+
+				rte_eth_copy_pci_info(eth_dev, pci_dev);
+				rte_eth_dev_probing_finish(eth_dev);
+
+				/* Impossible to have more than one port
+				 * matching a MAC address
+				 */
+				continue;
+			}
+
+			eth_dev = rte_eth_dev_allocate(name);
+			if (!eth_dev) {
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			eth_dev->data->mac_addrs =
+				rte_calloc("mana_mac", 1,
+					   sizeof(struct rte_ether_addr), 0);
+			if (!eth_dev->data->mac_addrs) {
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			rte_ether_addr_copy(&addr, eth_dev->data-

mac_addrs);

drivers/net/mana/mana.c

Quoted 4 lines
drivers/net/mana/mana.c new file +4 -0
+
+			priv->ib_pd = ibv_alloc_pd(ctx);
+			if (!priv->ib_pd) {
+				DRV_LOG(ERR, "ibv_alloc_pd failed port %d",

port);

drivers/net/mana/mana.c

Quoted 7 lines
drivers/net/mana/mana.c new file +7 -0
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			/* Create a parent domain with the port number */
+			attr.pd = priv->ib_pd;
+			attr.comp_mask =

IBV_PARENT_DOMAIN_INIT_ATTR_PD_CONTEXT;

Review

Quoted 2 lines
(quoted diff) +2 -0
+			attr.pd_context = (void *)(uint64_t)port;
+			priv->ib_parent_pd = ibv_alloc_parent_domain(ctx,

&attr);

drivers/net/mana/mana.c

Quoted 3 lines
drivers/net/mana/mana.c new file +3 -0
+			if (!priv->ib_parent_pd) {
+				DRV_LOG(ERR,
+					"ibv_alloc_parent_domain failed port

%d",

Quoted 16 lines
drivers/net/mana/mana.c new file +16 -0
+					port);
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			priv->ib_ctx = ctx;
+			priv->port_id = eth_dev->data->port_id;
+			priv->dev_port = port;
+			eth_dev->data->dev_private = priv;
+			priv->dev_data = eth_dev->data;
+
+			priv->max_rx_queues = dev_attr.orig_attr.max_qp;
+			priv->max_tx_queues = dev_attr.orig_attr.max_qp;
+
+			priv->max_rx_desc =
+				RTE_MIN(dev_attr.orig_attr.max_qp_wr,

drivers/net/mana/mana.c

Quoted 10 lines
drivers/net/mana/mana.c new file +10 -0
+					dev_attr.orig_attr.max_cqe);
+			priv->max_tx_desc =
+				RTE_MIN(dev_attr.orig_attr.max_qp_wr,
+					dev_attr.orig_attr.max_cqe);
+
+			priv->max_send_sge = dev_attr.orig_attr.max_sge;
+			priv->max_recv_sge = dev_attr.orig_attr.max_sge;
+
+			priv->max_mr = dev_attr.orig_attr.max_mr;
+			priv->max_mr_size =

dev_attr.orig_attr.max_mr_size;

Review

Quoted 2 lines
(quoted diff) +2 -0
+
+			DRV_LOG(INFO, "dev %s max queues %d desc %d

sge %d",

drivers/net/mana/mana.c line 545

Quoted 9 lines
(quoted diff) +1 -0
+				name, priv->max_rx_queues, priv-

max_rx_desc,

drivers/net/mana/mana.c new file +7 -0
+				priv->max_send_sge);
+
+			rte_spinlock_lock(&mana_shared_data->lock);
+			mana_shared_data->primary_cnt++;
+			rte_spinlock_unlock(&mana_shared_data->lock);
+
+			eth_dev->data->dev_flags |=

RTE_ETH_DEV_INTR_RMV;

drivers/net/mana/mana.c line 547

Quoted 5 lines
drivers/net/mana/mana.c new file +5 -0
+
+			eth_dev->device = &pci_dev->device;
+			eth_dev->data->dev_flags |=
+				RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
+

Please do not use the temporary macro. Please review this patch:

f30e69b41f94 ("ethdev: add device flag to bypass auto-filled queue xstats")

Quoted 7 lines
Quoted 2 lines

This patch requires that per queue statistics are filled in .xstats_get() by PMD.

Thanks for pointing this out.

It seems some PMDs are still depending on this flag for xstats.

MANA doesn't implement xstats_get() currently, this flag is useful. Is it

okay to keep using this flag before it's finally the time to remove it from all PMDs, or when MANA implements xstats?
Yes, your xstats doesn't implement now. Per queue stats should be filled in xstats API, and the stats API cannot see per queue stats, so stats API in driver shouldn't fill it(suggest that delete it from patch 17/18).

Quoted 5 lines
Quoted 2 lines

I guess this flag can be removed if PMD does not support xstats.

Quoted 1 line

I don't understand your suggestion. An application can call rte_eth_stats_get() to get port stats, and this will call into stats_get() in the driver, as implemented in patch 17/18.

When flag RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS is set, an application can also use rte_eth_xstats_get() to get port stats even the driver doesn't implement xstats_get().

I think new PMD should follow the announced switch Ferruh mentioned, otherwise, the switch will never be completed.

Suggest that mana driver can implement a simple xstats_get() to fill per queue stats if you want to support per queue stats.

@Ferruh, what do you think?

#7 lore raw

RE: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

Quoted 321 lines

Subject: Re: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

Quoted 47 lines · Long Li
Quoted 47 lines

Subject: Re: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

Quoted 42 lines · Long Li
Quoted 42 lines

Subject: Re: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

Quoted 23 lines · 在 2022/8/31 6:51, [email protected] 写道:

From: Long Li <[email protected]>

MANA is a PCI device. It uses IB verbs to access hardware through the kernel RDMA layer. This patch introduces build environment and basic device probe functions.

---
Change log:
v2:
Fix typos.
Make the driver build only on x86-64 and Linux.
Remove unused header files.
Change port definition to uint16_t or uint8_t (for IB). Use getline() in place of fgets() to read and truncate a line. v3:
Add meson build check for required functions from RDMA direct verb header file
v4:
Remove extra "\n" in logging code.
Use "r" in place of "rb" in fopen() to read text files.

[snip]

Review

Quoted 2 lines
(quoted diff) +2 -0
+
+static int mana_pci_probe_mac(struct rte_pci_driver *pci_drv

__rte_unused,

Quoted 11 lines
drivers/net/mana/mana.c new file +11 -0
+			      struct rte_pci_device *pci_dev,
+			      struct rte_ether_addr *mac_addr) {
+	struct ibv_device **ibv_list;
+	int ibv_idx;
+	struct ibv_context *ctx;
+	struct ibv_device_attr_ex dev_attr;
+	int num_devices;
+	int ret = 0;
+	uint8_t port;
+	struct mana_priv *priv = NULL;
+	struct rte_eth_dev *eth_dev = NULL;
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/net/mana/mana.c

Quoted 8 lines
drivers/net/mana/mana.c new file +8 -0
+	bool found_port;
+
+	ibv_list = ibv_get_device_list(&num_devices);
+	for (ibv_idx = 0; ibv_idx < num_devices; ibv_idx++) {
+		struct ibv_device *ibdev = ibv_list[ibv_idx];
+		struct rte_pci_addr pci_addr;
+
+		DRV_LOG(INFO, "Probe device name %s

dev_name %s

Quoted 15 lines
Quoted 15 lines
Quoted 15 lines
Quoted 15 lines

ibdev_path %s",

Quoted 14 lines
(quoted diff) +1 -0
+			ibdev->name, ibdev->dev_name, ibdev-

ibdev_path);

drivers/net/mana/mana.c new file +12 -0
+
+		if (mana_ibv_device_to_pci_addr(ibdev, &pci_addr))
+			continue;
+
+		/* Ignore if this IB device is not this PCI device */
+		if (pci_dev->addr.domain != pci_addr.domain ||
+		    pci_dev->addr.bus != pci_addr.bus ||
+		    pci_dev->addr.devid != pci_addr.devid ||
+		    pci_dev->addr.function != pci_addr.function)
+			continue;
+
+		ctx = ibv_open_device(ibdev);
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/net/mana/mana.c

Quoted 8 lines
drivers/net/mana/mana.c new file +8 -0
+		if (!ctx) {
+			DRV_LOG(ERR, "Failed to open IB device %s",
+				ibdev->name);
+			continue;
+		}
+
+		ret = ibv_query_device_ex(ctx, NULL, &dev_attr);
+		DRV_LOG(INFO,

"dev_attr.orig_attr.phys_port_cnt %u",

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines

drivers/net/mana/mana.c

Quoted 4 lines
drivers/net/mana/mana.c new file +4 -0
+			dev_attr.orig_attr.phys_port_cnt);
+		found_port = false;
+
+		for (port = 1; port <=

dev_attr.orig_attr.phys_port_cnt;

Quoted 11 lines
Quoted 11 lines
Quoted 11 lines
Quoted 11 lines

drivers/net/mana/mana.c

Quoted 11 lines
drivers/net/mana/mana.c new file +11 -0
+		     port++) {
+			struct ibv_parent_domain_init_attr attr = {};
+			struct rte_ether_addr addr;
+			char address[64];
+			char name[RTE_ETH_NAME_MAX_LEN];
+
+			ret = get_port_mac(ibdev, port, &addr);
+			if (ret)
+				continue;
+
+			if (mac_addr

&& !rte_is_same_ether_addr(&addr,

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines

mac_addr))

drivers/net/mana/mana.c

Quoted 3 lines
drivers/net/mana/mana.c new file +3 -0
+				continue;
+
+			rte_ether_format_addr(address,

sizeof(address),

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

&addr);

Review

Quoted 1 line
(quoted diff) +1 -0
+			DRV_LOG(INFO, "device located port %u

address

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

%s",

drivers/net/mana/mana.c line 422

Quoted 5 lines
drivers/net/mana/mana.c new file +5 -0
+				port, address);
+			found_port = true;
+
+			priv = rte_zmalloc_socket(NULL, sizeof(*priv),
+

RTE_CACHE_LINE_SIZE,

Quoted 11 lines
Quoted 11 lines
Quoted 11 lines
Quoted 11 lines

drivers/net/mana/mana.c

Quoted 10 lines
drivers/net/mana/mana.c new file +10 -0
+						  SOCKET_ID_ANY);
+			if (!priv) {
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			snprintf(name, sizeof(name), "%s_port%d",
+				 pci_dev->device.name, port);
+
+			if (rte_eal_process_type() ==

RTE_PROC_SECONDARY) {

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

drivers/net/mana/mana.c

Quoted 3 lines
drivers/net/mana/mana.c new file +3 -0
+				int fd;
+
+				eth_dev =

rte_eth_dev_attach_secondary(name);

Review

Quoted 2 lines
(quoted diff) +2 -0
+				if (!eth_dev) {
+					DRV_LOG(ERR, "Can't attach

to dev

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

%s",

drivers/net/mana/mana.c

Quoted 7 lines
drivers/net/mana/mana.c new file +7 -0
+						name);
+					ret = -ENOMEM;
+					goto failed;
+				}
+
+				eth_dev->device = &pci_dev->device;
+				eth_dev->dev_ops =

&mana_dev_sec_ops;

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

Review

Quoted 7 lines
drivers/net/mana/mana.c new file +4 -0
+				ret = mana_proc_priv_init(eth_dev);
+				if (ret)
+					goto failed;
+				priv->process_priv = eth_dev-

process_private;

(quoted diff) +2 -0
+
+				/* Get the IB FD from the primary

process */

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines

Review

Quoted 1 line
(quoted diff) +1 -0
+				fd =

mana_mp_req_verbs_cmd_fd(eth_dev);

Review

Quoted 2 lines
(quoted diff) +2 -0
+				if (fd < 0) {
+					DRV_LOG(ERR, "Failed to get

FD %d",

Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines

fd);

drivers/net/mana/mana.c

Quoted 5 lines
drivers/net/mana/mana.c new file +5 -0
+					ret = -ENODEV;
+					goto failed;
+				}
+
+				ret =

mana_map_doorbell_secondary(eth_dev, fd);

Review

Quoted 2 lines
(quoted diff) +2 -0
+				if (ret) {
+					DRV_LOG(ERR, "Failed

secondary

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

map %d",

drivers/net/mana/mana.c

Quoted 5 lines
drivers/net/mana/mana.c new file +5 -0
+						fd);
+					goto failed;
+				}
+
+				/* fd is no not used after mapping

doorbell */

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

drivers/net/mana/mana.c line 466

Quoted 3 lines
drivers/net/mana/mana.c new file +3 -0
+				close(fd);
+
+

rte_spinlock_lock(&mana_shared_data-

Quoted 5 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

Review

Quoted 2 lines

lock);

(quoted diff) +1 -0
+				mana_shared_data-

secondary_cnt++;

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

drivers/net/mana/mana.c line 466

Quoted 2 lines
drivers/net/mana/mana.c new file +2 -0
+				mana_local_data.secondary_cnt++;
+

rte_spinlock_unlock(&mana_shared_data-

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

Review

Quoted 3 lines

lock);

(quoted diff) +2 -0
+
+				rte_eth_copy_pci_info(eth_dev,

pci_dev);

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

+

	rte_eth_dev_probing_finish(eth_dev);
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

Review

Quoted 2 lines
(quoted diff) +2 -0
+
+				/* Impossible to have more than one

port

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
drivers/net/mana/mana.c new file +6 -0
+				 * matching a MAC address
+				 */
+				continue;
+			}
+
+			eth_dev = rte_eth_dev_allocate(name);
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/net/mana/mana.c

Quoted 8 lines
drivers/net/mana/mana.c new file +8 -0
+			if (!eth_dev) {
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			eth_dev->data->mac_addrs =
+				rte_calloc("mana_mac", 1,
+					   sizeof(struct

rte_ether_addr), 0);

Quoted 7 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

drivers/net/mana/mana.c

Quoted 6 lines
drivers/net/mana/mana.c new file +6 -0
+			if (!eth_dev->data->mac_addrs) {
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			rte_ether_addr_copy(&addr, eth_dev-

data-

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

drivers/net/mana/mana.c

Quoted 5 lines

mac_addrs);

drivers/net/mana/mana.c new file +4 -0
+
+			priv->ib_pd = ibv_alloc_pd(ctx);
+			if (!priv->ib_pd) {
+				DRV_LOG(ERR, "ibv_alloc_pd failed

port %d",

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

port);

drivers/net/mana/mana.c

Quoted 5 lines
drivers/net/mana/mana.c new file +5 -0
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			/* Create a parent domain with the port

number */

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

Review

Quoted 2 lines
(quoted diff) +2 -0
+			attr.pd = priv->ib_pd;
+			attr.comp_mask =

IBV_PARENT_DOMAIN_INIT_ATTR_PD_CONTEXT;

Review

Quoted 2 lines
(quoted diff) +2 -0
+			attr.pd_context = (void *)(uint64_t)port;
+			priv->ib_parent_pd =

ibv_alloc_parent_domain(ctx,

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines

&attr);

drivers/net/mana/mana.c

Quoted 3 lines
drivers/net/mana/mana.c new file +3 -0
+			if (!priv->ib_parent_pd) {
+				DRV_LOG(ERR,
+					"ibv_alloc_parent_domain

failed port

Quoted 13 lines
Quoted 13 lines
Quoted 13 lines
Quoted 13 lines

%d",

drivers/net/mana/mana.c

Quoted 12 lines
drivers/net/mana/mana.c new file +12 -0
+					port);
+				ret = -ENOMEM;
+				goto failed;
+			}
+
+			priv->ib_ctx = ctx;
+			priv->port_id = eth_dev->data->port_id;
+			priv->dev_port = port;
+			eth_dev->data->dev_private = priv;
+			priv->dev_data = eth_dev->data;
+
+			priv->max_rx_queues =

dev_attr.orig_attr.max_qp;

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

Review

Quoted 1 line
(quoted diff) +1 -0
+			priv->max_tx_queues =

dev_attr.orig_attr.max_qp;

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

drivers/net/mana/mana.c line 527

Quoted 3 lines
drivers/net/mana/mana.c new file +3 -0
+
+			priv->max_rx_desc =
+

RTE_MIN(dev_attr.orig_attr.max_qp_wr,

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

drivers/net/mana/mana.c line 527

Quoted 3 lines
drivers/net/mana/mana.c new file +3 -0
+					dev_attr.orig_attr.max_cqe);
+			priv->max_tx_desc =
+

RTE_MIN(dev_attr.orig_attr.max_qp_wr,

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

drivers/net/mana/mana.c

Quoted 3 lines
drivers/net/mana/mana.c new file +3 -0
+					dev_attr.orig_attr.max_cqe);
+
+			priv->max_send_sge =

dev_attr.orig_attr.max_sge;

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

Review

Quoted 1 line
(quoted diff) +1 -0
+			priv->max_recv_sge =

dev_attr.orig_attr.max_sge;

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

drivers/net/mana/mana.c

Quoted 3 lines
drivers/net/mana/mana.c new file +3 -0
+
+			priv->max_mr = dev_attr.orig_attr.max_mr;
+			priv->max_mr_size =

dev_attr.orig_attr.max_mr_size;

Review

Quoted 2 lines
(quoted diff) +2 -0
+
+			DRV_LOG(INFO, "dev %s max queues %d

desc %d

Quoted 10 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

sge %d",

drivers/net/mana/mana.c

Quoted 5 lines
(quoted diff) +1 -0
+				name, priv->max_rx_queues, priv-

max_rx_desc,

drivers/net/mana/mana.c new file +3 -0
+				priv->max_send_sge);
+
+			rte_spinlock_lock(&mana_shared_data-

lock);

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

Review

Quoted 2 lines
(quoted diff) +2 -0
+			mana_shared_data->primary_cnt++;
+			rte_spinlock_unlock(&mana_shared_data-

lock);

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

drivers/net/mana/mana.c line 545

Quoted 2 lines
drivers/net/mana/mana.c new file +2 -0
+
+			eth_dev->data->dev_flags |=

RTE_ETH_DEV_INTR_RMV;

drivers/net/mana/mana.c line 547

Quoted 4 lines
drivers/net/mana/mana.c new file +4 -0
+
+			eth_dev->device = &pci_dev->device;
+			eth_dev->data->dev_flags |=
+
	RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
Quoted 8 lines
Quoted 1 line

+

Please do not use the temporary macro. Please review this patch:

f30e69b41f94 ("ethdev: add device flag to bypass auto-filled queue xstats")

This patch requires that per queue statistics are filled in .xstats_get() by PMD.

Thanks for pointing this out.

It seems some PMDs are still depending on this flag for xstats.

Quoted 7 lines
Quoted 7 lines
Quoted 2 lines

MANA doesn't implement xstats_get() currently, this flag is useful. Is it

okay to keep using this flag before it's finally the time to remove it from all PMDs, or when MANA implements xstats?
Yes, your xstats doesn't implement now. Per queue stats should be filled in xstats API, and the stats API cannot see per queue stats, so stats API in driver shouldn't fill it(suggest that delete it from patch

17/18).

Quoted 4 lines
Quoted 3 lines

I guess this flag can be removed if PMD does not support xstats.

Quoted 1 line

I don't understand your suggestion. An application can call

rte_eth_stats_get() to get port stats, and this will call into stats_get() in the driver, as implemented in patch 17/18.

Quoted 1 line
Quoted 6 lines
Quoted 1 line

When flag RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS is set, an application

can also use rte_eth_xstats_get() to get port stats even the driver doesn't implement xstats_get().

I think new PMD should follow the announced switch Ferruh mentioned, otherwise, the switch will never be completed.

I see now I understand more. I prefer to keep patch 17/18, or an application calling rte_eth_stats_get() will fail. (before the switch happens)

Quoted 5 lines

Suggest that mana driver can implement a simple xstats_get() to fill per queue stats if you want to support per queue stats.

@Ferruh, what do you think?

#8 lore raw

Re: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

In reply to lihuisong (C)
Quoted 287 lines · lihuisong (C)

CAUTION: This message has originated from an External Source. Please use proper judgment and caution when opening attachments, clicking links, or responding to this email.

Quoted 277 lines · Long Li
Quoted 277 lines

Subject: Re: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

Quoted 259 lines · Long Li
Quoted 259 lines

Subject: Re: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

Quoted 23 lines · 在 2022/8/31 6:51, [email protected] 写道:

From: Long Li <[email protected]>

MANA is a PCI device. It uses IB verbs to access hardware through the kernel RDMA layer. This patch introduces build environment and basic device probe functions.

---
Change log:
v2:
Fix typos.
Make the driver build only on x86-64 and Linux.
Remove unused header files.
Change port definition to uint16_t or uint8_t (for IB). Use getline() in place of fgets() to read and truncate a line. v3:
Add meson build check for required functions from RDMA direct verb header file
v4:
Remove extra "\n" in logging code.
Use "r" in place of "rb" in fopen() to read text files.

[snip]

Review

Quoted 2 lines
(quoted diff) +2 -0
+
+static int mana_pci_probe_mac(struct rte_pci_driver *pci_drv

__rte_unused,

Quoted 12 lines

+                       struct rte_pci_device *pci_dev, +                       struct rte_ether_addr *mac_addr) {
+ struct ibv_device **ibv_list;
+ int ibv_idx;
+ struct ibv_context *ctx;
+ struct ibv_device_attr_ex dev_attr;
+ int num_devices;
+ int ret = 0;
+ uint8_t port;
+ struct mana_priv *priv = NULL;
+ struct rte_eth_dev *eth_dev = NULL;
+ bool found_port;

drivers/net/mana/mana.c

Quoted 7 lines
drivers/net/mana/mana.c new file +7 -0
+
+ ibv_list = ibv_get_device_list(&num_devices);
+ for (ibv_idx = 0; ibv_idx < num_devices; ibv_idx++) {
+         struct ibv_device *ibdev = ibv_list[ibv_idx];
+         struct rte_pci_addr pci_addr;
+
+         DRV_LOG(INFO, "Probe device name %s dev_name %s

ibdev_path %s",

Quoted 27 lines

+                 ibdev->name, ibdev->dev_name, ibdev- ibdev_path);

drivers/net/mana/mana.c new file +25 -0
+
+         if (mana_ibv_device_to_pci_addr(ibdev, &pci_addr))
+                 continue;
+
+         /* Ignore if this IB device is not this PCI device */
+         if (pci_dev->addr.domain != pci_addr.domain ||
+             pci_dev->addr.bus != pci_addr.bus ||
+             pci_dev->addr.devid != pci_addr.devid ||
+             pci_dev->addr.function != pci_addr.function)
+                 continue;
+
+         ctx = ibv_open_device(ibdev);
+         if (!ctx) {
+                 DRV_LOG(ERR, "Failed to open IB device %s",
+                         ibdev->name);
+                 continue;
+         }
+
+         ret = ibv_query_device_ex(ctx, NULL, &dev_attr);
+         DRV_LOG(INFO, "dev_attr.orig_attr.phys_port_cnt %u",
+                 dev_attr.orig_attr.phys_port_cnt);
+         found_port = false;
+
+         for (port = 1; port <= dev_attr.orig_attr.phys_port_cnt;
+              port++) {

drivers/net/mana/mana.c

Quoted 10 lines
drivers/net/mana/mana.c new file +10 -0
+                 struct ibv_parent_domain_init_attr attr = {};
+                 struct rte_ether_addr addr;
+                 char address[64];
+                 char name[RTE_ETH_NAME_MAX_LEN];
+
+                 ret = get_port_mac(ibdev, port, &addr);
+                 if (ret)
+                         continue;
+
+                 if (mac_addr && !rte_is_same_ether_addr(&addr,

mac_addr))

Quoted 3 lines

+                         continue;
+
+                 rte_ether_format_addr(address, sizeof(address),

&addr);

Quoted 1 line

+                 DRV_LOG(INFO, "device located port %u address

%s",

Quoted 5 lines

+                         port, address);
+                 found_port = true;

drivers/net/mana/mana.c new file +3 -0
+
+                 priv = rte_zmalloc_socket(NULL, sizeof(*priv),
+                                           RTE_CACHE_LINE_SIZE,

drivers/net/mana/mana.c

Quoted 10 lines
drivers/net/mana/mana.c new file +10 -0
+                                           SOCKET_ID_ANY);
+                 if (!priv) {
+                         ret = -ENOMEM;
+                         goto failed;
+                 }
+
+                 snprintf(name, sizeof(name), "%s_port%d",
+                          pci_dev->device.name, port);
+
+                 if (rte_eal_process_type() ==

RTE_PROC_SECONDARY) {

Quoted 3 lines

+                         int fd;
+
+                         eth_dev =

rte_eth_dev_attach_secondary(name);

Quoted 2 lines

+                         if (!eth_dev) {
+                                 DRV_LOG(ERR, "Can't attach to dev

%s",

Quoted 8 lines

+                                         name);
+                                 ret = -ENOMEM;
+                                 goto failed;
+                         }
+
+                         eth_dev->device = &pci_dev->device; +                         eth_dev->dev_ops = &mana_dev_sec_ops; +                         ret = mana_proc_priv_init(eth_dev);

Quoted 8 lines

+                         if (ret)
+                                 goto failed;
+                         priv->process_priv = eth_dev- process_private;
+
+                         /* Get the IB FD from the primary process */
+                         fd =

mana_mp_req_verbs_cmd_fd(eth_dev);

Quoted 2 lines

+                         if (fd < 0) {
+                                 DRV_LOG(ERR, "Failed to get FD %d",

fd);

Quoted 5 lines

+                                 ret = -ENODEV;
+                                 goto failed;
+                         }
+
+                         ret =

mana_map_doorbell_secondary(eth_dev, fd);

Quoted 2 lines

+                         if (ret) {
+                                 DRV_LOG(ERR, "Failed secondary

map %d",

Quoted 37 lines

+                                         fd);
+                                 goto failed;
+                         }
+
+                         /* fd is no not used after mapping doorbell */
+                         close(fd);
+
+                         rte_spinlock_lock(&mana_shared_data- lock);
+                         mana_shared_data->secondary_cnt++; +                         mana_local_data.secondary_cnt++; +                         rte_spinlock_unlock(&mana_shared_data- lock);

drivers/net/mana/mana.c new file +19 -0
+
+                         rte_eth_copy_pci_info(eth_dev, pci_dev);
+                         rte_eth_dev_probing_finish(eth_dev);
+
+                         /* Impossible to have more than one port
+                          * matching a MAC address
+                          */
+                         continue;
+                 }
+
+                 eth_dev = rte_eth_dev_allocate(name);
+                 if (!eth_dev) {
+                         ret = -ENOMEM;
+                         goto failed;
+                 }
+
+                 eth_dev->data->mac_addrs =
+                         rte_calloc("mana_mac", 1,
+                                    sizeof(struct 

rte_ether_addr), 0);
+                 if (!eth_dev->data->mac_addrs) { +                         ret = -ENOMEM;
+                         goto failed;

Quoted 8 lines

+                 }
+
+                 rte_ether_addr_copy(&addr, eth_dev->data- mac_addrs);
+
+                 priv->ib_pd = ibv_alloc_pd(ctx);
+                 if (!priv->ib_pd) {
+                         DRV_LOG(ERR, "ibv_alloc_pd failed port %d",

port);

Quoted 7 lines

+                         ret = -ENOMEM;
+                         goto failed;
+                 }
+
+                 /* Create a parent domain with the port number */ +                 attr.pd = priv->ib_pd;
+                 attr.comp_mask =

IBV_PARENT_DOMAIN_INIT_ATTR_PD_CONTEXT;

Quoted 2 lines

+                 attr.pd_context = (void *)(uint64_t)port; +                 priv->ib_parent_pd = ibv_alloc_parent_domain(ctx,

&attr);

Quoted 4 lines

+                 if (!priv->ib_parent_pd) {
+                         DRV_LOG(ERR,
+                                 "ibv_alloc_parent_domain failed port

%d",

Quoted 16 lines

+                                 port);
+                         ret = -ENOMEM;
+                         goto failed;
+                 }

drivers/net/mana/mana.c new file +12 -0
+
+                 priv->ib_ctx = ctx;
+                 priv->port_id = eth_dev->data->port_id;
+                 priv->dev_port = port;
+                 eth_dev->data->dev_private = priv;
+                 priv->dev_data = eth_dev->data;
+
+                 priv->max_rx_queues = dev_attr.orig_attr.max_qp;
+                 priv->max_tx_queues = dev_attr.orig_attr.max_qp;
+
+                 priv->max_rx_desc =
+                         RTE_MIN(dev_attr.orig_attr.max_qp_wr,

drivers/net/mana/mana.c

Quoted 10 lines
drivers/net/mana/mana.c new file +10 -0
+                                 dev_attr.orig_attr.max_cqe);
+                 priv->max_tx_desc =
+                         RTE_MIN(dev_attr.orig_attr.max_qp_wr,
+                                 dev_attr.orig_attr.max_cqe);
+
+                 priv->max_send_sge = dev_attr.orig_attr.max_sge;
+                 priv->max_recv_sge = dev_attr.orig_attr.max_sge;
+
+                 priv->max_mr = dev_attr.orig_attr.max_mr;
+                 priv->max_mr_size =

dev_attr.orig_attr.max_mr_size;

Quoted 2 lines

+
+                 DRV_LOG(INFO, "dev %s max queues %d desc %d

sge %d",

drivers/net/mana/mana.c line 545

Quoted 9 lines

+                         name, priv->max_rx_queues, priv- max_rx_desc,
+                         priv->max_send_sge);

drivers/net/mana/mana.c new file +6 -0
+
+                 rte_spinlock_lock(&mana_shared_data->lock);
+                 mana_shared_data->primary_cnt++;
+                 rte_spinlock_unlock(&mana_shared_data->lock);
+
+                 eth_dev->data->dev_flags |=

RTE_ETH_DEV_INTR_RMV;

drivers/net/mana/mana.c line 547

Quoted 5 lines
drivers/net/mana/mana.c new file +5 -0
+
+                 eth_dev->device = &pci_dev->device;
+                 eth_dev->data->dev_flags |=
+                         RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
+

Please do not use the temporary macro. Please review this patch:

f30e69b41f94 ("ethdev: add device flag to bypass auto-filled queue xstats")

Quoted 7 lines
Quoted 2 lines

This patch requires that per queue statistics are filled in .xstats_get() by PMD.

Thanks for pointing this out.

It seems some PMDs are still depending on this flag for xstats.

MANA doesn't implement xstats_get() currently, this flag is useful. Is it

okay to keep using this flag before it's finally the time to remove it from all PMDs, or when MANA implements xstats?
Yes, your xstats doesn't implement now. Per queue stats should be filled in xstats API, and the stats API cannot see per queue stats, so stats API in driver shouldn't fill it(suggest that delete it from patch 17/18).

Quoted 5 lines
Quoted 2 lines

I guess this flag can be removed if PMD does not support xstats.

Quoted 1 line

I don't understand your suggestion. An application can call rte_eth_stats_get() to get port stats, and this will call into stats_get() in the driver, as implemented in patch 17/18.

When flag RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS  is set, an application can also use rte_eth_xstats_get() to get port stats even the driver doesn't implement xstats_get().

Quoted 8 lines

I think new PMD should follow the announced switch Ferruh mentioned, otherwise, the switch will never be completed.

Suggest that mana driver can implement a simple xstats_get() to fill per queue stats if you want to support per queue stats.

@Ferruh, what do you think?

Hi Huisong,

Thanks for reminding it, yes it makes sense to implement new method in new drivers.

Long,

There is a long term plan to move queue stats from basic stats structure to xstats. The reason behind is increasing number of queues makes basis stats struct too big, on the other hand xstats is more flexible and no fixes size array is required.

You can remove the 'RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS' flag and driver won't support queue stats in xstats by default. Instead to have that support you will need to implement xstats, later or in this set. When queue stats implemented in xstats, please remember to remove updating 'stats->q_*' in basic stats.

Also in 17/18, the feature 'Stats per queue' seems added, but that is not correct, feature name is misleading here. But it is about queue stats mapping, please check 'doc/guides/nics/features.rst'. So can you please drop that feature.

#9 lore raw

RE: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

Quoted 331 lines

Subject: Re: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

Quoted 5 lines · lihuisong (C)

CAUTION: This message has originated from an External Source. Please use proper judgment and caution when opening attachments, clicking links, or responding to this email.

Quoted 28 lines
Quoted 27 lines · Long Li
Quoted 27 lines

Subject: Re: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

Quoted 22 lines · Long Li
Quoted 22 lines

Subject: Re: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

Quoted 17 lines · 在 2022/8/31 6:51, [email protected] 写道:

From: Long Li <[email protected]>

MANA is a PCI device. It uses IB verbs to access hardware through the kernel RDMA layer. This patch introduces build environment and basic device probe functions.

---
Change log:
v2:
Fix typos.
Make the driver build only on x86-64 and Linux. Remove unused header files.
Change port definition to uint16_t or uint8_t (for IB). Use getline() in place of fgets() to read and truncate a line. v3:
Add meson build check for required functions from RDMA direct

verb

Quoted 264 lines
Quoted 256 lines
Quoted 254 lines
Quoted 237 lines
Quoted 237 lines

Review

Quoted 8 lines

header file
v4:
Remove extra "\n" in logging code.
Use "r" in place of "rb" in fopen() to read text files.

[snip]

(quoted diff) +2 -0
+
+static int mana_pci_probe_mac(struct rte_pci_driver *pci_drv

__rte_unused,

Quoted 12 lines

+                       struct rte_pci_device *pci_dev, +                       struct rte_ether_addr *mac_addr) {
+ struct ibv_device **ibv_list;
+ int ibv_idx;
+ struct ibv_context *ctx;
+ struct ibv_device_attr_ex dev_attr;
+ int num_devices;
+ int ret = 0;
+ uint8_t port;
+ struct mana_priv *priv = NULL;
+ struct rte_eth_dev *eth_dev = NULL;
+ bool found_port;

Review

Quoted 7 lines
(quoted diff) +7 -0
+
+ ibv_list = ibv_get_device_list(&num_devices);
+ for (ibv_idx = 0; ibv_idx < num_devices; ibv_idx++) {
+         struct ibv_device *ibdev = ibv_list[ibv_idx];
+         struct rte_pci_addr pci_addr;
+
+         DRV_LOG(INFO, "Probe device name %s dev_name %s

ibdev_path %s",

Quoted 27 lines

+                 ibdev->name, ibdev->dev_name, ibdev- ibdev_path);

(quoted diff) +25 -0
+
+         if (mana_ibv_device_to_pci_addr(ibdev, &pci_addr))
+                 continue;
+
+         /* Ignore if this IB device is not this PCI device */
+         if (pci_dev->addr.domain != pci_addr.domain ||
+             pci_dev->addr.bus != pci_addr.bus ||
+             pci_dev->addr.devid != pci_addr.devid ||
+             pci_dev->addr.function != pci_addr.function)
+                 continue;
+
+         ctx = ibv_open_device(ibdev);
+         if (!ctx) {
+                 DRV_LOG(ERR, "Failed to open IB device %s",
+                         ibdev->name);
+                 continue;
+         }
+
+         ret = ibv_query_device_ex(ctx, NULL, &dev_attr);
+         DRV_LOG(INFO, "dev_attr.orig_attr.phys_port_cnt %u",
+                 dev_attr.orig_attr.phys_port_cnt);
+         found_port = false;
+
+         for (port = 1; port <= dev_attr.orig_attr.phys_port_cnt;
+              port++) {

Review

Quoted 10 lines
(quoted diff) +10 -0
+                 struct ibv_parent_domain_init_attr attr = {};
+                 struct rte_ether_addr addr;
+                 char address[64];
+                 char name[RTE_ETH_NAME_MAX_LEN];
+
+                 ret = get_port_mac(ibdev, port, &addr);
+                 if (ret)
+                         continue;
+
+                 if (mac_addr && !rte_is_same_ether_addr(&addr,

mac_addr))

Quoted 3 lines

+                         continue;
+
+                 rte_ether_format_addr(address, sizeof(address),

&addr);

Quoted 1 line

+                 DRV_LOG(INFO, "device located port %u address

%s",

Quoted 5 lines

+                         port, address);
+                 found_port = true;

(quoted diff) +3 -0
+
+                 priv = rte_zmalloc_socket(NULL, sizeof(*priv),
+                                           RTE_CACHE_LINE_SIZE,

Review

Quoted 10 lines
(quoted diff) +10 -0
+                                           SOCKET_ID_ANY);
+                 if (!priv) {
+                         ret = -ENOMEM;
+                         goto failed;
+                 }
+
+                 snprintf(name, sizeof(name), "%s_port%d",
+                          pci_dev->device.name, port);
+
+                 if (rte_eal_process_type() ==

RTE_PROC_SECONDARY) {

Quoted 3 lines

+                         int fd;
+
+                         eth_dev =

rte_eth_dev_attach_secondary(name);

Quoted 2 lines

+                         if (!eth_dev) {
+                                 DRV_LOG(ERR, "Can't attach to dev

%s",

Quoted 8 lines

+                                         name);
+                                 ret = -ENOMEM;
+                                 goto failed;
+                         }
+
+                         eth_dev->device = &pci_dev->device; +                         eth_dev->dev_ops = &mana_dev_sec_ops; +                         ret = mana_proc_priv_init(eth_dev);

Quoted 8 lines

+                         if (ret)
+                                 goto failed;
+                         priv->process_priv = eth_dev- process_private;
+
+                         /* Get the IB FD from the primary process */
+                         fd =

mana_mp_req_verbs_cmd_fd(eth_dev);

Quoted 2 lines

+                         if (fd < 0) {
+                                 DRV_LOG(ERR, "Failed to get FD %d",

fd);

Quoted 5 lines

+                                 ret = -ENODEV;
+                                 goto failed;
+                         }
+
+                         ret =

mana_map_doorbell_secondary(eth_dev, fd);

Quoted 2 lines

+                         if (ret) {
+                                 DRV_LOG(ERR, "Failed secondary

map %d",

Quoted 37 lines

+                                         fd);
+                                 goto failed;
+                         }
+
+                         /* fd is no not used after mapping doorbell */
+                         close(fd);
+
+                         rte_spinlock_lock(&mana_shared_data- lock);
+                         mana_shared_data->secondary_cnt++; +                         mana_local_data.secondary_cnt++; +                         rte_spinlock_unlock(&mana_shared_data- lock);

(quoted diff) +19 -0
+
+                         rte_eth_copy_pci_info(eth_dev, pci_dev);
+                         rte_eth_dev_probing_finish(eth_dev);
+
+                         /* Impossible to have more than one port
+                          * matching a MAC address
+                          */
+                         continue;
+                 }
+
+                 eth_dev = rte_eth_dev_allocate(name);
+                 if (!eth_dev) {
+                         ret = -ENOMEM;
+                         goto failed;
+                 }
+
+                 eth_dev->data->mac_addrs =
+                         rte_calloc("mana_mac", 1,
+                                    sizeof(struct

rte_ether_addr), 0);
+                 if (!eth_dev->data->mac_addrs) { +                         ret = -ENOMEM;
+                         goto failed;

Quoted 8 lines

+                 }
+
+                 rte_ether_addr_copy(&addr, eth_dev->data- mac_addrs);
+
+                 priv->ib_pd = ibv_alloc_pd(ctx);
+                 if (!priv->ib_pd) {
+                         DRV_LOG(ERR, "ibv_alloc_pd failed port %d",

port);

Quoted 7 lines

+                         ret = -ENOMEM;
+                         goto failed;
+                 }
+
+                 /* Create a parent domain with the port number */ +                 attr.pd = priv->ib_pd;
+                 attr.comp_mask =

IBV_PARENT_DOMAIN_INIT_ATTR_PD_CONTEXT;

Quoted 2 lines

+                 attr.pd_context = (void *)(uint64_t)port; +                 priv->ib_parent_pd = ibv_alloc_parent_domain(ctx,

&attr);

Quoted 4 lines

+                 if (!priv->ib_parent_pd) {
+                         DRV_LOG(ERR,
+                                 "ibv_alloc_parent_domain failed port

%d",

Quoted 16 lines

+                                 port);
+                         ret = -ENOMEM;
+                         goto failed;
+                 }

(quoted diff) +12 -0
+
+                 priv->ib_ctx = ctx;
+                 priv->port_id = eth_dev->data->port_id;
+                 priv->dev_port = port;
+                 eth_dev->data->dev_private = priv;
+                 priv->dev_data = eth_dev->data;
+
+                 priv->max_rx_queues = dev_attr.orig_attr.max_qp;
+                 priv->max_tx_queues = dev_attr.orig_attr.max_qp;
+
+                 priv->max_rx_desc =
+                         RTE_MIN(dev_attr.orig_attr.max_qp_wr,

Review

Quoted 10 lines
(quoted diff) +10 -0
+                                 dev_attr.orig_attr.max_cqe);
+                 priv->max_tx_desc =
+                         RTE_MIN(dev_attr.orig_attr.max_qp_wr,
+                                 dev_attr.orig_attr.max_cqe);
+
+                 priv->max_send_sge = dev_attr.orig_attr.max_sge;
+                 priv->max_recv_sge = dev_attr.orig_attr.max_sge;
+
+                 priv->max_mr = dev_attr.orig_attr.max_mr;
+                 priv->max_mr_size =

dev_attr.orig_attr.max_mr_size;

Quoted 2 lines

+
+                 DRV_LOG(INFO, "dev %s max queues %d desc %d

sge %d",

Review

Quoted 9 lines

+                         name, priv->max_rx_queues, priv- max_rx_desc,
+                         priv->max_send_sge);

(quoted diff) +6 -0
+
+                 rte_spinlock_lock(&mana_shared_data->lock);
+                 mana_shared_data->primary_cnt++;
+                 rte_spinlock_unlock(&mana_shared_data->lock);
+
+                 eth_dev->data->dev_flags |=

RTE_ETH_DEV_INTR_RMV;

Review

Quoted 5 lines
(quoted diff) +5 -0
+
+                 eth_dev->device = &pci_dev->device;
+                 eth_dev->data->dev_flags |=
+                         RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
+

Please do not use the temporary macro. Please review this patch:

f30e69b41f94 ("ethdev: add device flag to bypass auto-filled queue xstats")

Quoted 8 lines
Quoted 2 lines

This patch requires that per queue statistics are filled in .xstats_get() by PMD.

Thanks for pointing this out.

It seems some PMDs are still depending on this flag for xstats.

MANA doesn't implement xstats_get() currently, this flag is useful. Is it

okay to keep using this flag before it's finally the time to remove it from all
PMDs, or when MANA implements xstats?
Yes, your xstats doesn't implement now. Per queue stats should be filled in
xstats API, and the stats API cannot see per queue stats, so stats API in driver
shouldn't fill it(suggest that delete it from patch 17/18).

Quoted 2 lines

I guess this flag can be removed if PMD does not support xstats.

Quoted 1 line
Quoted 7 lines

I don't understand your suggestion. An application can call rte_eth_stats_get() to get port stats, and this will call into stats_get() in the driver, as implemented in patch 17/18.

When flag RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS  is set, an application can also use rte_eth_xstats_get() to get port stats even the driver doesn't implement xstats_get().

Quoted 8 lines

I think new PMD should follow the announced switch Ferruh mentioned, otherwise, the switch will never be completed.

Suggest that mana driver can implement a simple xstats_get() to fill per queue stats if you want to support per queue stats.

@Ferruh, what do you think?

Hi Huisong,

Thanks for reminding it, yes it makes sense to implement new method in new drivers.

Long,

There is a long term plan to move queue stats from basic stats structure to xstats. The reason behind is increasing number of queues makes basis stats struct too big, on the other hand xstats is more flexible and no fixes size array is required.

You can remove the 'RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS' flag and driver
won't support queue stats in xstats by default. Instead to have that support you will need to implement xstats, later or in this set. When queue stats implemented in xstats, please remember to remove updating 'stats->q_*' in basic stats.

Quoted 4 lines

Also in 17/18, the feature 'Stats per queue' seems added, but that is not correct, feature name is misleading here. But it is about queue stats mapping, please check 'doc/guides/nics/features.rst'. So can you please drop that feature.

Thank you for clearing the confusion. I'm removing "Stats per queue" in doc/guides/nics/features/mana.ini. The other parts of patch 17/18 are still relevant so not changing them.

Also removing 'RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS' as suggested.

#10 lore raw

Re: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

In reply to [email protected]
Quoted 7 lines · On 2022/8/31 6:51, [email protected] wrote:

From: Long Li <[email protected]>

MANA is a PCI device. It uses IB verbs to access hardware through the kernel RDMA layer. This patch introduces build environment and basic device probe functions.

...

Quoted 15 lines
drivers/net/mana/mp.c new file +15 -0
+static int mana_mp_primary_handle(const struct rte_mp_msg *mp_msg,
+				  const void *peer)
+{
+	struct rte_eth_dev *dev;
+	const struct mana_mp_param *param =
+		(const struct mana_mp_param *)mp_msg->param;
+	struct rte_mp_msg mp_res = { 0 };
+	struct mana_mp_param *res = (struct mana_mp_param *)mp_res.param;
+	int ret;
+	struct mana_priv *priv;
+
+	if (!rte_eth_dev_is_valid_port(param->port_id)) {
+		DRV_LOG(ERR, "MP handle port ID %u invalid", param->port_id);
+		return -ENODEV;
+	}

drivers/net/mana/mp.c line 52

Quoted 10 lines
drivers/net/mana/mp.c new file +10 -0
+
+	dev = &rte_eth_devices[param->port_id];
+	priv = dev->data->dev_private;
+
+	mp_init_msg(&mp_res, param->type, param->port_id);
+
+	switch (param->type) {
+	case MANA_MP_REQ_VERBS_CMD_FD:
+		mp_res.num_fds = 1;
+		mp_res.fds[0] = priv->ib_ctx->cmd_fd;

The cmd_fd is system level handler?

If it's process private handler, it should not used directly in another process.

Quoted 13 lines
drivers/net/mana/mp.c new file +13 -0
+		res->result = 0;
+		ret = rte_mp_reply(&mp_res, peer);
+		break;
+
+	default:
+		DRV_LOG(ERR, "Port %u unknown primary MP type %u",
+			param->port_id, param->type);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
#11 lore raw

RE: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

Quoted 43 lines

Subject: Re: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

Quoted 7 lines · On 2022/8/31 6:51, [email protected] wrote:

From: Long Li <[email protected]>

MANA is a PCI device. It uses IB verbs to access hardware through the kernel RDMA layer. This patch introduces build environment and basic device probe functions.

...

drivers/net/mana/mp.c

Quoted 8 lines
drivers/net/mana/mp.c new file +8 -0
+static int mana_mp_primary_handle(const struct rte_mp_msg *mp_msg,
+				  const void *peer)
+{
+	struct rte_eth_dev *dev;
+	const struct mana_mp_param *param =
+		(const struct mana_mp_param *)mp_msg->param;
+	struct rte_mp_msg mp_res = { 0 };
+	struct mana_mp_param *res = (struct mana_mp_param

*)mp_res.param;

Quoted 7 lines
drivers/net/mana/mp.c new file +7 -0
+	int ret;
+	struct mana_priv *priv;
+
+	if (!rte_eth_dev_is_valid_port(param->port_id)) {
+		DRV_LOG(ERR, "MP handle port ID %u invalid", param->port_id);
+		return -ENODEV;
+	}

drivers/net/mana/mp.c line 52

Quoted 10 lines
drivers/net/mana/mp.c new file +10 -0
+
+	dev = &rte_eth_devices[param->port_id];
+	priv = dev->data->dev_private;
+
+	mp_init_msg(&mp_res, param->type, param->port_id);
+
+	switch (param->type) {
+	case MANA_MP_REQ_VERBS_CMD_FD:
+		mp_res.num_fds = 1;
+		mp_res.fds[0] = priv->ib_ctx->cmd_fd;

The cmd_fd is system level handler?

Quoted 1 line

If it's process private handler, it should not used directly in another process.

According to rte_mp_xxx semantics, the file handle is duplicated to another process. It's not directly used. It's required for secondary process to map to the same doorbell pages.

Quoted 14 lines
Quoted 14 lines
drivers/net/mana/mp.c new file +13 -0
+		res->result = 0;
+		ret = rte_mp_reply(&mp_res, peer);
+		break;
+
+	default:
+		DRV_LOG(ERR, "Port %u unknown primary MP type %u",
+			param->port_id, param->type);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
#12 lore raw

Re: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

Quoted 41 lines · Long Li
Quoted 41 lines

Subject: Re: [Patch v6 01/18] net/mana: add basic driver, build environment and doc

Quoted 7 lines · On 2022/8/31 6:51, [email protected] wrote:

From: Long Li <[email protected]>

MANA is a PCI device. It uses IB verbs to access hardware through the kernel RDMA layer. This patch introduces build environment and basic device probe functions.

...

drivers/net/mana/mp.c

Quoted 8 lines
drivers/net/mana/mp.c new file +8 -0
+static int mana_mp_primary_handle(const struct rte_mp_msg *mp_msg,
+				  const void *peer)
+{
+	struct rte_eth_dev *dev;
+	const struct mana_mp_param *param =
+		(const struct mana_mp_param *)mp_msg->param;
+	struct rte_mp_msg mp_res = { 0 };
+	struct mana_mp_param *res = (struct mana_mp_param

*)mp_res.param;

Quoted 7 lines
drivers/net/mana/mp.c new file +7 -0
+	int ret;
+	struct mana_priv *priv;
+
+	if (!rte_eth_dev_is_valid_port(param->port_id)) {
+		DRV_LOG(ERR, "MP handle port ID %u invalid", param->port_id);
+		return -ENODEV;
+	}

drivers/net/mana/mp.c line 52

Quoted 10 lines
drivers/net/mana/mp.c new file +10 -0
+
+	dev = &rte_eth_devices[param->port_id];
+	priv = dev->data->dev_private;
+
+	mp_init_msg(&mp_res, param->type, param->port_id);
+
+	switch (param->type) {
+	case MANA_MP_REQ_VERBS_CMD_FD:
+		mp_res.num_fds = 1;
+		mp_res.fds[0] = priv->ib_ctx->cmd_fd;

The cmd_fd is system level handler?

Quoted 2 lines
Quoted 1 line

If it's process private handler, it should not used directly in another process.

According to rte_mp_xxx semantics, the file handle is duplicated to another process. It's not directly used. It's required for secondary process to map to the same doorbell pages.

You are right. I notice the rte_mp_xx use AF_UNIX which could process it.

Thanks for clarify.

Quoted 14 lines
Quoted 14 lines
Quoted 14 lines
drivers/net/mana/mp.c new file +13 -0
+		res->result = 0;
+		ret = rte_mp_reply(&mp_res, peer);
+		break;
+
+	default:
+		DRV_LOG(ERR, "Port %u unknown primary MP type %u",
+			param->port_id, param->type);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
#13 lore raw

PATCH v6 2/18 net/mana: add device configuration and stop

In reply to [email protected]

From: Long Li <[email protected]>

MANA defines its memory allocation functions to override IB layer default functions to allocate device queues. This patch adds the code for device configuration and stop.

---
Change log:
v2:
Removed validation for offload settings in mana_dev_configure().

 drivers/net/mana/mana.c | 75 +++++++++++++++++++++++++++++++++++++++--
 drivers/net/mana/mana.h |  3 ++
 2 files changed, 76 insertions(+), 2 deletions(-)
drivers/net/mana/mana.c +73 -2
index cb59eb6882..147ab144d5 100644
@@ -40,7 +40,79 @@ static rte_spinlock_t mana_shared_data_lock = RTE_SPINLOCK_INITIALIZER;
 int mana_logtype_driver;
 int mana_logtype_init;
 
+void *mana_alloc_verbs_buf(size_t size, void *data)
+{
+	void *ret;
+	size_t alignment = rte_mem_page_size();
+	int socket = (int)(uintptr_t)data;
+
+	DRV_LOG(DEBUG, "size=%zu socket=%d", size, socket);
+
+	if (alignment == (size_t)-1) {
+		DRV_LOG(ERR, "Failed to get mem page size");
+		rte_errno = ENOMEM;
+		return NULL;
+	}
+
+	ret = rte_zmalloc_socket("mana_verb_buf", size, alignment, socket);
+	if (!ret && size)
+		rte_errno = ENOMEM;
+	return ret;
+}
+
+void mana_free_verbs_buf(void *ptr, void *data __rte_unused)
+{
+	rte_free(ptr);
+}
+
+static int mana_dev_configure(struct rte_eth_dev *dev)
+{
+	struct mana_priv *priv = dev->data->dev_private;
+	struct rte_eth_conf *dev_conf = &dev->data->dev_conf;
+
+	if (dev_conf->rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG)
+		dev_conf->rxmode.offloads |= DEV_RX_OFFLOAD_RSS_HASH;
+
+	if (dev->data->nb_rx_queues != dev->data->nb_tx_queues) {
+		DRV_LOG(ERR, "Only support equal number of rx/tx queues");
+		return -EINVAL;
+	}
+
+	if (!rte_is_power_of_2(dev->data->nb_rx_queues)) {
+		DRV_LOG(ERR, "number of TX/RX queues must be power of 2");
+		return -EINVAL;
+	}
+
+	priv->num_queues = dev->data->nb_rx_queues;
+
+	manadv_set_context_attr(priv->ib_ctx, MANADV_CTX_ATTR_BUF_ALLOCATORS,
+				(void *)((uintptr_t)&(struct manadv_ctx_allocators){
+					.alloc = &mana_alloc_verbs_buf,
+					.free = &mana_free_verbs_buf,
+					.data = 0,
+				}));
+
+	return 0;
+}
+
+static int
+mana_dev_close(struct rte_eth_dev *dev)
+{
+	struct mana_priv *priv = dev->data->dev_private;
+	int ret;
+
+	ret = ibv_close_device(priv->ib_ctx);
+	if (ret) {
+		ret = errno;
+		return ret;
+	}
+
+	return 0;
+}
+
 const struct eth_dev_ops mana_dev_ops = {
+	.dev_configure		= mana_dev_configure,
+	.dev_close		= mana_dev_close,
 };
 
 const struct eth_dev_ops mana_dev_sec_ops = {
@@ -627,8 +699,7 @@ static int mana_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 
 static int mana_dev_uninit(struct rte_eth_dev *dev)
 {
-	RTE_SET_USED(dev);
-	return 0;
+	return mana_dev_close(dev);
 }
 
 static int mana_pci_remove(struct rte_pci_device *pci_dev)
drivers/net/mana/mana.h +3 -0
index e30c030b4e..66873394b9 100644
@@ -207,4 +207,7 @@ int mana_mp_req_verbs_cmd_fd(struct rte_eth_dev *dev);
 
 void mana_mp_req_on_rxtx(struct rte_eth_dev *dev, enum mana_mp_req_type type);
 
+void *mana_alloc_verbs_buf(size_t size, void *data);
+void mana_free_verbs_buf(void *ptr, void *data __rte_unused);
+
 #endif
Signature · 1 line
2.17.1
#14 lore raw

PATCH v6 3/18 net/mana: add function to report support ptypes

In reply to [email protected]

From: Long Li <[email protected]>

Report supported protocol types.

---
 drivers/net/mana/mana.c | 16 ++++++++++++++++
 drivers/net/mana/mana.h |  2 --
 2 files changed, 16 insertions(+), 2 deletions(-)
drivers/net/mana/mana.c +16 -0
index 147ab144d5..4559632056 100644
@@ -110,9 +110,25 @@ mana_dev_close(struct rte_eth_dev *dev)
 	return 0;
 }
 
+static const uint32_t *mana_supported_ptypes(struct rte_eth_dev *dev __rte_unused)
+{
+	static const uint32_t ptypes[] = {
+		RTE_PTYPE_L2_ETHER,
+		RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
+		RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
+		RTE_PTYPE_L4_FRAG,
+		RTE_PTYPE_L4_TCP,
+		RTE_PTYPE_L4_UDP,
+		RTE_PTYPE_UNKNOWN
+	};
+
+	return ptypes;
+}
+
 const struct eth_dev_ops mana_dev_ops = {
 	.dev_configure		= mana_dev_configure,
 	.dev_close		= mana_dev_close,
+	.dev_supported_ptypes_get = mana_supported_ptypes,
 };
 
 const struct eth_dev_ops mana_dev_sec_ops = {
drivers/net/mana/mana.h +0 -2
index 66873394b9..c433940022 100644
@@ -168,8 +168,6 @@ extern int mana_logtype_init;
 
 #define PMD_INIT_FUNC_TRACE() PMD_INIT_LOG(DEBUG, " >>")
 
-const uint32_t *mana_supported_ptypes(struct rte_eth_dev *dev);
-
 uint16_t mana_rx_burst_removed(void *dpdk_rxq, struct rte_mbuf **pkts,
 			       uint16_t pkts_n);
 
Signature · 1 line
2.17.1
#15 lore raw

PATCH v6 4/18 net/mana: add link update

In reply to [email protected]

From: Long Li <[email protected]>

The carrier state is managed by the Azure host. MANA runs as a VF and always reports "up".

---
 doc/guides/nics/features/mana.ini |  1 +
 drivers/net/mana/mana.c           | 17 +++++++++++++++++
 2 files changed, 18 insertions(+)
doc/guides/nics/features/mana.ini +1 -0
index b92a27374c..62554b0a0a 100644
@@ -4,6 +4,7 @@
 ; Refer to default.ini for the full list of available PMD features.
 ;
 [Features]
+Link status          = P
 Linux                = Y
 Multiprocess aware   = Y
 Usage doc            = Y
drivers/net/mana/mana.c +17 -0
index 4559632056..b77d0c29b0 100644
@@ -125,10 +125,27 @@ static const uint32_t *mana_supported_ptypes(struct rte_eth_dev *dev __rte_unuse
 	return ptypes;
 }
 
+static int mana_dev_link_update(struct rte_eth_dev *dev,
+				int wait_to_complete __rte_unused)
+{
+	struct rte_eth_link link;
+
+	/* MANA has no concept of carrier state, always reporting UP */
+	link = (struct rte_eth_link) {
+		.link_duplex = RTE_ETH_LINK_FULL_DUPLEX,
+		.link_autoneg = RTE_ETH_LINK_SPEED_FIXED,
+		.link_speed = RTE_ETH_SPEED_NUM_200G,
+		.link_status = RTE_ETH_LINK_UP,
+	};
+
+	return rte_eth_linkstatus_set(dev, &link);
+}
+
 const struct eth_dev_ops mana_dev_ops = {
 	.dev_configure		= mana_dev_configure,
 	.dev_close		= mana_dev_close,
 	.dev_supported_ptypes_get = mana_supported_ptypes,
+	.link_update		= mana_dev_link_update,
 };
 
 const struct eth_dev_ops mana_dev_sec_ops = {
Signature · 1 line
2.17.1
#16 lore raw

PATCH v6 5/18 net/mana: add function for device removal interrupts

In reply to [email protected]

From: Long Li <[email protected]>

MANA supports PCI hot plug events. Add this interrupt to DPDK core so its parent PMD can detect device removal during Azure servicing or live migration.

---
 doc/guides/nics/features/mana.ini |  1 +
 drivers/net/mana/mana.c           | 97 +++++++++++++++++++++++++++++++
 drivers/net/mana/mana.h           |  1 +
 3 files changed, 99 insertions(+)
doc/guides/nics/features/mana.ini +1 -0
index 62554b0a0a..8043e11f99 100644
@@ -7,5 +7,6 @@
 Link status          = P
 Linux                = Y
 Multiprocess aware   = Y
+Removal event        = Y
 Usage doc            = Y
 x86-64               = Y
drivers/net/mana/mana.c +97 -0

121 lines not on this page · raw message

drivers/net/mana/mana.h +1 -0
index c433940022..f97eed2e81 100644
@@ -72,6 +72,7 @@ struct mana_priv {
 	uint8_t ind_table_key[40];
 	struct ibv_qp *rwq_qp;
 	void *db_page;
+	struct rte_intr_handle *intr_handle;
 	int max_rx_queues;
 	int max_tx_queues;
 	int max_rx_desc;
Signature · 1 line
2.17.1
#17 lore raw

PATCH v6 6/18 net/mana: add device info

In reply to [email protected]

From: Long Li <[email protected]>

Add the function to get device info.

---
 doc/guides/nics/features/mana.ini |  1 +
 drivers/net/mana/mana.c           | 82 +++++++++++++++++++++++++++++++
 2 files changed, 83 insertions(+)
doc/guides/nics/features/mana.ini +1 -0
index 8043e11f99..566b3e8770 100644
@@ -8,5 +8,6 @@ Link status          = P
 Linux                = Y
 Multiprocess aware   = Y
 Removal event        = Y
+Speed capabilities   = P
 Usage doc            = Y
 x86-64               = Y
drivers/net/mana/mana.c +82 -0

99 lines not on this page · raw message

Signature · 1 line
2.17.1
#18 lore raw

Re: [Patch v6 06/18] net/mana: add device info

Quoted 35 lines · On 2022/8/31 6:51, [email protected] wrote:

From: Long Li <[email protected]>

Add the function to get device info.

---
 doc/guides/nics/features/mana.ini |  1 +
 drivers/net/mana/mana.c           | 82 +++++++++++++++++++++++++++++++
 2 files changed, 83 insertions(+)
doc/guides/nics/features/mana.ini +1 -0
index 8043e11f99..566b3e8770 100644
@@ -8,5 +8,6 @@ Link status          = P
 Linux                = Y
 Multiprocess aware   = Y
 Removal event        = Y
+Speed capabilities   = P
 Usage doc            = Y
 x86-64               = Y
drivers/net/mana/mana.c +6 -0
index c9591035ac..e1550b3c08 100644
@@ -116,6 +116,86 @@ mana_dev_close(struct rte_eth_dev *dev)
 	return 0;
 }
 
+static int mana_dev_info_get(struct rte_eth_dev *dev,
+			     struct rte_eth_dev_info *dev_info)
+{
+	struct mana_priv *priv = dev->data->dev_private;
+
+	dev_info->max_mtu = RTE_ETHER_MTU;

...

drivers/net/mana/mana.c mana_dev_close(struct rte_eth_dev *dev) · line 184

Quoted 7 lines
drivers/net/mana/mana.c +7 -0
+	dev_info->tx_desc_lim.nb_max = priv->max_tx_desc;
+	dev_info->tx_desc_lim.nb_align = MIN_BUFFERS_PER_QUEUE;
+	dev_info->tx_desc_lim.nb_seg_max = priv->max_send_sge;
+	dev_info->rx_desc_lim.nb_mtu_seg_max = priv->max_recv_sge;
+
+	/* Speed */
+	dev_info->speed_capa = ETH_LINK_SPEED_100G;

I notice "[Patch v6 04/18] net/mana: add link update" report always 200G, why here is 100G?

Quoted 14 lines
drivers/net/mana/mana.c +14 -0
+
+	/* RX params */
+	dev_info->default_rxportconf.burst_size = 1;
+	dev_info->default_rxportconf.ring_size = MAX_RECEIVE_BUFFERS_PER_QUEUE;
+	dev_info->default_rxportconf.nb_queues = 1;
+
+	/* TX params */
+	dev_info->default_txportconf.burst_size = 1;
+	dev_info->default_txportconf.ring_size = MAX_SEND_BUFFERS_PER_QUEUE;
+	dev_info->default_txportconf.nb_queues = 1;
+
+	return 0;
+}
+

...

#19 lore raw

RE: [Patch v6 06/18] net/mana: add device info

Quoted 41 lines

Subject: Re: [Patch v6 06/18] net/mana: add device info

Quoted 35 lines · On 2022/8/31 6:51, [email protected] wrote:

From: Long Li <[email protected]>

Add the function to get device info.

---
 doc/guides/nics/features/mana.ini |  1 +
 drivers/net/mana/mana.c           | 82 +++++++++++++++++++++++++++++++
 2 files changed, 83 insertions(+)
doc/guides/nics/features/mana.ini +1 -0
index 8043e11f99..566b3e8770 100644
@@ -8,5 +8,6 @@ Link status          = P
 Linux                = Y
 Multiprocess aware   = Y
 Removal event        = Y
+Speed capabilities   = P
 Usage doc            = Y
 x86-64               = Y
drivers/net/mana/mana.c index renamed from drivers/net/mana/mana.c +0 -0

c9591035ac..e1550b3c08 100644

drivers/net/mana/mana.c +5 -0
@@ -116,6 +116,86 @@ mana_dev_close(struct rte_eth_dev *dev)
 	return 0;
 }
 
+static int mana_dev_info_get(struct rte_eth_dev *dev,
+			     struct rte_eth_dev_info *dev_info) {
+	struct mana_priv *priv = dev->data->dev_private;
+
+	dev_info->max_mtu = RTE_ETHER_MTU;

...

Quoted 10 lines

drivers/net/mana/mana.c mana_dev_close(struct rte_eth_dev *dev) · line 184

Quoted 7 lines
drivers/net/mana/mana.c +7 -0
+	dev_info->tx_desc_lim.nb_max = priv->max_tx_desc;
+	dev_info->tx_desc_lim.nb_align = MIN_BUFFERS_PER_QUEUE;
+	dev_info->tx_desc_lim.nb_seg_max = priv->max_send_sge;
+	dev_info->rx_desc_lim.nb_mtu_seg_max = priv->max_recv_sge;
+
+	/* Speed */
+	dev_info->speed_capa = ETH_LINK_SPEED_100G;

I notice "[Patch v6 04/18] net/mana: add link update" report always 200G, why here is 100G?

Thanks for pointing this out. I will fix patch 04.

Quoted 19 lines

drivers/net/mana/mana.c mana_dev_close(struct rte_eth_dev *dev)

Quoted 5 lines
drivers/net/mana/mana.c +4 -0
+
+	/* RX params */
+	dev_info->default_rxportconf.burst_size = 1;
+	dev_info->default_rxportconf.ring_size =

MAX_RECEIVE_BUFFERS_PER_QUEUE;

drivers/net/mana/mana.c mana_dev_close(struct rte_eth_dev *dev)

Quoted 5 lines
drivers/net/mana/mana.c +5 -0
+	dev_info->default_rxportconf.nb_queues = 1;
+
+	/* TX params */
+	dev_info->default_txportconf.burst_size = 1;
+	dev_info->default_txportconf.ring_size =

MAX_SEND_BUFFERS_PER_QUEUE;

Quoted 5 lines
drivers/net/mana/mana.c +5 -0
+	dev_info->default_txportconf.nb_queues = 1;
+
+	return 0;
+}
+

...

#20 lore raw

PATCH v6 7/18 net/mana: add function to configure RSS

In reply to [email protected]

From: Long Li <[email protected]>

Currently this PMD supports RSS configuration when the device is stopped. Configuring RSS in running state will be supported in the future.

---
 doc/guides/nics/features/mana.ini |  1 +
 drivers/net/mana/mana.c           | 61 +++++++++++++++++++++++++++++++
 drivers/net/mana/mana.h           |  1 +
 3 files changed, 63 insertions(+)
doc/guides/nics/features/mana.ini +1 -0
index 566b3e8770..a59c21cc10 100644
@@ -8,6 +8,7 @@ Link status          = P
 Linux                = Y
 Multiprocess aware   = Y
 Removal event        = Y
+RSS hash             = Y
 Speed capabilities   = P
 Usage doc            = Y
 x86-64               = Y
drivers/net/mana/mana.c +61 -0

73 lines not on this page · raw message

drivers/net/mana/mana.h +1 -0
index f97eed2e81..33f68b3d1b 100644
@@ -72,6 +72,7 @@ struct mana_priv {
 	uint8_t ind_table_key[40];
 	struct ibv_qp *rwq_qp;
 	void *db_page;
+	struct rte_eth_rss_conf rss_conf;
 	struct rte_intr_handle *intr_handle;
 	int max_rx_queues;
 	int max_tx_queues;
Signature · 1 line
2.17.1
#21 lore raw

PATCH v6 8/18 net/mana: add function to configure RX queues

In reply to [email protected]

From: Long Li <[email protected]>

RX hardware queue is allocated when starting the queue. This function is for queue configuration pre starting.

---
 drivers/net/mana/mana.c | 68 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)
drivers/net/mana/mana.c +68 -0
index cb136f24c1..d03adab041 100644
@@ -196,6 +196,16 @@ static int mana_dev_info_get(struct rte_eth_dev *dev,
 	return 0;
 }
 
+static void mana_dev_rx_queue_info(struct rte_eth_dev *dev, uint16_t queue_id,
+				   struct rte_eth_rxq_info *qinfo)
+{
+	struct mana_rxq *rxq = dev->data->rx_queues[queue_id];
+
+	qinfo->mp = rxq->mp;
+	qinfo->nb_desc = rxq->num_desc;
+	qinfo->conf.offloads = dev->data->dev_conf.rxmode.offloads;
+}
+
 static const uint32_t *mana_supported_ptypes(struct rte_eth_dev *dev __rte_unused)
 {
 	static const uint32_t ptypes[] = {
@@ -270,6 +280,61 @@ static int mana_rss_hash_conf_get(struct rte_eth_dev *dev,
 	return 0;
 }
 
+static int mana_dev_rx_queue_setup(struct rte_eth_dev *dev,
+				   uint16_t queue_idx, uint16_t nb_desc,
+				   unsigned int socket_id,
+				   const struct rte_eth_rxconf *rx_conf __rte_unused,
+				   struct rte_mempool *mp)
+{
+	struct mana_priv *priv = dev->data->dev_private;
+	struct mana_rxq *rxq;
+	int ret;
+
+	rxq = rte_zmalloc_socket("mana_rxq", sizeof(*rxq), 0, socket_id);
+	if (!rxq) {
+		DRV_LOG(ERR, "failed to allocate rxq");
+		return -ENOMEM;
+	}
+
+	DRV_LOG(DEBUG, "idx %u nb_desc %u socket %u",
+		queue_idx, nb_desc, socket_id);
+
+	rxq->socket = socket_id;
+
+	rxq->desc_ring = rte_zmalloc_socket("mana_rx_mbuf_ring",
+					    sizeof(struct mana_rxq_desc) *
+						nb_desc,
+					    RTE_CACHE_LINE_SIZE, socket_id);
+
+	if (!rxq->desc_ring) {
+		DRV_LOG(ERR, "failed to allocate rxq desc_ring");
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	rxq->num_desc = nb_desc;
+
+	rxq->priv = priv;
+	rxq->num_desc = nb_desc;
+	rxq->mp = mp;
+	dev->data->rx_queues[queue_idx] = rxq;
+
+	return 0;
+
+fail:
+	rte_free(rxq->desc_ring);
+	rte_free(rxq);
+	return ret;
+}
+
+static void mana_dev_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
+{
+	struct mana_rxq *rxq = dev->data->rx_queues[qid];
+
+	rte_free(rxq->desc_ring);
+	rte_free(rxq);
+}
+
 static int mana_dev_link_update(struct rte_eth_dev *dev,
 				int wait_to_complete __rte_unused)
 {
@@ -290,9 +355,12 @@ const struct eth_dev_ops mana_dev_ops = {
 	.dev_configure		= mana_dev_configure,
 	.dev_close		= mana_dev_close,
 	.dev_infos_get		= mana_dev_info_get,
+	.rxq_info_get		= mana_dev_rx_queue_info,
 	.dev_supported_ptypes_get = mana_supported_ptypes,
 	.rss_hash_update	= mana_rss_hash_update,
 	.rss_hash_conf_get	= mana_rss_hash_conf_get,
+	.rx_queue_setup		= mana_dev_rx_queue_setup,
+	.rx_queue_release	= mana_dev_rx_queue_release,
 	.link_update		= mana_dev_link_update,
 };
 
Signature · 1 line
2.17.1
#22 lore raw

PATCH v6 9/18 net/mana: add function to configure TX queues

In reply to [email protected]

From: Long Li <[email protected]>

TX hardware queue is allocated when starting the queue, this is for pre configuration.

---
 drivers/net/mana/mana.c | 65 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)
drivers/net/mana/mana.c +65 -0
index d03adab041..490686f404 100644
@@ -196,6 +196,15 @@ static int mana_dev_info_get(struct rte_eth_dev *dev,
 	return 0;
 }
 
+static void mana_dev_tx_queue_info(struct rte_eth_dev *dev, uint16_t queue_id,
+			    struct rte_eth_txq_info *qinfo)
+{
+	struct mana_txq *txq = dev->data->tx_queues[queue_id];
+
+	qinfo->conf.offloads = dev->data->dev_conf.txmode.offloads;
+	qinfo->nb_desc = txq->num_desc;
+}
+
 static void mana_dev_rx_queue_info(struct rte_eth_dev *dev, uint16_t queue_id,
 				   struct rte_eth_rxq_info *qinfo)
 {
@@ -280,6 +289,59 @@ static int mana_rss_hash_conf_get(struct rte_eth_dev *dev,
 	return 0;
 }
 
+static int mana_dev_tx_queue_setup(struct rte_eth_dev *dev,
+				   uint16_t queue_idx, uint16_t nb_desc,
+				   unsigned int socket_id,
+				   const struct rte_eth_txconf *tx_conf __rte_unused)
+
+{
+	struct mana_priv *priv = dev->data->dev_private;
+	struct mana_txq *txq;
+	int ret;
+
+	txq = rte_zmalloc_socket("mana_txq", sizeof(*txq), 0, socket_id);
+	if (!txq) {
+		DRV_LOG(ERR, "failed to allocate txq");
+		return -ENOMEM;
+	}
+
+	txq->socket = socket_id;
+
+	txq->desc_ring = rte_malloc_socket("mana_tx_desc_ring",
+					   sizeof(struct mana_txq_desc) *
+						nb_desc,
+					   RTE_CACHE_LINE_SIZE, socket_id);
+	if (!txq->desc_ring) {
+		DRV_LOG(ERR, "failed to allocate txq desc_ring");
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	DRV_LOG(DEBUG, "idx %u nb_desc %u socket %u txq->desc_ring %p",
+		queue_idx, nb_desc, socket_id, txq->desc_ring);
+
+	txq->desc_ring_head = 0;
+	txq->desc_ring_tail = 0;
+	txq->priv = priv;
+	txq->num_desc = nb_desc;
+	dev->data->tx_queues[queue_idx] = txq;
+
+	return 0;
+
+fail:
+	rte_free(txq->desc_ring);
+	rte_free(txq);
+	return ret;
+}
+
+static void mana_dev_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
+{
+	struct mana_txq *txq = dev->data->tx_queues[qid];
+
+	rte_free(txq->desc_ring);
+	rte_free(txq);
+}
+
 static int mana_dev_rx_queue_setup(struct rte_eth_dev *dev,
 				   uint16_t queue_idx, uint16_t nb_desc,
 				   unsigned int socket_id,
@@ -355,10 +417,13 @@ const struct eth_dev_ops mana_dev_ops = {
 	.dev_configure		= mana_dev_configure,
 	.dev_close		= mana_dev_close,
 	.dev_infos_get		= mana_dev_info_get,
+	.txq_info_get		= mana_dev_tx_queue_info,
 	.rxq_info_get		= mana_dev_rx_queue_info,
 	.dev_supported_ptypes_get = mana_supported_ptypes,
 	.rss_hash_update	= mana_rss_hash_update,
 	.rss_hash_conf_get	= mana_rss_hash_conf_get,
+	.tx_queue_setup		= mana_dev_tx_queue_setup,
+	.tx_queue_release	= mana_dev_tx_queue_release,
 	.rx_queue_setup		= mana_dev_rx_queue_setup,
 	.rx_queue_release	= mana_dev_rx_queue_release,
 	.link_update		= mana_dev_link_update,
Signature · 1 line
2.17.1
#23 lore raw

PATCH v6 10/18 net/mana: implement memory registration

In reply to [email protected]

From: Long Li <[email protected]>

MANA hardware has iommu built-in, that provides hardware safe access to user memory through memory registration. Since memory registration is an expensive operation, this patch implements a two level memory registration cache mechanisum for each queue and for each port.

---
Change log:
v2:
Change all header file functions to start with mana_. Use spinlock in place of rwlock to memory cache access. Remove unused header files.
v4:
Remove extra "\n" in logging function.

 drivers/net/mana/mana.c      |  20 +++
 drivers/net/mana/mana.h      |  39 +++++
 drivers/net/mana/meson.build |   1 +
 drivers/net/mana/mp.c        |  85 +++++++++
 drivers/net/mana/mr.c        | 324 +++++++++++++++++++++++++++++++++++
 5 files changed, 469 insertions(+)
 create mode 100644 drivers/net/mana/mr.c
drivers/net/mana/mana.c +20 -0
index 490686f404..d18cc4ab0e 100644
@@ -103,6 +103,8 @@ mana_dev_close(struct rte_eth_dev *dev)
 	struct mana_priv *priv = dev->data->dev_private;
 	int ret;
 
+	mana_remove_all_mr(priv);
+
 	ret = mana_intr_uninstall(priv);
 	if (ret)
 		return ret;
@@ -317,6 +319,13 @@ static int mana_dev_tx_queue_setup(struct rte_eth_dev *dev,
 		goto fail;
 	}
 
+	ret = mana_mr_btree_init(&txq->mr_btree,
+				 MANA_MR_BTREE_PER_QUEUE_N, socket_id);
+	if (ret) {
+		DRV_LOG(ERR, "Failed to init TXQ MR btree");
+		goto fail;
+	}
+
 	DRV_LOG(DEBUG, "idx %u nb_desc %u socket %u txq->desc_ring %p",
 		queue_idx, nb_desc, socket_id, txq->desc_ring);
 
@@ -338,6 +347,8 @@ static void mana_dev_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
 {
 	struct mana_txq *txq = dev->data->tx_queues[qid];
 
+	mana_mr_btree_free(&txq->mr_btree);
+
 	rte_free(txq->desc_ring);
 	rte_free(txq);
 }
@@ -374,6 +385,13 @@ static int mana_dev_rx_queue_setup(struct rte_eth_dev *dev,
 		goto fail;
 	}
 
+	ret = mana_mr_btree_init(&rxq->mr_btree,
+				 MANA_MR_BTREE_PER_QUEUE_N, socket_id);
+	if (ret) {
+		DRV_LOG(ERR, "Failed to init RXQ MR btree");
+		goto fail;
+	}
+
 	rxq->num_desc = nb_desc;
 
 	rxq->priv = priv;
@@ -393,6 +411,8 @@ static void mana_dev_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
 {
 	struct mana_rxq *rxq = dev->data->rx_queues[qid];
 
+	mana_mr_btree_free(&rxq->mr_btree);
+
 	rte_free(rxq->desc_ring);
 	rte_free(rxq);
 }
drivers/net/mana/mana.h +39 -0
index 33f68b3d1b..9e15b43275 100644
@@ -50,6 +50,22 @@ struct mana_shared_data {
 #define MAX_RECEIVE_BUFFERS_PER_QUEUE	256
 #define MAX_SEND_BUFFERS_PER_QUEUE	256
 
+struct mana_mr_cache {
+	uint32_t	lkey;
+	uintptr_t	addr;
+	size_t		len;
+	void		*verb_obj;
+};
+
+#define MANA_MR_BTREE_CACHE_N	512
+struct mana_mr_btree {
+	uint16_t	len;	/* Used entries */
+	uint16_t	size;	/* Total entries */
+	int		overflow;
+	int		socket;
+	struct mana_mr_cache *table;
+};
+
 struct mana_process_priv {
 	void *db_page;
 };
@@ -82,6 +98,8 @@ struct mana_priv {
 	int max_recv_sge;
 	int max_mr;
 	uint64_t max_mr_size;
+	struct mana_mr_btree mr_btree;
+	rte_spinlock_t	mr_btree_lock;
 };
 
 struct mana_txq_desc {
@@ -131,6 +149,7 @@ struct mana_txq {
 	uint32_t desc_ring_head, desc_ring_tail;
 
 	struct mana_stats stats;
+	struct mana_mr_btree mr_btree;
 	unsigned int socket;
 };
 
@@ -153,6 +172,7 @@ struct mana_rxq {
 	struct mana_gdma_queue gdma_cq;
 
 	struct mana_stats stats;
+	struct mana_mr_btree mr_btree;
 
 	unsigned int socket;
 };
@@ -176,6 +196,24 @@ uint16_t mana_rx_burst_removed(void *dpdk_rxq, struct rte_mbuf **pkts,
 uint16_t mana_tx_burst_removed(void *dpdk_rxq, struct rte_mbuf **pkts,
 			       uint16_t pkts_n);
 
+struct mana_mr_cache *mana_find_pmd_mr(struct mana_mr_btree *local_tree,
+				       struct mana_priv *priv,
+				       struct rte_mbuf *mbuf);
+int mana_new_pmd_mr(struct mana_mr_btree *local_tree, struct mana_priv *priv,
+		    struct rte_mempool *pool);
+void mana_remove_all_mr(struct mana_priv *priv);
+void mana_del_pmd_mr(struct mana_mr_cache *mr);
+
+void mana_mempool_chunk_cb(struct rte_mempool *mp, void *opaque,
+			   struct rte_mempool_memhdr *memhdr, unsigned int idx);
+
+struct mana_mr_cache *mana_mr_btree_lookup(struct mana_mr_btree *bt,
+					   uint16_t *idx,
+					   uintptr_t addr, size_t len);
+int mana_mr_btree_insert(struct mana_mr_btree *bt, struct mana_mr_cache *entry);
+int mana_mr_btree_init(struct mana_mr_btree *bt, int n, int socket);
+void mana_mr_btree_free(struct mana_mr_btree *bt);
+
 /** Request timeout for IPC. */
 #define MANA_MP_REQ_TIMEOUT_SEC 5
 
@@ -204,6 +242,7 @@ int mana_mp_init_secondary(void);
 void mana_mp_uninit_primary(void);
 void mana_mp_uninit_secondary(void);
 int mana_mp_req_verbs_cmd_fd(struct rte_eth_dev *dev);
+int mana_mp_req_mr_create(struct mana_priv *priv, uintptr_t addr, uint32_t len);
 
 void mana_mp_req_on_rxtx(struct rte_eth_dev *dev, enum mana_mp_req_type type);
 
drivers/net/mana/meson.build +1 -0
index 81c4118f53..9771394370 100644
@@ -11,6 +11,7 @@ deps += ['pci', 'bus_pci', 'net', 'eal', 'kvargs']
 
 sources += files(
 	'mana.c',
+	'mr.c',
 	'mp.c',
 )
 
drivers/net/mana/mp.c +85 -0

103 lines not on this page · raw message

drivers/net/mana/mr.c new file +324 -0

324 lines not on this page · raw message

Signature · 1 line
2.17.1
#24 lore raw

PATCH v6 11/18 net/mana: implement the hardware layer operations

In reply to [email protected]

From: Long Li <[email protected]>

The hardware layer of MANA understands the device queue and doorbell formats. Those functions are implemented for use by packet RX/TX code.

---
Change log:
v2:
Remove unused header files.
Rename a camel case.
v5:
Use RTE_BIT32() instead of defining a new BIT()
v6:
add rte_rmb() after reading owner bits

 drivers/net/mana/gdma.c      | 289 +++++++++++++++++++++++++++++++++++
 drivers/net/mana/mana.h      | 183 ++++++++++++++++++++++
 drivers/net/mana/meson.build |   1 +
 3 files changed, 473 insertions(+)
 create mode 100644 drivers/net/mana/gdma.c
drivers/net/mana/gdma.c new file +289 -0
new file mode 100644
index 0000000000..7ad175651e
@@ -0,0 +1,289 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2022 Microsoft Corporation
+ */
+
+#include <ethdev_driver.h>
+#include <rte_io.h>
+
+#include "mana.h"
+
+uint8_t *gdma_get_wqe_pointer(struct mana_gdma_queue *queue)
+{
+	uint32_t offset_in_bytes =
+		(queue->head * GDMA_WQE_ALIGNMENT_UNIT_SIZE) &
+		(queue->size - 1);
+
+	DRV_LOG(DEBUG, "txq sq_head %u sq_size %u offset_in_bytes %u",
+		queue->head, queue->size, offset_in_bytes);
+
+	if (offset_in_bytes + GDMA_WQE_ALIGNMENT_UNIT_SIZE > queue->size)
+		DRV_LOG(ERR, "fatal error: offset_in_bytes %u too big",
+			offset_in_bytes);
+
+	return ((uint8_t *)queue->buffer) + offset_in_bytes;
+}
+
+static uint32_t
+write_dma_client_oob(uint8_t *work_queue_buffer_pointer,
+		     const struct gdma_work_request *work_request,
+		     uint32_t client_oob_size)
+{
+	uint8_t *p = work_queue_buffer_pointer;
+
+	struct gdma_wqe_dma_oob *header = (struct gdma_wqe_dma_oob *)p;
+
+	memset(header, 0, sizeof(struct gdma_wqe_dma_oob));
+	header->num_sgl_entries = work_request->num_sgl_elements;
+	header->inline_client_oob_size_in_dwords =
+		client_oob_size / sizeof(uint32_t);
+	header->client_data_unit = work_request->client_data_unit;
+
+	DRV_LOG(DEBUG, "queue buf %p sgl %u oob_h %u du %u oob_buf %p oob_b %u",
+		work_queue_buffer_pointer, header->num_sgl_entries,
+		header->inline_client_oob_size_in_dwords,
+		header->client_data_unit, work_request->inline_oob_data,
+		work_request->inline_oob_size_in_bytes);
+
+	p += sizeof(struct gdma_wqe_dma_oob);
+	if (work_request->inline_oob_data &&
+	    work_request->inline_oob_size_in_bytes > 0) {
+		memcpy(p, work_request->inline_oob_data,
+		       work_request->inline_oob_size_in_bytes);
+		if (client_oob_size > work_request->inline_oob_size_in_bytes)
+			memset(p + work_request->inline_oob_size_in_bytes, 0,
+			       client_oob_size -
+			       work_request->inline_oob_size_in_bytes);
+	}
+
+	return sizeof(struct gdma_wqe_dma_oob) + client_oob_size;
+}
+
+static uint32_t
+write_scatter_gather_list(uint8_t *work_queue_head_pointer,
+			  uint8_t *work_queue_end_pointer,
+			  uint8_t *work_queue_cur_pointer,
+			  struct gdma_work_request *work_request)
+{
+	struct gdma_sgl_element *sge_list;
+	struct gdma_sgl_element dummy_sgl[1];
+	uint8_t *address;
+	uint32_t size;
+	uint32_t num_sge;
+	uint32_t size_to_queue_end;
+	uint32_t sge_list_size;
+
+	DRV_LOG(DEBUG, "work_queue_cur_pointer %p work_request->flags %x",
+		work_queue_cur_pointer, work_request->flags);
+
+	num_sge = work_request->num_sgl_elements;
+	sge_list = work_request->sgl;
+	size_to_queue_end = (uint32_t)(work_queue_end_pointer -
+				       work_queue_cur_pointer);
+
+	if (num_sge == 0) {
+		/* Per spec, the case of an empty SGL should be handled as
+		 * follows to avoid corrupted WQE errors:
+		 * Write one dummy SGL entry
+		 * Set the address to 1, leave the rest as 0
+		 */
+		dummy_sgl[num_sge].address = 1;
+		dummy_sgl[num_sge].size = 0;
+		dummy_sgl[num_sge].memory_key = 0;
+		num_sge++;
+		sge_list = dummy_sgl;
+	}
+
+	sge_list_size = 0;
+	{
+		address = (uint8_t *)sge_list;
+		size = sizeof(struct gdma_sgl_element) * num_sge;
+		if (size_to_queue_end < size) {
+			memcpy(work_queue_cur_pointer, address,
+			       size_to_queue_end);
+			work_queue_cur_pointer = work_queue_head_pointer;
+			address += size_to_queue_end;
+			size -= size_to_queue_end;
+		}
+
+		memcpy(work_queue_cur_pointer, address, size);
+		sge_list_size = size;
+	}
+
+	DRV_LOG(DEBUG, "sge %u address 0x%" PRIx64 " size %u key %u list_s %u",
+		num_sge, sge_list->address, sge_list->size,
+		sge_list->memory_key, sge_list_size);
+
+	return sge_list_size;
+}
+
+int gdma_post_work_request(struct mana_gdma_queue *queue,
+			   struct gdma_work_request *work_req,
+			   struct gdma_posted_wqe_info *wqe_info)
+{
+	uint32_t client_oob_size =
+		work_req->inline_oob_size_in_bytes >
+				INLINE_OOB_SMALL_SIZE_IN_BYTES ?
+			INLINE_OOB_LARGE_SIZE_IN_BYTES :
+			INLINE_OOB_SMALL_SIZE_IN_BYTES;
+
+	uint32_t sgl_data_size = sizeof(struct gdma_sgl_element) *
+			RTE_MAX((uint32_t)1, work_req->num_sgl_elements);
+	uint32_t wqe_size =
+		RTE_ALIGN(sizeof(struct gdma_wqe_dma_oob) +
+				client_oob_size + sgl_data_size,
+			  GDMA_WQE_ALIGNMENT_UNIT_SIZE);
+	uint8_t *wq_buffer_pointer;
+	uint32_t queue_free_units = queue->count - (queue->head - queue->tail);
+
+	if (wqe_size / GDMA_WQE_ALIGNMENT_UNIT_SIZE > queue_free_units) {
+		DRV_LOG(DEBUG, "WQE size %u queue count %u head %u tail %u",
+			wqe_size, queue->count, queue->head, queue->tail);
+		return -EBUSY;
+	}
+
+	DRV_LOG(DEBUG, "client_oob_size %u sgl_data_size %u wqe_size %u",
+		client_oob_size, sgl_data_size, wqe_size);
+
+	if (wqe_info) {
+		wqe_info->wqe_index =
+			((queue->head * GDMA_WQE_ALIGNMENT_UNIT_SIZE) &
+			 (queue->size - 1)) / GDMA_WQE_ALIGNMENT_UNIT_SIZE;
+		wqe_info->unmasked_queue_offset = queue->head;
+		wqe_info->wqe_size_in_bu =
+			wqe_size / GDMA_WQE_ALIGNMENT_UNIT_SIZE;
+	}
+
+	wq_buffer_pointer = gdma_get_wqe_pointer(queue);
+	wq_buffer_pointer += write_dma_client_oob(wq_buffer_pointer, work_req,
+						  client_oob_size);
+	if (wq_buffer_pointer >= ((uint8_t *)queue->buffer) + queue->size)
+		wq_buffer_pointer -= queue->size;
+
+	write_scatter_gather_list((uint8_t *)queue->buffer,
+				  (uint8_t *)queue->buffer + queue->size,
+				  wq_buffer_pointer, work_req);
+
+	queue->head += wqe_size / GDMA_WQE_ALIGNMENT_UNIT_SIZE;
+
+	return 0;
+}
+
+union gdma_doorbell_entry {
+	uint64_t     as_uint64;
+
+	struct {
+		uint64_t id	  : 24;
+		uint64_t reserved    : 8;
+		uint64_t tail_ptr    : 31;
+		uint64_t arm	 : 1;
+	} cq;
+
+	struct {
+		uint64_t id	  : 24;
+		uint64_t wqe_cnt     : 8;
+		uint64_t tail_ptr    : 32;
+	} rq;
+
+	struct {
+		uint64_t id	  : 24;
+		uint64_t reserved    : 8;
+		uint64_t tail_ptr    : 32;
+	} sq;
+
+	struct {
+		uint64_t id	  : 16;
+		uint64_t reserved    : 16;
+		uint64_t tail_ptr    : 31;
+		uint64_t arm	 : 1;
+	} eq;
+}; /* HW DATA */
+
+#define DOORBELL_OFFSET_SQ      0x0
+#define DOORBELL_OFFSET_RQ      0x400
+#define DOORBELL_OFFSET_CQ      0x800
+#define DOORBELL_OFFSET_EQ      0xFF8
+
+int mana_ring_doorbell(void *db_page, enum gdma_queue_types queue_type,
+		       uint32_t queue_id, uint32_t tail)
+{
+	uint8_t *addr = db_page;
+	union gdma_doorbell_entry e = {};
+
+	switch (queue_type) {
+	case gdma_queue_send:
+		e.sq.id = queue_id;
+		e.sq.tail_ptr = tail;
+		addr += DOORBELL_OFFSET_SQ;
+		break;
+
+	case gdma_queue_receive:
+		e.rq.id = queue_id;
+		e.rq.tail_ptr = tail;
+		e.rq.wqe_cnt = 1;
+		addr += DOORBELL_OFFSET_RQ;
+		break;
+
+	case gdma_queue_completion:
+		e.cq.id = queue_id;
+		e.cq.tail_ptr = tail;
+		e.cq.arm = 1;
+		addr += DOORBELL_OFFSET_CQ;
+		break;
+
+	default:
+		DRV_LOG(ERR, "Unsupported queue type %d", queue_type);
+		return -1;
+	}
+
+	/* Ensure all writes are done before ringing doorbell */
+	rte_wmb();
+
+	DRV_LOG(DEBUG, "db_page %p addr %p queue_id %u type %u tail %u",
+		db_page, addr, queue_id, queue_type, tail);
+
+	rte_write64(e.as_uint64, addr);
+	return 0;
+}
+
+int gdma_poll_completion_queue(struct mana_gdma_queue *cq,
+			       struct gdma_comp *comp)
+{
+	struct gdma_hardware_completion_entry *cqe;
+	uint32_t head = cq->head % cq->count;
+	uint32_t new_owner_bits, old_owner_bits;
+	uint32_t cqe_owner_bits;
+	struct gdma_hardware_completion_entry *buffer = cq->buffer;
+
+	cqe = &buffer[head];
+	new_owner_bits = (cq->head / cq->count) & COMPLETION_QUEUE_OWNER_MASK;
+	old_owner_bits = (cq->head / cq->count - 1) &
+				COMPLETION_QUEUE_OWNER_MASK;
+	cqe_owner_bits = cqe->owner_bits;
+
+	DRV_LOG(DEBUG, "comp cqe bits 0x%x owner bits 0x%x",
+		cqe_owner_bits, old_owner_bits);
+
+	if (cqe_owner_bits == old_owner_bits)
+		return 0; /* No new entry */
+
+	if (cqe_owner_bits != new_owner_bits) {
+		DRV_LOG(ERR, "CQ overflowed, ID %u cqe 0x%x new 0x%x",
+			cq->id, cqe_owner_bits, new_owner_bits);
+		return -1;
+	}
+
+	/* Ensure checking owner bits happens before reading from CQE */
+	rte_rmb();
+
+	comp->work_queue_number = cqe->wq_num;
+	comp->send_work_queue = cqe->is_sq;
+
+	memcpy(comp->completion_data, cqe->dma_client_data, GDMA_COMP_DATA_SIZE);
+
+	cq->head++;
+
+	DRV_LOG(DEBUG, "comp new 0x%x old 0x%x cqe 0x%x wq %u sq %u head %u",
+		new_owner_bits, old_owner_bits, cqe_owner_bits,
+		comp->work_queue_number, comp->send_work_queue, cq->head);
+	return 1;
+}
drivers/net/mana/mana.h +183 -0

201 lines not on this page · raw message

drivers/net/mana/meson.build +1 -0
index 9771394370..364d57a619 100644
@@ -12,6 +12,7 @@ deps += ['pci', 'bus_pci', 'net', 'eal', 'kvargs']
 sources += files(
 	'mana.c',
 	'mr.c',
+	'gdma.c',
 	'mp.c',
 )
 
Signature · 1 line
2.17.1
#25 lore raw

PATCH v6 12/18 net/mana: add function to start/stop TX queues

In reply to [email protected]

From: Long Li <[email protected]>

MANA allocate device queues through the IB layer when starting TX queues. When device is stopped all the queues are unmapped and freed.

---
Change log:
v2:
Add prefix mana_ to all function names.
Remove unused header files.

 doc/guides/nics/features/mana.ini |   1 +
 drivers/net/mana/mana.h           |   4 +
 drivers/net/mana/meson.build      |   1 +
 drivers/net/mana/tx.c             | 163 ++++++++++++++++++++++++++++++
 4 files changed, 169 insertions(+)
 create mode 100644 drivers/net/mana/tx.c
doc/guides/nics/features/mana.ini +1 -0
index a59c21cc10..821443b292 100644
@@ -7,6 +7,7 @@
 Link status          = P
 Linux                = Y
 Multiprocess aware   = Y
+Queue start/stop     = Y
 Removal event        = Y
 RSS hash             = Y
 Speed capabilities   = P
drivers/net/mana/mana.h +4 -0
index d87358ab15..3613ba7ca2 100644
@@ -379,6 +379,10 @@ uint16_t mana_tx_burst_removed(void *dpdk_rxq, struct rte_mbuf **pkts,
 int gdma_poll_completion_queue(struct mana_gdma_queue *cq,
 			       struct gdma_comp *comp);
 
+int mana_start_tx_queues(struct rte_eth_dev *dev);
+
+int mana_stop_tx_queues(struct rte_eth_dev *dev);
+
 struct mana_mr_cache *mana_find_pmd_mr(struct mana_mr_btree *local_tree,
 				       struct mana_priv *priv,
 				       struct rte_mbuf *mbuf);
drivers/net/mana/meson.build +1 -0
index 364d57a619..031f443d16 100644
@@ -11,6 +11,7 @@ deps += ['pci', 'bus_pci', 'net', 'eal', 'kvargs']
 
 sources += files(
 	'mana.c',
+	'tx.c',
 	'mr.c',
 	'gdma.c',
 	'mp.c',
drivers/net/mana/tx.c new file +163 -0

163 lines not on this page · raw message

Signature · 1 line
2.17.1
#26 lore raw

PATCH v6 13/18 net/mana: add function to start/stop RX queues

In reply to [email protected]

From: Long Li <[email protected]>

MANA allocates device queues through the IB layer when starting RX queues. When device is stopped all the queues are unmapped and freed.

---
Change log:
v2:
Add prefix mana_ to all function names.
Remove unused header files.
v4:
Move defition "uint32_t i" from inside "for ()" to outside

 drivers/net/mana/mana.h      |   3 +
 drivers/net/mana/meson.build |   1 +
 drivers/net/mana/rx.c        | 346 +++++++++++++++++++++++++++++++++++
 3 files changed, 350 insertions(+)
 create mode 100644 drivers/net/mana/rx.c
drivers/net/mana/mana.h +3 -0
index 3613ba7ca2..dc808d363f 100644
@@ -364,6 +364,7 @@ extern int mana_logtype_init;
 
 int mana_ring_doorbell(void *db_page, enum gdma_queue_types queue_type,
 		       uint32_t queue_id, uint32_t tail);
+int mana_rq_ring_doorbell(struct mana_rxq *rxq);
 
 int gdma_post_work_request(struct mana_gdma_queue *queue,
 			   struct gdma_work_request *work_req,
@@ -379,8 +380,10 @@ uint16_t mana_tx_burst_removed(void *dpdk_rxq, struct rte_mbuf **pkts,
 int gdma_poll_completion_queue(struct mana_gdma_queue *cq,
 			       struct gdma_comp *comp);
 
+int mana_start_rx_queues(struct rte_eth_dev *dev);
 int mana_start_tx_queues(struct rte_eth_dev *dev);
 
+int mana_stop_rx_queues(struct rte_eth_dev *dev);
 int mana_stop_tx_queues(struct rte_eth_dev *dev);
 
 struct mana_mr_cache *mana_find_pmd_mr(struct mana_mr_btree *local_tree,
drivers/net/mana/meson.build +1 -0
index 031f443d16..62e103a510 100644
@@ -11,6 +11,7 @@ deps += ['pci', 'bus_pci', 'net', 'eal', 'kvargs']
 
 sources += files(
 	'mana.c',
+	'rx.c',
 	'tx.c',
 	'mr.c',
 	'gdma.c',
drivers/net/mana/rx.c new file +346 -0

346 lines not on this page · raw message

Signature · 1 line
2.17.1
#27 lore raw

PATCH v6 14/18 net/mana: add function to receive packets

In reply to [email protected]

From: Long Li <[email protected]>

With all the RX queues created, MANA can use those queues to receive packets.

---
Change log:
v2:
Add mana_ to all function names.
Rename a camel case.

 doc/guides/nics/features/mana.ini |   2 +
 drivers/net/mana/mana.c           |   2 +
 drivers/net/mana/mana.h           |  37 +++++++++++
 drivers/net/mana/mp.c             |   2 +
 drivers/net/mana/rx.c             | 104 ++++++++++++++++++++++++++++++
 5 files changed, 147 insertions(+)
doc/guides/nics/features/mana.ini +2 -0
index 821443b292..fdbf22d335 100644
@@ -6,6 +6,8 @@
 [Features]
 Link status          = P
 Linux                = Y
+L3 checksum offload  = Y
+L4 checksum offload  = Y
 Multiprocess aware   = Y
 Queue start/stop     = Y
 Removal event        = Y
drivers/net/mana/mana.c +2 -0
index d18cc4ab0e..c349822991 100644
@@ -950,6 +950,8 @@ static int mana_pci_probe_mac(struct rte_pci_driver *pci_drv __rte_unused,
 				/* fd is no not used after mapping doorbell */
 				close(fd);
 
+				eth_dev->rx_pkt_burst = mana_rx_burst;
+
 				rte_spinlock_lock(&mana_shared_data->lock);
 				mana_shared_data->secondary_cnt++;
 				mana_local_data.secondary_cnt++;
drivers/net/mana/mana.h +37 -0
index dc808d363f..bafc4d6082 100644
@@ -178,6 +178,11 @@ struct gdma_work_request {
 
 enum mana_cqe_type {
 	CQE_INVALID                     = 0,
+
+	CQE_RX_OKAY                     = 1,
+	CQE_RX_COALESCED_4              = 2,
+	CQE_RX_OBJECT_FENCE             = 3,
+	CQE_RX_TRUNCATED                = 4,
 };
 
 struct mana_cqe_header {
@@ -203,6 +208,35 @@ struct mana_cqe_header {
 	(NDIS_HASH_TCP_IPV4 | NDIS_HASH_UDP_IPV4 | NDIS_HASH_TCP_IPV6 |      \
 	 NDIS_HASH_UDP_IPV6 | NDIS_HASH_TCP_IPV6_EX | NDIS_HASH_UDP_IPV6_EX)
 
+struct mana_rx_comp_per_packet_info {
+	uint32_t packet_length	: 16;
+	uint32_t reserved0	: 16;
+	uint32_t reserved1;
+	uint32_t packet_hash;
+}; /* HW DATA */
+#define RX_COM_OOB_NUM_PACKETINFO_SEGMENTS 4
+
+struct mana_rx_comp_oob {
+	struct mana_cqe_header cqe_hdr;
+
+	uint32_t rx_vlan_id				: 12;
+	uint32_t rx_vlan_tag_present			: 1;
+	uint32_t rx_outer_ip_header_checksum_succeeded	: 1;
+	uint32_t rx_outer_ip_header_checksum_failed	: 1;
+	uint32_t reserved				: 1;
+	uint32_t rx_hash_type				: 9;
+	uint32_t rx_ip_header_checksum_succeeded	: 1;
+	uint32_t rx_ip_header_checksum_failed		: 1;
+	uint32_t rx_tcp_checksum_succeeded		: 1;
+	uint32_t rx_tcp_checksum_failed			: 1;
+	uint32_t rx_udp_checksum_succeeded		: 1;
+	uint32_t rx_udp_checksum_failed			: 1;
+	uint32_t reserved1				: 1;
+	struct mana_rx_comp_per_packet_info
+		packet_info[RX_COM_OOB_NUM_PACKETINFO_SEGMENTS];
+	uint32_t received_wqe_offset;
+}; /* HW DATA */
+
 struct gdma_wqe_dma_oob {
 	uint32_t reserved:24;
 	uint32_t last_v_bytes:8;
@@ -371,6 +405,9 @@ int gdma_post_work_request(struct mana_gdma_queue *queue,
 			   struct gdma_posted_wqe_info *wqe_info);
 uint8_t *gdma_get_wqe_pointer(struct mana_gdma_queue *queue);
 
+uint16_t mana_rx_burst(void *dpdk_rxq, struct rte_mbuf **rx_pkts,
+		       uint16_t pkts_n);
+
 uint16_t mana_rx_burst_removed(void *dpdk_rxq, struct rte_mbuf **pkts,
 			       uint16_t pkts_n);
 
drivers/net/mana/mp.c +2 -0
index f4f78d2787..36a88c561a 100644
@@ -138,6 +138,8 @@ static int mana_mp_secondary_handle(const struct rte_mp_msg *mp_msg,
 	case MANA_MP_REQ_START_RXTX:
 		DRV_LOG(INFO, "Port %u starting datapath", dev->data->port_id);
 
+		dev->rx_pkt_burst = mana_rx_burst;
+
 		rte_mb();
 
 		res->result = 0;
drivers/net/mana/rx.c +104 -0

107 lines not on this page · raw message

Signature · 1 line
2.17.1
#28 lore raw

PATCH v6 15/18 net/mana: add function to send packets

In reply to [email protected]

From: Long Li <[email protected]>

With all the TX queues created, MANA can send packets over those queues.

---
Change log:
v2:
Rename all camel cases.

 doc/guides/nics/features/mana.ini |   1 +
 drivers/net/mana/mana.c           |   1 +
 drivers/net/mana/mana.h           |  65 ++++++++
 drivers/net/mana/mp.c             |   1 +
 drivers/net/mana/tx.c             | 241 ++++++++++++++++++++++++++++++
 5 files changed, 309 insertions(+)
doc/guides/nics/features/mana.ini +1 -0
index fdbf22d335..7922816d66 100644
@@ -4,6 +4,7 @@
 ; Refer to default.ini for the full list of available PMD features.
 ;
 [Features]
+Free Tx mbuf on demand = Y
 Link status          = P
 Linux                = Y
 L3 checksum offload  = Y
drivers/net/mana/mana.c +1 -0
index c349822991..0dcd3f3124 100644
@@ -950,6 +950,7 @@ static int mana_pci_probe_mac(struct rte_pci_driver *pci_drv __rte_unused,
 				/* fd is no not used after mapping doorbell */
 				close(fd);
 
+				eth_dev->tx_pkt_burst = mana_tx_burst;
 				eth_dev->rx_pkt_burst = mana_rx_burst;
 
 				rte_spinlock_lock(&mana_shared_data->lock);
drivers/net/mana/mana.h +65 -0

89 lines not on this page · raw message

drivers/net/mana/mp.c +1 -0
index 36a88c561a..da9c0f36a1 100644
@@ -138,6 +138,7 @@ static int mana_mp_secondary_handle(const struct rte_mp_msg *mp_msg,
 	case MANA_MP_REQ_START_RXTX:
 		DRV_LOG(INFO, "Port %u starting datapath", dev->data->port_id);
 
+		dev->tx_pkt_burst = mana_tx_burst;
 		dev->rx_pkt_burst = mana_rx_burst;
 
 		rte_mb();
drivers/net/mana/tx.c +241 -0

244 lines not on this page · raw message

Signature · 1 line
2.17.1
#29 lore raw

Re: [Patch v6 15/18] net/mana: add function to send packets

Quoted 5 lines · On 2022/8/31 6:51, [email protected] wrote:

From: Long Li <[email protected]>

With all the TX queues created, MANA can send packets over those queues.

...

Quoted 43 lines

}

drivers/net/mana/tx.c +42 -0
+
+uint16_t mana_tx_burst(void *dpdk_txq, struct rte_mbuf **tx_pkts,
+		       uint16_t nb_pkts)
+{
+	struct mana_txq *txq = dpdk_txq;
+	struct mana_priv *priv = txq->priv;
+	struct gdma_comp comp;
+	int ret;
+	void *db_page;
+
+	/* Process send completions from GDMA */
+	while (gdma_poll_completion_queue(&txq->gdma_cq, &comp) == 1) {
+		struct mana_txq_desc *desc =
+			&txq->desc_ring[txq->desc_ring_tail];
+		struct mana_tx_comp_oob *oob =
+			(struct mana_tx_comp_oob *)&comp.completion_data[0];
+
+		if (oob->cqe_hdr.cqe_type != CQE_TX_OKAY) {
+			DRV_LOG(ERR,
+				"mana_tx_comp_oob cqe_type %u vendor_err %u",
+				oob->cqe_hdr.cqe_type, oob->cqe_hdr.vendor_err);
+			txq->stats.errors++;
+		} else {
+			DRV_LOG(DEBUG, "mana_tx_comp_oob CQE_TX_OKAY");
+			txq->stats.packets++;
+		}
+
+		if (!desc->pkt) {
+			DRV_LOG(ERR, "mana_txq_desc has a NULL pkt");
+		} else {
+			txq->stats.bytes += desc->pkt->data_len;
+			rte_pktmbuf_free(desc->pkt);
+		}
+
+		desc->pkt = NULL;
+		txq->desc_ring_tail = (txq->desc_ring_tail + 1) % txq->num_desc;
+		txq->gdma_sq.tail += desc->wqe_size_in_bu;
+	}
+
+	/* Post send requests to GDMA */
+	uint16_t pkt_idx;
+

drivers/net/mana/tx.c static inline uint16_t get_vsq_frame_num(uint32_t vsq) · line 215

Quoted 10 lines
drivers/net/mana/tx.c +10 -0
+	for (pkt_idx = 0; pkt_idx < nb_pkts; pkt_idx++) {
+		struct rte_mbuf *m_pkt = tx_pkts[pkt_idx];
+		struct rte_mbuf *m_seg = m_pkt;
+		struct transmit_oob_v2 tx_oob = {0};
+		struct one_sgl sgl = {0};
+
+		/* Drop the packet if it exceeds max segments */
+		if (m_pkt->nb_segs > priv->max_send_sge) {
+			DRV_LOG(ERR, "send packet segments %d exceeding max",
+				m_pkt->nb_segs);

This branch violate rte_eth_tx_burst definition, which defined the return value is " * The maximum number of packets to transmit."

Also I notice the driver didn't implement tx-prepare, which could hold such checking in framework's definition.

Quoted 76 lines
drivers/net/mana/tx.c +76 -0
+			continue;
+		}
+
+		/* Fill in the oob */
+		tx_oob.short_oob.packet_format = short_packet_format;
+		tx_oob.short_oob.tx_is_outer_ipv4 =
+			m_pkt->ol_flags & RTE_MBUF_F_TX_IPV4 ? 1 : 0;
+		tx_oob.short_oob.tx_is_outer_ipv6 =
+			m_pkt->ol_flags & RTE_MBUF_F_TX_IPV6 ? 1 : 0;
+
+		tx_oob.short_oob.tx_compute_IP_header_checksum =
+			m_pkt->ol_flags & RTE_MBUF_F_TX_IP_CKSUM ? 1 : 0;
+
+		if ((m_pkt->ol_flags & RTE_MBUF_F_TX_L4_MASK) ==
+				RTE_MBUF_F_TX_TCP_CKSUM) {
+			struct rte_tcp_hdr *tcp_hdr;
+
+			/* HW needs partial TCP checksum */
+
+			tcp_hdr = rte_pktmbuf_mtod_offset(m_pkt,
+					  struct rte_tcp_hdr *,
+					  m_pkt->l2_len + m_pkt->l3_len);
+
+			if (m_pkt->ol_flags & RTE_MBUF_F_TX_IPV4) {
+				struct rte_ipv4_hdr *ip_hdr;
+
+				ip_hdr = rte_pktmbuf_mtod_offset(m_pkt,
+						struct rte_ipv4_hdr *,
+						m_pkt->l2_len);
+				tcp_hdr->cksum = rte_ipv4_phdr_cksum(ip_hdr,
+							m_pkt->ol_flags);
+
+			} else if (m_pkt->ol_flags & RTE_MBUF_F_TX_IPV6) {
+				struct rte_ipv6_hdr *ip_hdr;
+
+				ip_hdr = rte_pktmbuf_mtod_offset(m_pkt,
+						struct rte_ipv6_hdr *,
+						m_pkt->l2_len);
+				tcp_hdr->cksum = rte_ipv6_phdr_cksum(ip_hdr,
+							m_pkt->ol_flags);
+			} else {
+				DRV_LOG(ERR, "Invalid input for TCP CKSUM");
+			}
+
+			tx_oob.short_oob.tx_compute_TCP_checksum = 1;
+			tx_oob.short_oob.tx_transport_header_offset =
+				m_pkt->l2_len + m_pkt->l3_len;
+		}
+
+		if ((m_pkt->ol_flags & RTE_MBUF_F_TX_L4_MASK) ==
+				RTE_MBUF_F_TX_UDP_CKSUM) {
+			struct rte_udp_hdr *udp_hdr;
+
+			/* HW needs partial UDP checksum */
+			udp_hdr = rte_pktmbuf_mtod_offset(m_pkt,
+					struct rte_udp_hdr *,
+					m_pkt->l2_len + m_pkt->l3_len);
+
+			if (m_pkt->ol_flags & RTE_MBUF_F_TX_IPV4) {
+				struct rte_ipv4_hdr *ip_hdr;
+
+				ip_hdr = rte_pktmbuf_mtod_offset(m_pkt,
+						struct rte_ipv4_hdr *,
+						m_pkt->l2_len);
+
+				udp_hdr->dgram_cksum =
+					rte_ipv4_phdr_cksum(ip_hdr,
+							    m_pkt->ol_flags);
+
+			} else if (m_pkt->ol_flags & RTE_MBUF_F_TX_IPV6) {
+				struct rte_ipv6_hdr *ip_hdr;
+
+				ip_hdr = rte_pktmbuf_mtod_offset(m_pkt,
+						struct rte_ipv6_hdr *,
+						m_pkt->l2_len);
+

drivers/net/mana/tx.c static inline uint16_t get_vsq_frame_num(uint32_t vsq) · line 301

Quoted 10 lines
drivers/net/mana/tx.c +10 -0
+				udp_hdr->dgram_cksum =
+					rte_ipv6_phdr_cksum(ip_hdr,
+							    m_pkt->ol_flags);
+
+			} else {
+				DRV_LOG(ERR, "Invalid input for UDP CKSUM");
+			}
+
+			tx_oob.short_oob.tx_compute_UDP_checksum = 1;
+		}

Why not have TSO process, which was reported support in dev_info_get ?

Quoted 104 lines
drivers/net/mana/tx.c +103 -0
+
+		tx_oob.short_oob.suppress_tx_CQE_generation = 0;
+		tx_oob.short_oob.VCQ_number = txq->gdma_cq.id;
+
+		tx_oob.short_oob.VSQ_frame_num =
+			get_vsq_frame_num(txq->gdma_sq.id);
+		tx_oob.short_oob.short_vport_offset = txq->tx_vp_offset;
+
+		DRV_LOG(DEBUG, "tx_oob packet_format %u ipv4 %u ipv6 %u",
+			tx_oob.short_oob.packet_format,
+			tx_oob.short_oob.tx_is_outer_ipv4,
+			tx_oob.short_oob.tx_is_outer_ipv6);
+
+		DRV_LOG(DEBUG, "tx_oob checksum ip %u tcp %u udp %u offset %u",
+			tx_oob.short_oob.tx_compute_IP_header_checksum,
+			tx_oob.short_oob.tx_compute_TCP_checksum,
+			tx_oob.short_oob.tx_compute_UDP_checksum,
+			tx_oob.short_oob.tx_transport_header_offset);
+
+		DRV_LOG(DEBUG, "pkt[%d]: buf_addr 0x%p, nb_segs %d, pkt_len %d",
+			pkt_idx, m_pkt->buf_addr, m_pkt->nb_segs,
+			m_pkt->pkt_len);
+
+		/* Create SGL for packet data buffers */
+		for (uint16_t seg_idx = 0; seg_idx < m_pkt->nb_segs; seg_idx++) {
+			struct mana_mr_cache *mr =
+				mana_find_pmd_mr(&txq->mr_btree, priv, m_seg);
+
+			if (!mr) {
+				DRV_LOG(ERR, "failed to get MR, pkt_idx %u",
+					pkt_idx);
+				return pkt_idx;
+			}
+
+			sgl.gdma_sgl[seg_idx].address =
+				rte_cpu_to_le_64(rte_pktmbuf_mtod(m_seg,
+								  uint64_t));
+			sgl.gdma_sgl[seg_idx].size = m_seg->data_len;
+			sgl.gdma_sgl[seg_idx].memory_key = mr->lkey;
+
+			DRV_LOG(DEBUG,
+				"seg idx %u addr 0x%" PRIx64 " size %x key %x",
+				seg_idx, sgl.gdma_sgl[seg_idx].address,
+				sgl.gdma_sgl[seg_idx].size,
+				sgl.gdma_sgl[seg_idx].memory_key);
+
+			m_seg = m_seg->next;
+		}
+
+		struct gdma_work_request work_req = {0};
+		struct gdma_posted_wqe_info wqe_info = {0};
+
+		work_req.gdma_header.struct_size = sizeof(work_req);
+		wqe_info.gdma_header.struct_size = sizeof(wqe_info);
+
+		work_req.sgl = sgl.gdma_sgl;
+		work_req.num_sgl_elements = m_pkt->nb_segs;
+		work_req.inline_oob_size_in_bytes =
+			sizeof(struct transmit_short_oob_v2);
+		work_req.inline_oob_data = &tx_oob;
+		work_req.flags = 0;
+		work_req.client_data_unit = NOT_USING_CLIENT_DATA_UNIT;
+
+		ret = gdma_post_work_request(&txq->gdma_sq, &work_req,
+					     &wqe_info);
+		if (!ret) {
+			struct mana_txq_desc *desc =
+				&txq->desc_ring[txq->desc_ring_head];
+
+			/* Update queue for tracking pending requests */
+			desc->pkt = m_pkt;
+			desc->wqe_size_in_bu = wqe_info.wqe_size_in_bu;
+			txq->desc_ring_head =
+				(txq->desc_ring_head + 1) % txq->num_desc;
+
+			DRV_LOG(DEBUG, "nb_pkts %u pkt[%d] sent",
+				nb_pkts, pkt_idx);
+		} else {
+			DRV_LOG(INFO, "pkt[%d] failed to post send ret %d",
+				pkt_idx, ret);
+			break;
+		}
+	}
+
+	/* Ring hardware door bell */
+	db_page = priv->db_page;
+	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
+		struct rte_eth_dev *dev =
+			&rte_eth_devices[priv->dev_data->port_id];
+		struct mana_process_priv *process_priv = dev->process_private;
+
+		db_page = process_priv->db_page;
+	}
+
+	ret = mana_ring_doorbell(db_page, gdma_queue_send,
+				 txq->gdma_sq.id,
+				 txq->gdma_sq.head *
+					GDMA_WQE_ALIGNMENT_UNIT_SIZE);
+	if (ret)
+		DRV_LOG(ERR, "mana_ring_doorbell failed ret %d", ret);
+
+	return pkt_idx;
+}
#30 lore raw

RE: [Patch v6 15/18] net/mana: add function to send packets

Quoted 68 lines

Subject: Re: [Patch v6 15/18] net/mana: add function to send packets

Quoted 5 lines · On 2022/8/31 6:51, [email protected] wrote:

From: Long Li <[email protected]>

With all the TX queues created, MANA can send packets over those queues.

...

Quoted 7 lines

}

drivers/net/mana/tx.c +6 -0
+
+uint16_t mana_tx_burst(void *dpdk_txq, struct rte_mbuf **tx_pkts,
+		       uint16_t nb_pkts)
+{
+	struct mana_txq *txq = dpdk_txq;
+	struct mana_priv *priv = txq->priv;

drivers/net/mana/tx.c static inline uint16_t get_vsq_frame_num(uint32_t vsq)

Quoted 10 lines
drivers/net/mana/tx.c +10 -0
+	struct gdma_comp comp;
+	int ret;
+	void *db_page;
+
+	/* Process send completions from GDMA */
+	while (gdma_poll_completion_queue(&txq->gdma_cq, &comp) == 1) {
+		struct mana_txq_desc *desc =
+			&txq->desc_ring[txq->desc_ring_tail];
+		struct mana_tx_comp_oob *oob =
+			(struct mana_tx_comp_oob

*)&comp.completion_data[0];

drivers/net/mana/tx.c static inline uint16_t get_vsq_frame_num(uint32_t vsq)

Quoted 4 lines
drivers/net/mana/tx.c +4 -0
+
+		if (oob->cqe_hdr.cqe_type != CQE_TX_OKAY) {
+			DRV_LOG(ERR,
+				"mana_tx_comp_oob cqe_type %u

vendor_err %u",

drivers/net/mana/tx.c static inline uint16_t get_vsq_frame_num(uint32_t vsq)

Quoted 5 lines
(quoted diff) +1 -0
+				oob->cqe_hdr.cqe_type, oob-

cqe_hdr.vendor_err);

drivers/net/mana/tx.c +3 -0
+			txq->stats.errors++;
+		} else {
+			DRV_LOG(DEBUG, "mana_tx_comp_oob

CQE_TX_OKAY");

Quoted 17 lines
drivers/net/mana/tx.c +17 -0
+			txq->stats.packets++;
+		}
+
+		if (!desc->pkt) {
+			DRV_LOG(ERR, "mana_txq_desc has a NULL pkt");
+		} else {
+			txq->stats.bytes += desc->pkt->data_len;
+			rte_pktmbuf_free(desc->pkt);
+		}
+
+		desc->pkt = NULL;
+		txq->desc_ring_tail = (txq->desc_ring_tail + 1) % txq->num_desc;
+		txq->gdma_sq.tail += desc->wqe_size_in_bu;
+	}
+
+	/* Post send requests to GDMA */
+	uint16_t pkt_idx;

drivers/net/mana/tx.c static inline uint16_t get_vsq_frame_num(uint32_t vsq)

Quoted 10 lines
drivers/net/mana/tx.c +10 -0
+
+	for (pkt_idx = 0; pkt_idx < nb_pkts; pkt_idx++) {
+		struct rte_mbuf *m_pkt = tx_pkts[pkt_idx];
+		struct rte_mbuf *m_seg = m_pkt;
+		struct transmit_oob_v2 tx_oob = {0};
+		struct one_sgl sgl = {0};
+
+		/* Drop the packet if it exceeds max segments */
+		if (m_pkt->nb_segs > priv->max_send_sge) {
+			DRV_LOG(ERR, "send packet segments %d exceeding

max",

Quoted 4 lines

drivers/net/mana/tx.c static inline uint16_t get_vsq_frame_num(uint32_t vsq) · line 215

Quoted 1 line
drivers/net/mana/tx.c +1 -0
+				m_pkt->nb_segs);

This branch violate rte_eth_tx_burst definition, which defined the return value is
" * The maximum number of packets to transmit."

Will fix this.

Quoted 84 lines

Also I notice the driver didn't implement tx-prepare, which could hold such checking in framework's definition.

Quoted 80 lines
drivers/net/mana/tx.c +80 -0
+			continue;
+		}
+
+		/* Fill in the oob */
+		tx_oob.short_oob.packet_format = short_packet_format;
+		tx_oob.short_oob.tx_is_outer_ipv4 =
+			m_pkt->ol_flags & RTE_MBUF_F_TX_IPV4 ? 1 : 0;
+		tx_oob.short_oob.tx_is_outer_ipv6 =
+			m_pkt->ol_flags & RTE_MBUF_F_TX_IPV6 ? 1 : 0;
+
+		tx_oob.short_oob.tx_compute_IP_header_checksum =
+			m_pkt->ol_flags & RTE_MBUF_F_TX_IP_CKSUM ? 1 : 0;
+
+		if ((m_pkt->ol_flags & RTE_MBUF_F_TX_L4_MASK) ==
+				RTE_MBUF_F_TX_TCP_CKSUM) {
+			struct rte_tcp_hdr *tcp_hdr;
+
+			/* HW needs partial TCP checksum */
+
+			tcp_hdr = rte_pktmbuf_mtod_offset(m_pkt,
+					  struct rte_tcp_hdr *,
+					  m_pkt->l2_len + m_pkt->l3_len);
+
+			if (m_pkt->ol_flags & RTE_MBUF_F_TX_IPV4) {
+				struct rte_ipv4_hdr *ip_hdr;
+
+				ip_hdr = rte_pktmbuf_mtod_offset(m_pkt,
+						struct rte_ipv4_hdr *,
+						m_pkt->l2_len);
+				tcp_hdr->cksum = rte_ipv4_phdr_cksum(ip_hdr,
+							m_pkt->ol_flags);
+
+			} else if (m_pkt->ol_flags & RTE_MBUF_F_TX_IPV6) {
+				struct rte_ipv6_hdr *ip_hdr;
+
+				ip_hdr = rte_pktmbuf_mtod_offset(m_pkt,
+						struct rte_ipv6_hdr *,
+						m_pkt->l2_len);
+				tcp_hdr->cksum = rte_ipv6_phdr_cksum(ip_hdr,
+							m_pkt->ol_flags);
+			} else {
+				DRV_LOG(ERR, "Invalid input for TCP CKSUM");
+			}
+
+			tx_oob.short_oob.tx_compute_TCP_checksum = 1;
+			tx_oob.short_oob.tx_transport_header_offset =
+				m_pkt->l2_len + m_pkt->l3_len;
+		}
+
+		if ((m_pkt->ol_flags & RTE_MBUF_F_TX_L4_MASK) ==
+				RTE_MBUF_F_TX_UDP_CKSUM) {
+			struct rte_udp_hdr *udp_hdr;
+
+			/* HW needs partial UDP checksum */
+			udp_hdr = rte_pktmbuf_mtod_offset(m_pkt,
+					struct rte_udp_hdr *,
+					m_pkt->l2_len + m_pkt->l3_len);
+
+			if (m_pkt->ol_flags & RTE_MBUF_F_TX_IPV4) {
+				struct rte_ipv4_hdr *ip_hdr;
+
+				ip_hdr = rte_pktmbuf_mtod_offset(m_pkt,
+						struct rte_ipv4_hdr *,
+						m_pkt->l2_len);
+
+				udp_hdr->dgram_cksum =
+					rte_ipv4_phdr_cksum(ip_hdr,
+							    m_pkt->ol_flags);
+
+			} else if (m_pkt->ol_flags & RTE_MBUF_F_TX_IPV6) {
+				struct rte_ipv6_hdr *ip_hdr;
+
+				ip_hdr = rte_pktmbuf_mtod_offset(m_pkt,
+						struct rte_ipv6_hdr *,
+						m_pkt->l2_len);
+
+				udp_hdr->dgram_cksum =
+					rte_ipv6_phdr_cksum(ip_hdr,
+							    m_pkt->ol_flags);
+
Quoted 8 lines

drivers/net/mana/tx.c static inline uint16_t get_vsq_frame_num(uint32_t vsq) · line 301

Quoted 6 lines
drivers/net/mana/tx.c +6 -0
+			} else {
+				DRV_LOG(ERR, "Invalid input for UDP CKSUM");
+			}
+
+			tx_oob.short_oob.tx_compute_UDP_checksum = 1;
+		}

Why not have TSO process, which was reported support in dev_info_get ?

TSO is currently not implemented. I'm changing BNIC_DEV_TX_OFFLOAD_SUPPORT to fix this.

Quoted 109 lines
Quoted 5 lines
drivers/net/mana/tx.c +4 -0
+
+		tx_oob.short_oob.suppress_tx_CQE_generation = 0;
+		tx_oob.short_oob.VCQ_number = txq->gdma_cq.id;
+

drivers/net/mana/tx.c static inline uint16_t get_vsq_frame_num(uint32_t vsq)

Quoted 10 lines
drivers/net/mana/tx.c +10 -0
+		tx_oob.short_oob.VSQ_frame_num =
+			get_vsq_frame_num(txq->gdma_sq.id);
+		tx_oob.short_oob.short_vport_offset = txq->tx_vp_offset;
+
+		DRV_LOG(DEBUG, "tx_oob packet_format %u ipv4 %u ipv6 %u",
+			tx_oob.short_oob.packet_format,
+			tx_oob.short_oob.tx_is_outer_ipv4,
+			tx_oob.short_oob.tx_is_outer_ipv6);
+
+		DRV_LOG(DEBUG, "tx_oob checksum ip %u tcp %u udp %u

offset %u",

drivers/net/mana/tx.c static inline uint16_t get_vsq_frame_num(uint32_t vsq)

Quoted 6 lines
drivers/net/mana/tx.c +6 -0
+			tx_oob.short_oob.tx_compute_IP_header_checksum,
+			tx_oob.short_oob.tx_compute_TCP_checksum,
+			tx_oob.short_oob.tx_compute_UDP_checksum,
+			tx_oob.short_oob.tx_transport_header_offset);
+
+		DRV_LOG(DEBUG, "pkt[%d]: buf_addr 0x%p, nb_segs %d,

pkt_len %d",

drivers/net/mana/tx.c static inline uint16_t get_vsq_frame_num(uint32_t vsq)

Quoted 5 lines
drivers/net/mana/tx.c +5 -0
+			pkt_idx, m_pkt->buf_addr, m_pkt->nb_segs,
+			m_pkt->pkt_len);
+
+		/* Create SGL for packet data buffers */
+		for (uint16_t seg_idx = 0; seg_idx < m_pkt->nb_segs; seg_idx++)

{

Review

Quoted 2 lines
(quoted diff) +2 -0
+			struct mana_mr_cache *mr =
+				mana_find_pmd_mr(&txq->mr_btree, priv,

m_seg);

Quoted 77 lines
drivers/net/mana/tx.c +76 -0
+
+			if (!mr) {
+				DRV_LOG(ERR, "failed to get MR, pkt_idx %u",
+					pkt_idx);
+				return pkt_idx;
+			}
+
+			sgl.gdma_sgl[seg_idx].address =
+				rte_cpu_to_le_64(rte_pktmbuf_mtod(m_seg,
+								  uint64_t));
+			sgl.gdma_sgl[seg_idx].size = m_seg->data_len;
+			sgl.gdma_sgl[seg_idx].memory_key = mr->lkey;
+
+			DRV_LOG(DEBUG,
+				"seg idx %u addr 0x%" PRIx64 " size %x key %x",
+				seg_idx, sgl.gdma_sgl[seg_idx].address,
+				sgl.gdma_sgl[seg_idx].size,
+				sgl.gdma_sgl[seg_idx].memory_key);
+
+			m_seg = m_seg->next;
+		}
+
+		struct gdma_work_request work_req = {0};
+		struct gdma_posted_wqe_info wqe_info = {0};
+
+		work_req.gdma_header.struct_size = sizeof(work_req);
+		wqe_info.gdma_header.struct_size = sizeof(wqe_info);
+
+		work_req.sgl = sgl.gdma_sgl;
+		work_req.num_sgl_elements = m_pkt->nb_segs;
+		work_req.inline_oob_size_in_bytes =
+			sizeof(struct transmit_short_oob_v2);
+		work_req.inline_oob_data = &tx_oob;
+		work_req.flags = 0;
+		work_req.client_data_unit = NOT_USING_CLIENT_DATA_UNIT;
+
+		ret = gdma_post_work_request(&txq->gdma_sq, &work_req,
+					     &wqe_info);
+		if (!ret) {
+			struct mana_txq_desc *desc =
+				&txq->desc_ring[txq->desc_ring_head];
+
+			/* Update queue for tracking pending requests */
+			desc->pkt = m_pkt;
+			desc->wqe_size_in_bu = wqe_info.wqe_size_in_bu;
+			txq->desc_ring_head =
+				(txq->desc_ring_head + 1) % txq->num_desc;
+
+			DRV_LOG(DEBUG, "nb_pkts %u pkt[%d] sent",
+				nb_pkts, pkt_idx);
+		} else {
+			DRV_LOG(INFO, "pkt[%d] failed to post send ret %d",
+				pkt_idx, ret);
+			break;
+		}
+	}
+
+	/* Ring hardware door bell */
+	db_page = priv->db_page;
+	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
+		struct rte_eth_dev *dev =
+			&rte_eth_devices[priv->dev_data->port_id];
+		struct mana_process_priv *process_priv = dev->process_private;
+
+		db_page = process_priv->db_page;
+	}
+
+	ret = mana_ring_doorbell(db_page, gdma_queue_send,
+				 txq->gdma_sq.id,
+				 txq->gdma_sq.head *
+					GDMA_WQE_ALIGNMENT_UNIT_SIZE);
+	if (ret)
+		DRV_LOG(ERR, "mana_ring_doorbell failed ret %d", ret);
+
+	return pkt_idx;
+}
#31 lore raw

PATCH v6 16/18 net/mana: add function to start/stop device

In reply to [email protected]

From: Long Li <[email protected]>

Add support for starting/stopping the device.

---
Change log:
v2:
Use spinlock for memory registration cache. Add prefix mana_ to all function names.
v6:
Roll back device state on error in mana_dev_start()

 drivers/net/mana/mana.c | 77 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 77 insertions(+)
drivers/net/mana/mana.c +77 -0
index 0dcd3f3124..eb37f359db 100644
@@ -97,6 +97,81 @@ static int mana_dev_configure(struct rte_eth_dev *dev)
 
 static int mana_intr_uninstall(struct mana_priv *priv);
 
+static int
+mana_dev_start(struct rte_eth_dev *dev)
+{
+	int ret;
+	struct mana_priv *priv = dev->data->dev_private;
+
+	rte_spinlock_init(&priv->mr_btree_lock);
+	ret = mana_mr_btree_init(&priv->mr_btree, MANA_MR_BTREE_CACHE_N,
+				 dev->device->numa_node);
+	if (ret) {
+		DRV_LOG(ERR, "Failed to init device MR btree %d", ret);
+		return ret;
+	}
+
+	ret = mana_start_tx_queues(dev);
+	if (ret) {
+		DRV_LOG(ERR, "failed to start tx queues %d", ret);
+		goto failed_tx;
+	}
+
+	ret = mana_start_rx_queues(dev);
+	if (ret) {
+		DRV_LOG(ERR, "failed to start rx queues %d", ret);
+		goto failed_rx;
+	}
+
+	rte_wmb();
+
+	dev->tx_pkt_burst = mana_tx_burst;
+	dev->rx_pkt_burst = mana_rx_burst;
+
+	DRV_LOG(INFO, "TX/RX queues have started");
+
+	/* Enable datapath for secondary processes */
+	mana_mp_req_on_rxtx(dev, MANA_MP_REQ_START_RXTX);
+
+	return 0;
+
+failed_rx:
+	mana_stop_tx_queues(dev);
+
+failed_tx:
+	mana_mr_btree_free(&priv->mr_btree);
+
+	return ret;
+}
+
+static int
+mana_dev_stop(struct rte_eth_dev *dev __rte_unused)
+{
+	int ret;
+
+	dev->tx_pkt_burst = mana_tx_burst_removed;
+	dev->rx_pkt_burst = mana_rx_burst_removed;
+
+	/* Stop datapath on secondary processes */
+	mana_mp_req_on_rxtx(dev, MANA_MP_REQ_STOP_RXTX);
+
+	rte_wmb();
+
+	ret = mana_stop_tx_queues(dev);
+	if (ret) {
+		DRV_LOG(ERR, "failed to stop tx queues");
+		return ret;
+	}
+
+	ret = mana_stop_rx_queues(dev);
+	if (ret) {
+		DRV_LOG(ERR, "failed to stop tx queues");
+		return ret;
+	}
+
+	return 0;
+}
+
 static int
 mana_dev_close(struct rte_eth_dev *dev)
 {
@@ -435,6 +510,8 @@ static int mana_dev_link_update(struct rte_eth_dev *dev,
 
 const struct eth_dev_ops mana_dev_ops = {
 	.dev_configure		= mana_dev_configure,
+	.dev_start		= mana_dev_start,
+	.dev_stop		= mana_dev_stop,
 	.dev_close		= mana_dev_close,
 	.dev_infos_get		= mana_dev_info_get,
 	.txq_info_get		= mana_dev_tx_queue_info,
Signature · 1 line
2.17.1
#32 lore raw

PATCH v6 17/18 net/mana: add function to report queue stats

In reply to [email protected]

From: Long Li <[email protected]>

Report packet statistics.

---
Change log:
v5:
Fixed calculation of stats packets/bytes/errors by adding them over the queue stats.

 doc/guides/nics/features/mana.ini |  2 +
 drivers/net/mana/mana.c           | 77 +++++++++++++++++++++++++++++++
 2 files changed, 79 insertions(+)
doc/guides/nics/features/mana.ini +2 -0
index 7922816d66..b2729aba3a 100644
@@ -4,6 +4,7 @@
 ; Refer to default.ini for the full list of available PMD features.
 ;
 [Features]
+Basic stats          = Y
 Free Tx mbuf on demand = Y
 Link status          = P
 Linux                = Y
@@ -14,5 +15,6 @@ Queue start/stop     = Y
 Removal event        = Y
 RSS hash             = Y
 Speed capabilities   = P
+Stats per queue      = Y
 Usage doc            = Y
 x86-64               = Y
drivers/net/mana/mana.c +77 -0

92 lines not on this page · raw message

Signature · 1 line
2.17.1
#33 lore raw

PATCH v6 18/18 net/mana: add function to support RX interrupts

In reply to [email protected]

From: Long Li <[email protected]>

mana can receive RX interrupts from kernel through RDMA verbs interface. Implement RX interrupts in the driver.

---
Change log:
v5:
New patch added to the series

 doc/guides/nics/features/mana.ini |   1 +
 drivers/net/mana/gdma.c           |  10 +--
 drivers/net/mana/mana.c           | 125 ++++++++++++++++++++++++++----
 drivers/net/mana/mana.h           |  13 +++-
 drivers/net/mana/rx.c             |  91 +++++++++++++++++++---
 drivers/net/mana/tx.c             |   3 +-
 6 files changed, 207 insertions(+), 36 deletions(-)
doc/guides/nics/features/mana.ini +1 -0
index b2729aba3a..42d78ac6b1 100644
@@ -14,6 +14,7 @@ Multiprocess aware   = Y
 Queue start/stop     = Y
 Removal event        = Y
 RSS hash             = Y
+Rx interrupt         = Y
 Speed capabilities   = P
 Stats per queue      = Y
 Usage doc            = Y
drivers/net/mana/gdma.c +5 -5
index 7ad175651e..275520bff5 100644
@@ -204,7 +204,7 @@ union gdma_doorbell_entry {
 #define DOORBELL_OFFSET_EQ      0xFF8
 
 int mana_ring_doorbell(void *db_page, enum gdma_queue_types queue_type,
-		       uint32_t queue_id, uint32_t tail)
+		       uint32_t queue_id, uint32_t tail, uint8_t arm)
 {
 	uint8_t *addr = db_page;
 	union gdma_doorbell_entry e = {};
@@ -219,14 +219,14 @@ int mana_ring_doorbell(void *db_page, enum gdma_queue_types queue_type,
 	case gdma_queue_receive:
 		e.rq.id = queue_id;
 		e.rq.tail_ptr = tail;
-		e.rq.wqe_cnt = 1;
+		e.rq.wqe_cnt = arm;
 		addr += DOORBELL_OFFSET_RQ;
 		break;
 
 	case gdma_queue_completion:
 		e.cq.id = queue_id;
 		e.cq.tail_ptr = tail;
-		e.cq.arm = 1;
+		e.cq.arm = arm;
 		addr += DOORBELL_OFFSET_CQ;
 		break;
 
@@ -238,8 +238,8 @@ int mana_ring_doorbell(void *db_page, enum gdma_queue_types queue_type,
 	/* Ensure all writes are done before ringing doorbell */
 	rte_wmb();
 
-	DRV_LOG(DEBUG, "db_page %p addr %p queue_id %u type %u tail %u",
-		db_page, addr, queue_id, queue_type, tail);
+	DRV_LOG(DEBUG, "db_page %p addr %p queue_id %u type %u tail %u arm %u",
+		db_page, addr, queue_id, queue_type, tail, arm);
 
 	rte_write64(e.as_uint64, addr);
 	return 0;
drivers/net/mana/mana.c +108 -17

207 lines not on this page · raw message

drivers/net/mana/mana.h +11 -2
index b4056bd50b..9cc98fee4c 100644
@@ -427,6 +427,7 @@ struct mana_rxq {
 	uint32_t num_desc;
 	struct rte_mempool *mp;
 	struct ibv_cq *cq;
+	struct ibv_comp_channel *channel;
 	struct ibv_wq *wq;
 
 	/* For storing pending requests */
@@ -460,8 +461,8 @@ extern int mana_logtype_init;
 #define PMD_INIT_FUNC_TRACE() PMD_INIT_LOG(DEBUG, " >>")
 
 int mana_ring_doorbell(void *db_page, enum gdma_queue_types queue_type,
-		       uint32_t queue_id, uint32_t tail);
-int mana_rq_ring_doorbell(struct mana_rxq *rxq);
+		       uint32_t queue_id, uint32_t tail, uint8_t arm);
+int mana_rq_ring_doorbell(struct mana_rxq *rxq, uint8_t arm);
 
 int gdma_post_work_request(struct mana_gdma_queue *queue,
 			   struct gdma_work_request *work_req,
@@ -496,6 +497,10 @@ int mana_new_pmd_mr(struct mana_mr_btree *local_tree, struct mana_priv *priv,
 void mana_remove_all_mr(struct mana_priv *priv);
 void mana_del_pmd_mr(struct mana_mr_cache *mr);
 
+void mana_intr_handler(void *arg);
+int mana_intr_install(struct rte_eth_dev *eth_dev, struct mana_priv *priv);
+int mana_intr_uninstall(struct mana_priv *priv);
+
 void mana_mempool_chunk_cb(struct rte_mempool *mp, void *opaque,
 			   struct rte_mempool_memhdr *memhdr, unsigned int idx);
 
@@ -541,4 +546,8 @@ void mana_mp_req_on_rxtx(struct rte_eth_dev *dev, enum mana_mp_req_type type);
 void *mana_alloc_verbs_buf(size_t size, void *data);
 void mana_free_verbs_buf(void *ptr, void *data __rte_unused);
 
+int mana_rx_intr_enable(struct rte_eth_dev *dev, uint16_t rx_queue_id);
+int mana_rx_intr_disable(struct rte_eth_dev *dev, uint16_t rx_queue_id);
+int mana_fd_set_non_blocking(int fd);
+
 #endif
drivers/net/mana/rx.c +80 -11

142 lines not on this page · raw message

drivers/net/mana/tx.c +2 -1
index 0aefab1b6c..5878ea62f9 100644
@@ -396,7 +396,8 @@ uint16_t mana_tx_burst(void *dpdk_txq, struct rte_mbuf **tx_pkts,
 	ret = mana_ring_doorbell(db_page, gdma_queue_send,
 				 txq->gdma_sq.id,
 				 txq->gdma_sq.head *
-					GDMA_WQE_ALIGNMENT_UNIT_SIZE);
+					GDMA_WQE_ALIGNMENT_UNIT_SIZE,
+				 0);
 	if (ret)
 		DRV_LOG(ERR, "mana_ring_doorbell failed ret %d", ret);
 
Signature · 1 line
2.17.1