[V11 12/18] net/hinic3: add futions for initialization

Feifei Wang wff_light at vip.163.com
Wed Sep 17 12:15:46 CEST 2025


From: Xin Wang <wangxin679 at h-partners.com>

This patch contains data structures and function codes
related to device initialization.

Signed-off-by: Xin Wang <wangxin679 at h-partners.com>
Reviewed-by: Feifei Wang <wangfeifei40 at huawei.com>
Reviewed-by: Yi Chen <chenyi221 at huawei.com>
---
 drivers/net/hinic3/hinic3_ethdev.c | 255 +++++++++++++++++++++++++++++
 drivers/net/hinic3/hinic3_ethdev.h | 118 +++++++++++++
 drivers/net/hinic3/meson.build     |  25 +++
 3 files changed, 398 insertions(+)
 create mode 100644 drivers/net/hinic3/hinic3_ethdev.c
 create mode 100644 drivers/net/hinic3/hinic3_ethdev.h
 create mode 100644 drivers/net/hinic3/meson.build

diff --git a/drivers/net/hinic3/hinic3_ethdev.c b/drivers/net/hinic3/hinic3_ethdev.c
new file mode 100644
index 0000000000..0cf0b774c5
--- /dev/null
+++ b/drivers/net/hinic3/hinic3_ethdev.c
@@ -0,0 +1,255 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2025 Huawei Technologies Co., Ltd
+ */
+#include <ethdev_pci.h>
+#include <eal_interrupts.h>
+
+#include "base/hinic3_compat.h"
+#include "base/hinic3_csr.h"
+#include "base/hinic3_wq.h"
+#include "base/hinic3_eqs.h"
+#include "base/hinic3_cmdq.h"
+#include "base/hinic3_hwdev.h"
+#include "base/hinic3_hwif.h"
+#include "base/hinic3_hw_cfg.h"
+#include "base/hinic3_hw_comm.h"
+#include "base/hinic3_nic_cfg.h"
+#include "base/hinic3_nic_event.h"
+#include "hinic3_ethdev.h"
+
+/*
+ * Init mac_vlan table in hardwares.
+ *
+ * @param[in] eth_dev
+ * Pointer to ethernet device structure.
+ *
+ * @return
+ * 0 on success, non-zero on failure.
+ */
+static int
+hinic3_init_mac_table(struct rte_eth_dev *eth_dev)
+{
+	struct hinic3_nic_dev *nic_dev =
+		HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
+	uint8_t addr_bytes[RTE_ETHER_ADDR_LEN];
+	uint16_t func_id = 0;
+	int err = 0;
+
+	err = hinic3_get_default_mac(nic_dev->hwdev, addr_bytes,
+				     RTE_ETHER_ADDR_LEN);
+	if (err)
+		return err;
+
+	rte_ether_addr_copy((struct rte_ether_addr *)addr_bytes,
+			    &eth_dev->data->mac_addrs[0]);
+	if (rte_is_zero_ether_addr(&eth_dev->data->mac_addrs[0]))
+		rte_eth_random_addr(eth_dev->data->mac_addrs[0].addr_bytes);
+
+	func_id = hinic3_global_func_id(nic_dev->hwdev);
+	err = hinic3_set_mac(nic_dev->hwdev,
+			     eth_dev->data->mac_addrs[0].addr_bytes, 0, func_id);
+	if (err && err != HINIC3_PF_SET_VF_ALREADY)
+		return err;
+
+	rte_ether_addr_copy(&eth_dev->data->mac_addrs[0],
+			    &nic_dev->default_addr);
+
+	return 0;
+}
+
+/**
+ * Delete all multicast MAC addresses from the NIC device.
+ *
+ * This function iterates over the list of multicast MAC addresses and removes
+ * each address from the NIC device by calling `hinic3_del_mac`. After each
+ * deletion, the address is reset to zero.
+ *
+ * @param[in] nic_dev
+ * Pointer to NIC device structure.
+ */
+static void
+hinic3_delete_mc_addr_list(struct hinic3_nic_dev *nic_dev)
+{
+	uint16_t func_id;
+	uint32_t i;
+
+	func_id = hinic3_global_func_id(nic_dev->hwdev);
+
+	for (i = 0; i < HINIC3_MAX_MC_MAC_ADDRS; i++) {
+		if (rte_is_zero_ether_addr(&nic_dev->mc_list[i]))
+			break;
+
+		hinic3_del_mac(nic_dev->hwdev, nic_dev->mc_list[i].addr_bytes, 0, func_id);
+		memset(&nic_dev->mc_list[i], 0, sizeof(struct rte_ether_addr));
+	}
+}
+
+/**
+ * Deinit mac_vlan table in hardware.
+ *
+ * @param[in] eth_dev
+ * Pointer to ethernet device structure.
+ */
+static void
+hinic3_deinit_mac_addr(struct rte_eth_dev *eth_dev)
+{
+	struct hinic3_nic_dev *nic_dev =
+		HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
+	uint16_t func_id = 0;
+	int err;
+	int i;
+
+	func_id = hinic3_global_func_id(nic_dev->hwdev);
+
+	for (i = 0; i < HINIC3_MAX_UC_MAC_ADDRS; i++) {
+		if (rte_is_zero_ether_addr(&eth_dev->data->mac_addrs[i]))
+			continue;
+
+		err = hinic3_del_mac(nic_dev->hwdev,
+				     eth_dev->data->mac_addrs[i].addr_bytes, 0, func_id);
+		if (err && err != HINIC3_PF_SET_VF_ALREADY)
+			PMD_DRV_LOG(ERR,
+				    "Delete mac table failed, dev_name: %s",
+				    eth_dev->data->name);
+
+		memset(&eth_dev->data->mac_addrs[i], 0,
+		       sizeof(struct rte_ether_addr));
+	}
+
+	/* Delete multicast mac addrs. */
+	hinic3_delete_mc_addr_list(nic_dev);
+}
+
+/**
+ * Check the valid CoS bitmap to determine the available CoS IDs and set
+ * the default CoS ID to the highest valid one.
+ *
+ * @param[in] hwdev
+ * Pointer to hardware device structure.
+ * @param[out] cos_id
+ * Pointer to store the default CoS ID.
+ *
+ * @return
+ * 0 on success, non-zero on failure.
+ */
+static int
+hinic3_pf_get_default_cos(struct hinic3_hwdev *hwdev, uint8_t *cos_id)
+{
+	uint8_t default_cos = 0;
+	uint8_t valid_cos_bitmap;
+	uint8_t i;
+
+	valid_cos_bitmap = hwdev->cfg_mgmt->svc_cap.cos_valid_bitmap;
+	if (!valid_cos_bitmap) {
+		PMD_DRV_LOG(ERR, "PF has none cos to support");
+		return -EFAULT;
+	}
+
+	for (i = 0; i < HINIC3_COS_NUM_MAX; i++) {
+		if (valid_cos_bitmap & RTE_BIT32(i))
+			/* Find max cos id as default cos. */
+			default_cos = i;
+	}
+
+	*cos_id = default_cos;
+
+	return 0;
+}
+
+static int
+hinic3_init_default_cos(struct hinic3_nic_dev *nic_dev)
+{
+	uint8_t cos_id = 0;
+	int err;
+
+	if (!HINIC3_IS_VF(nic_dev->hwdev)) {
+		err = hinic3_pf_get_default_cos(nic_dev->hwdev, &cos_id);
+		if (err) {
+			PMD_DRV_LOG(ERR, "Get PF default cos failed, err: %d", err);
+			return err;
+		}
+	} else {
+		err = hinic3_vf_get_default_cos(nic_dev->hwdev, &cos_id);
+		if (err) {
+			PMD_DRV_LOG(ERR, "Get VF default cos failed, err: %d", err);
+			return err;
+		}
+	}
+
+	nic_dev->default_cos = cos_id;
+	PMD_DRV_LOG(DEBUG, "Default cos %d", nic_dev->default_cos);
+	return 0;
+}
+
+/**
+ * Initialize Class of Service (CoS). For PF devices, it also sync the link
+ * status with the physical port.
+ *
+ * @param[in] nic_dev
+ * Pointer to NIC device structure.
+ *
+ * @return
+ * 0 on success, non-zero on failure.
+ */
+static int
+hinic3_set_default_hw_feature(struct hinic3_nic_dev *nic_dev)
+{
+	int err;
+
+	err = hinic3_init_default_cos(nic_dev);
+	if (err)
+		return err;
+
+	if (hinic3_func_type(nic_dev->hwdev) == TYPE_VF)
+		return 0;
+
+	err = hinic3_set_link_status_follow(nic_dev->hwdev,
+					    HINIC3_LINK_FOLLOW_PORT);
+	if (err == HINIC3_MGMT_CMD_UNSUPPORTED)
+		PMD_DRV_LOG(WARNING, "Don't support to set link status follow phy port status");
+	else if (err)
+		return err;
+
+	return 0;
+}
+
+static int
+hinic3_init_sw_rxtxqs(struct hinic3_nic_dev *nic_dev)
+{
+	uint32_t txq_size;
+	uint32_t rxq_size;
+
+	/* Allocate software txq array. */
+	txq_size = nic_dev->max_sqs * sizeof(*nic_dev->txqs);
+	nic_dev->txqs =
+		rte_zmalloc("hinic3_txqs", txq_size, RTE_CACHE_LINE_SIZE);
+	if (!nic_dev->txqs) {
+		PMD_DRV_LOG(ERR, "Allocate txqs failed");
+		return -ENOMEM;
+	}
+
+	/* Allocate software rxq array. */
+	rxq_size = nic_dev->max_rqs * sizeof(*nic_dev->rxqs);
+	nic_dev->rxqs =
+		rte_zmalloc("hinic3_rxqs", rxq_size, RTE_CACHE_LINE_SIZE);
+	if (!nic_dev->rxqs) {
+		/* Free txqs. */
+		rte_free(nic_dev->txqs);
+		nic_dev->txqs = NULL;
+
+		PMD_DRV_LOG(ERR, "Allocate rxqs failed");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void
+hinic3_deinit_sw_rxtxqs(struct hinic3_nic_dev *nic_dev)
+{
+	rte_free(nic_dev->txqs);
+	nic_dev->txqs = NULL;
+
+	rte_free(nic_dev->rxqs);
+	nic_dev->rxqs = NULL;
+}
diff --git a/drivers/net/hinic3/hinic3_ethdev.h b/drivers/net/hinic3/hinic3_ethdev.h
new file mode 100644
index 0000000000..fbefed10a2
--- /dev/null
+++ b/drivers/net/hinic3/hinic3_ethdev.h
@@ -0,0 +1,118 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2025 Huawei Technologies Co., Ltd
+ */
+
+#ifndef _HINIC3_ETHDEV_H_
+#define _HINIC3_ETHDEV_H_
+
+#include <rte_ethdev.h>
+#include <rte_ethdev_core.h>
+
+#define HINIC3_PMD_DRV_VERSION "B106"
+
+#define PCI_DEV_TO_INTR_HANDLE(pci_dev) ((pci_dev)->intr_handle)
+
+#define HINIC3_PKT_RX_L4_CKSUM_BAD     RTE_MBUF_F_RX_L4_CKSUM_BAD
+#define HINIC3_PKT_RX_IP_CKSUM_BAD     RTE_MBUF_F_RX_IP_CKSUM_BAD
+#define HINIC3_PKT_RX_IP_CKSUM_UNKNOWN RTE_MBUF_F_RX_IP_CKSUM_UNKNOWN
+#define HINIC3_PKT_RX_L4_CKSUM_GOOD    RTE_MBUF_F_RX_L4_CKSUM_GOOD
+#define HINIC3_PKT_RX_IP_CKSUM_GOOD    RTE_MBUF_F_RX_IP_CKSUM_GOOD
+#define HINIC3_PKT_TX_TCP_SEG	       RTE_MBUF_F_TX_TCP_SEG
+#define HINIC3_PKT_TX_UDP_CKSUM	       RTE_MBUF_F_TX_UDP_CKSUM
+#define HINIC3_PKT_TX_TCP_CKSUM	       RTE_MBUF_F_TX_TCP_CKSUM
+#define HINIC3_PKT_TX_IP_CKSUM	       RTE_MBUF_F_TX_IP_CKSUM
+#define HINIC3_PKT_TX_VLAN_PKT	       RTE_MBUF_F_TX_VLAN
+#define HINIC3_PKT_TX_L4_MASK	       RTE_MBUF_F_TX_L4_MASK
+#define HINIC3_PKT_TX_SCTP_CKSUM       RTE_MBUF_F_TX_SCTP_CKSUM
+#define HINIC3_PKT_TX_IPV6	       RTE_MBUF_F_TX_IPV6
+#define HINIC3_PKT_TX_IPV4	       RTE_MBUF_F_TX_IPV4
+#define HINIC3_PKT_RX_VLAN	       RTE_MBUF_F_RX_VLAN
+#define HINIC3_PKT_RX_VLAN_STRIPPED    RTE_MBUF_F_RX_VLAN_STRIPPED
+#define HINIC3_PKT_RX_RSS_HASH	       RTE_MBUF_F_RX_RSS_HASH
+#define HINIC3_PKT_TX_TUNNEL_MASK      RTE_MBUF_F_TX_TUNNEL_MASK
+#define HINIC3_PKT_TX_TUNNEL_VXLAN     RTE_MBUF_F_TX_TUNNEL_VXLAN
+#define HINIC3_PKT_TX_OUTER_IP_CKSUM   RTE_MBUF_F_TX_OUTER_IP_CKSUM
+#define HINIC3_PKT_TX_OUTER_IPV6       RTE_MBUF_F_TX_OUTER_IPV6
+#define HINIC3_PKT_RX_LRO	       RTE_MBUF_F_RX_LRO
+#define HINIC3_PKT_TX_L4_NO_CKSUM      RTE_MBUF_F_TX_L4_NO_CKSUM
+
+#define HINCI3_CPY_MEMPOOL_NAME "cpy_mempool"
+/* Mbuf pool for copy invalid mbuf segs. */
+#define HINIC3_COPY_MEMPOOL_DEPTH 1024
+#define HINIC3_COPY_MEMPOOL_CACHE 128
+#define HINIC3_COPY_MBUF_SIZE	  4096
+
+#define HINIC3_DEV_NAME_LEN 32
+#define DEV_STOP_DELAY_MS   100
+#define DEV_START_DELAY_MS  100
+#define HINIC3_FLUSH_QUEUE_TIMEOUT 3000
+
+#define HINIC3_UINT32_BIT_SIZE (CHAR_BIT * sizeof(uint32_t))
+#define HINIC3_VFTA_SIZE       (4096 / HINIC3_UINT32_BIT_SIZE)
+#define HINIC3_MAX_QUEUE_NUM   64
+
+#define HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev) \
+	((struct hinic3_nic_dev *)(dev)->data->dev_private)
+
+enum hinic3_dev_status {
+	HINIC3_DEV_INIT,
+	HINIC3_DEV_CLOSE,
+	HINIC3_DEV_START,
+	HINIC3_DEV_INTR_EN
+};
+
+enum hinic3_tx_cvlan_type {
+	HINIC3_TX_TPID0,
+};
+
+enum nic_feature_cap {
+	NIC_F_CSUM = RTE_BIT32(0),
+	NIC_F_SCTP_CRC = RTE_BIT32(1),
+	NIC_F_TSO = RTE_BIT32(2),
+	NIC_F_LRO = RTE_BIT32(3),
+	NIC_F_UFO = RTE_BIT32(4),
+	NIC_F_RSS = RTE_BIT32(5),
+	NIC_F_RX_VLAN_FILTER = RTE_BIT32(6),
+	NIC_F_RX_VLAN_STRIP = RTE_BIT32(7),
+	NIC_F_TX_VLAN_INSERT = RTE_BIT32(8),
+	NIC_F_VXLAN_OFFLOAD = RTE_BIT32(9),
+	NIC_F_IPSEC_OFFLOAD = RTE_BIT32(10),
+	NIC_F_FDIR = RTE_BIT32(11),
+	NIC_F_PROMISC = RTE_BIT32(12),
+	NIC_F_ALLMULTI = RTE_BIT32(13),
+};
+
+#define DEFAULT_DRV_FEATURE 0x3FFF
+
+struct hinic3_nic_dev {
+	struct hinic3_hwdev *hwdev; /**< Hardware device. */
+	struct hinic3_txq **txqs;
+	struct hinic3_rxq **rxqs;
+	struct rte_mempool *cpy_mpool;
+
+	uint16_t num_sqs;
+	uint16_t num_rqs;
+	uint16_t max_sqs;
+	uint16_t max_rqs;
+
+	uint16_t rx_buff_len;
+	uint16_t mtu_size;
+
+	uint32_t rx_mode;
+	uint8_t rx_queue_list[HINIC3_MAX_QUEUE_NUM];
+	rte_spinlock_t queue_list_lock;
+
+	uint32_t default_cos;
+	uint32_t rx_csum_en;
+
+	RTE_ATOMIC(uint64_t)dev_status;
+
+	struct rte_ether_addr default_addr;
+	struct rte_ether_addr *mc_list;
+
+	char dev_name[HINIC3_DEV_NAME_LEN];
+	uint64_t feature_cap;
+	uint32_t vfta[HINIC3_VFTA_SIZE]; /**< VLAN bitmap. */
+};
+
+#endif /* _HINIC3_ETHDEV_H_ */
diff --git a/drivers/net/hinic3/meson.build b/drivers/net/hinic3/meson.build
new file mode 100644
index 0000000000..018b300f75
--- /dev/null
+++ b/drivers/net/hinic3/meson.build
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2025 Huawei Technologies Co., Ltd
+
+if not is_linux
+    build = false
+    reason = 'only supported on Linux'
+    subdir_done()
+endif
+
+if (arch_subdir != 'x86' and arch_subdir != 'arm'
+        or not dpdk_conf.get('RTE_ARCH_64'))
+    build = false
+    reason = 'only supported on x86_64 and aarch64'
+    subdir_done()
+endif
+
+cflags += ['-DHW_CONVERT_ENDIAN']
+
+subdir('base')
+
+sources = files(
+        'hinic3_ethdev.c',
+)
+
+includes += include_directories('base')
\ No newline at end of file
-- 
2.47.0.windows.2



More information about the dev mailing list