new file mode 100644
@@ -0,0 +1,11 @@
+;
+; Supported features of the 'ngbe_vf' network poll mode driver.
+;
+; Refer to default.ini for the full list of available PMD features.
+;
+[Features]
+Multiprocess aware = Y
+Linux = Y
+ARMv8 = Y
+x86-32 = Y
+x86-64 = Y
\ No newline at end of file
@@ -10,6 +10,7 @@ sources = [
'ngbe_phy_rtl.c',
'ngbe_phy_mvl.c',
'ngbe_phy_yt.c',
+ 'ngbe_vf.c',
]
error_cflags = []
@@ -11,5 +11,6 @@
#include "ngbe_eeprom.h"
#include "ngbe_phy.h"
#include "ngbe_hw.h"
+#include "ngbe_vf.h"
#endif /* _NGBE_H_ */
@@ -9,6 +9,7 @@
#include "ngbe_eeprom.h"
#include "ngbe_mng.h"
#include "ngbe_hw.h"
+#include "ngbe_vf.h"
static s32 ngbe_is_lldp(struct ngbe_hw *hw)
{
@@ -2113,6 +2114,9 @@ s32 ngbe_init_shared_code(struct ngbe_hw *hw)
case ngbe_mac_em:
ngbe_init_ops_pf(hw);
break;
+ case ngbe_mac_em_vf:
+ ngbe_init_ops_vf(hw);
+ break;
default:
status = NGBE_ERR_DEVICE_NOT_SUPPORTED;
break;
new file mode 100644
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2025 Beijing WangXun Technology Co., Ltd.
+ * Copyright(c) 2010-2017 Intel Corporation
+ */
+
+#include "ngbe_type.h"
+#include "ngbe_vf.h"
+
+/**
+ * ngbe_init_ops_vf - Initialize the pointers for vf
+ * @hw: pointer to hardware structure
+ *
+ * This will assign function pointers, adapter-specific functions can
+ * override the assignment of generic function pointers by assigning
+ * their own adapter-specific function pointers.
+ * Does not touch the hardware.
+ **/
+s32 ngbe_init_ops_vf(struct ngbe_hw *hw)
+{
+ struct ngbe_mac_info *mac = &hw->mac;
+
+ mac->max_tx_queues = 1;
+ mac->max_rx_queues = 1;
+
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2025 Beijing WangXun Technology Co., Ltd.
+ * Copyright(c) 2010-2017 Intel Corporation
+ */
+
+#ifndef _NGBE_VF_H_
+#define _NGBE_VF_H_
+
+#include "ngbe_type.h"
+
+s32 ngbe_init_ops_vf(struct ngbe_hw *hw);
+
+#endif /* __NGBE_VF_H__ */
@@ -15,6 +15,7 @@ sources = files(
'ngbe_ptypes.c',
'ngbe_pf.c',
'ngbe_rxtx.c',
+ 'ngbe_ethdev_vf.c',
)
deps += ['hash']
new file mode 100644
@@ -0,0 +1,163 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2025 Beijing WangXun Technology Co., Ltd.
+ * Copyright(c) 2010-2017 Intel Corporation
+ */
+
+#include <sys/queue.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <ethdev_pci.h>
+
+#include "ngbe_logs.h"
+#include "base/ngbe.h"
+#include "ngbe_ethdev.h"
+#include "ngbe_rxtx.h"
+#include "ngbe_regs_group.h"
+
+#define NGBEVF_PMD_NAME "rte_ngbevf_pmd" /* PMD name */
+static int ngbevf_dev_close(struct rte_eth_dev *dev);
+
+/*
+ * The set of PCI devices this driver supports (for VF)
+ */
+static const struct rte_pci_id pci_id_ngbevf_map[] = {
+ { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860AL_W_VF) },
+ { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860A2_VF) },
+ { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860A2S_VF) },
+ { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860A4_VF) },
+ { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860A4S_VF) },
+ { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860AL2_VF) },
+ { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860AL2S_VF) },
+ { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860AL4_VF) },
+ { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860AL4S_VF) },
+ { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860NCSI_VF) },
+ { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860A1_VF) },
+ { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, NGBE_DEV_ID_EM_WX1860A1L_VF) },
+ { .vendor_id = 0, /* sentinel */ },
+};
+
+static const struct eth_dev_ops ngbevf_eth_dev_ops;
+
+/*
+ * Virtual Function device init
+ */
+static int
+eth_ngbevf_dev_init(struct rte_eth_dev *eth_dev)
+{
+ int err;
+ struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
+ struct ngbe_hw *hw = ngbe_dev_hw(eth_dev);
+
+ PMD_INIT_FUNC_TRACE();
+
+ eth_dev->dev_ops = &ngbevf_eth_dev_ops;
+
+ rte_eth_copy_pci_info(eth_dev, pci_dev);
+
+ hw->device_id = pci_dev->id.device_id;
+ hw->vendor_id = pci_dev->id.vendor_id;
+ hw->sub_system_id = pci_dev->id.subsystem_device_id;
+ ngbe_map_device_id(hw);
+ hw->hw_addr = (void *)pci_dev->mem_resource[0].addr;
+
+ /* Initialize the shared code (base driver) */
+ err = ngbe_init_shared_code(hw);
+ if (err != 0) {
+ PMD_INIT_LOG(ERR,
+ "Shared code init failed for ngbevf: %d", err);
+ return -EIO;
+ }
+
+ hw->mac.num_rar_entries = 32; /* The MAX of the underlying PF */
+
+ /* Allocate memory for storing MAC addresses */
+ eth_dev->data->mac_addrs = rte_zmalloc("ngbevf", RTE_ETHER_ADDR_LEN *
+ hw->mac.num_rar_entries, 0);
+ if (eth_dev->data->mac_addrs == NULL) {
+ PMD_INIT_LOG(ERR,
+ "Failed to allocate %u bytes needed to store MAC addresses",
+ RTE_ETHER_ADDR_LEN * hw->mac.num_rar_entries);
+ return -ENOMEM;
+ }
+
+ PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x mac.type=%s",
+ eth_dev->data->port_id, pci_dev->id.vendor_id,
+ pci_dev->id.device_id, "ngbe_mac_sp_vf");
+
+ return 0;
+}
+
+/* Virtual Function device uninit */
+static int
+eth_ngbevf_dev_uninit(struct rte_eth_dev *eth_dev)
+{
+ PMD_INIT_FUNC_TRACE();
+
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+ return 0;
+
+ ngbevf_dev_close(eth_dev);
+
+ return 0;
+}
+
+static int eth_ngbevf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
+ struct rte_pci_device *pci_dev)
+{
+ return rte_eth_dev_pci_generic_probe(pci_dev,
+ sizeof(struct ngbe_adapter), eth_ngbevf_dev_init);
+}
+
+static int eth_ngbevf_pci_remove(struct rte_pci_device *pci_dev)
+{
+ return rte_eth_dev_pci_generic_remove(pci_dev, eth_ngbevf_dev_uninit);
+}
+
+/*
+ * virtual function driver struct
+ */
+static struct rte_pci_driver rte_ngbevf_pmd = {
+ .id_table = pci_id_ngbevf_map,
+ .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
+ .probe = eth_ngbevf_pci_probe,
+ .remove = eth_ngbevf_pci_remove,
+};
+
+static int
+ngbevf_dev_info_get(struct rte_eth_dev *dev,
+ struct rte_eth_dev_info *dev_info)
+{
+ struct ngbe_hw *hw = ngbe_dev_hw(dev);
+
+ dev_info->max_rx_queues = (uint16_t)hw->mac.max_rx_queues;
+ dev_info->max_tx_queues = (uint16_t)hw->mac.max_tx_queues;
+
+ return 0;
+}
+
+static int
+ngbevf_dev_close(struct rte_eth_dev *dev)
+{
+ PMD_INIT_FUNC_TRACE();
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+ return 0;
+
+ rte_free(dev->data->mac_addrs);
+ dev->data->mac_addrs = NULL;
+
+ return 0;
+}
+
+/*
+ * dev_ops for virtual function, bare necessities for basic vf
+ * operation have been implemented
+ */
+static const struct eth_dev_ops ngbevf_eth_dev_ops = {
+ .dev_infos_get = ngbevf_dev_info_get,
+};
+
+RTE_PMD_REGISTER_PCI(net_ngbe_vf, rte_ngbevf_pmd);
+RTE_PMD_REGISTER_PCI_TABLE(net_ngbe_vf, pci_id_ngbevf_map);
+RTE_PMD_REGISTER_KMOD_DEP(net_ngbe_vf, "* igb_uio | vfio-pci");