[PATCH v3 1/1] net/nbl: add igb uio support for NBL VF devices

Dimon Zhao dimon.zhao at nebula-matrix.com
Wed Feb 25 04:39:42 CET 2026


Due to a chip design limitation, only the VF
supports the igb_uio driver. The PF does not.

The igb_uio driver requires allocating interrupts and configuring the
PCIe MSI-X table before the driver's probe function is called.
This pre-probe configuration is only possible on the VF due to the
hardware limitation; the PF can only configure the MSI-X table during
its probe process.

Therefore, using igb_uio on the PF will fail.
This commit clarifies this restriction.

Signed-off-by: Dimon Zhao <dimon.zhao at nebula-matrix.com>
---
 doc/guides/nics/nbl.rst                       | 11 ++++
 doc/guides/rel_notes/release_26_03.rst        |  4 ++
 drivers/net/nbl/nbl_core.c                    |  2 +
 drivers/net/nbl/nbl_dev/nbl_dev.c             | 33 ++++++++++--
 drivers/net/nbl/nbl_dev/nbl_dev.h             |  3 ++
 drivers/net/nbl/nbl_dispatch.c                | 50 +++++++++++++++++++
 drivers/net/nbl/nbl_ethdev.c                  | 13 +++++
 .../nbl_hw/nbl_hw_leonis/nbl_hw_leonis_snic.c | 12 +++++
 .../nbl_hw/nbl_hw_leonis/nbl_hw_leonis_snic.h |  9 ++++
 .../nbl/nbl_hw/nbl_hw_leonis/nbl_res_leonis.c | 10 ++++
 drivers/net/nbl/nbl_include/nbl_def_channel.h |  5 ++
 .../net/nbl/nbl_include/nbl_def_dispatch.h    |  3 ++
 drivers/net/nbl/nbl_include/nbl_def_hw.h      |  3 ++
 .../net/nbl/nbl_include/nbl_def_resource.h    |  3 ++
 14 files changed, 157 insertions(+), 4 deletions(-)

diff --git a/doc/guides/nics/nbl.rst b/doc/guides/nics/nbl.rst
index ba0a119dfd..c74826a3c2 100644
--- a/doc/guides/nics/nbl.rst
+++ b/doc/guides/nics/nbl.rst
@@ -101,3 +101,14 @@ Limitations or Known Issues
 32-bit architectures are not supported.
 
 Windows and BSD are not supported yet.
+
+**igb_uio Driver Support**
+
+Due to chip design limitations, only the VF supports the ``igb_uio`` driver,
+PF does not support this driver.
+
+**uio_pci_generic Driver Support**
+
+The ``uio_pci_generic`` driver is not supported on either PF or VF devices.
+This is because the NBL PMD requires MSI-X interrupts to receive mailbox
+messages, but the ``uio_pci_generic`` driver does not support MSI-X interrupts.
diff --git a/doc/guides/rel_notes/release_26_03.rst b/doc/guides/rel_notes/release_26_03.rst
index 0a78b86fee..f8f3017a08 100644
--- a/doc/guides/rel_notes/release_26_03.rst
+++ b/doc/guides/rel_notes/release_26_03.rst
@@ -112,6 +112,10 @@ New Features
   Added handling of the key combination Control+L
   to clear the screen before redisplaying the prompt.
 
+* **Updated NBL driver.**
+
+  * Added support for igb_uio driver on VF devices.
+
 Removed Items
 -------------
 
diff --git a/drivers/net/nbl/nbl_core.c b/drivers/net/nbl/nbl_core.c
index 313f8c5bd6..df8c0c76ed 100644
--- a/drivers/net/nbl/nbl_core.c
+++ b/drivers/net/nbl/nbl_core.c
@@ -41,6 +41,8 @@ int nbl_core_init(struct nbl_adapter *adapter, struct rte_eth_dev *eth_dev)
 	common->eth_dev = eth_dev;
 	nbl_init_func_caps(pci_dev, &adapter->caps);
 
+	common->is_vf = (pci_dev->id.device_id == NBL_DEVICE_ID_M18100_VF);
+
 	product_base_ops = nbl_core_get_product_ops(adapter->caps.product_type);
 
 	/* every product's hw/chan/res layer has a great difference, so call their own init ops */
diff --git a/drivers/net/nbl/nbl_dev/nbl_dev.c b/drivers/net/nbl/nbl_dev/nbl_dev.c
index 2b0413fb7c..9573f465fb 100644
--- a/drivers/net/nbl/nbl_dev/nbl_dev.c
+++ b/drivers/net/nbl/nbl_dev/nbl_dev.c
@@ -857,8 +857,12 @@ static void nbl_dev_mailbox_interrupt_handler(void *cn_arg)
 {
 	struct nbl_dev_mgt *dev_mgt = (struct nbl_dev_mgt *)cn_arg;
 	const struct nbl_channel_ops *chan_ops = NBL_DEV_MGT_TO_CHAN_OPS(dev_mgt);
+	struct nbl_dev_net_mgt *net_dev = NBL_DEV_MGT_TO_NET_DEV(dev_mgt);
 
 	chan_ops->notify_interrupt(NBL_DEV_MGT_TO_CHAN_PRIV(dev_mgt));
+
+	if (net_dev->net_msix_mask_en)
+		rte_write32(net_dev->irq_data, net_dev->irq_enable_base);
 }
 
 static int nbl_dev_common_start(struct nbl_dev_mgt *dev_mgt)
@@ -873,6 +877,7 @@ static int nbl_dev_common_start(struct nbl_dev_mgt *dev_mgt)
 	u8 *mac;
 	int ret;
 	u16 priv_cnt = 0;
+	u16 global_vector_id = 0;
 
 	board_info = &common->board_info;
 	disp_ops->get_board_info(NBL_DEV_MGT_TO_DISP_PRIV(dev_mgt), board_info);
@@ -881,9 +886,26 @@ static int nbl_dev_common_start(struct nbl_dev_mgt *dev_mgt)
 	disp_ops->clear_flow(NBL_DEV_MGT_TO_DISP_PRIV(dev_mgt), net_dev->vsi_id);
 
 	if (NBL_IS_NOT_COEXISTENCE(common)) {
-		ret = disp_ops->configure_msix_map(NBL_DEV_MGT_TO_DISP_PRIV(dev_mgt), 0, 1, 0);
-		if (ret)
-			goto configure_msix_map_failed;
+		if (pci_dev->kdrv == RTE_PCI_KDRV_VFIO) {
+			ret = disp_ops->configure_msix_map(NBL_DEV_MGT_TO_DISP_PRIV(dev_mgt),
+							   0, 1, 0);
+			if (ret)
+				goto configure_msix_map_failed;
+		} else {
+			ret = disp_ops->get_global_vector(NBL_DEV_MGT_TO_DISP_PRIV(dev_mgt),
+							  net_dev->vsi_id, 0, &global_vector_id);
+			if (ret)
+				goto get_global_vector_failed;
+			net_dev->irq_enable_base =
+			disp_ops->get_msix_irq_enable_info(NBL_DEV_MGT_TO_DISP_PRIV(dev_mgt),
+							   global_vector_id, &net_dev->irq_data);
+			if (!net_dev->irq_enable_base) {
+				ret = -EINVAL;
+				goto get_msix_irq_enable_info_failed;
+			}
+			net_dev->net_msix_mask_en = true;
+			rte_write32(net_dev->irq_data, net_dev->irq_enable_base);
+		}
 
 		ret = disp_ops->enable_mailbox_irq(NBL_DEV_MGT_TO_DISP_PRIV(dev_mgt), 0, true);
 		if (ret)
@@ -960,7 +982,10 @@ static int nbl_dev_common_start(struct nbl_dev_mgt *dev_mgt)
 	}
 enable_mailbox_irq_failed:
 	if (NBL_IS_NOT_COEXISTENCE(common))
-		disp_ops->destroy_msix_map(NBL_DEV_MGT_TO_DISP_PRIV(dev_mgt));
+		if (pci_dev->kdrv == RTE_PCI_KDRV_VFIO)
+			disp_ops->destroy_msix_map(NBL_DEV_MGT_TO_DISP_PRIV(dev_mgt));
+get_msix_irq_enable_info_failed:
+get_global_vector_failed:
 configure_msix_map_failed:
 	return ret;
 }
diff --git a/drivers/net/nbl/nbl_dev/nbl_dev.h b/drivers/net/nbl/nbl_dev/nbl_dev.h
index bfe2b06deb..230a983cf4 100644
--- a/drivers/net/nbl/nbl_dev/nbl_dev.h
+++ b/drivers/net/nbl/nbl_dev/nbl_dev.h
@@ -62,6 +62,9 @@ struct nbl_dev_net_mgt {
 	bool hw_stats_inited;
 	rte_thread_t tid;
 	int fd[2];
+	bool net_msix_mask_en;
+	u8 *irq_enable_base;
+	u32 irq_data;
 };
 
 struct nbl_dev_mgt {
diff --git a/drivers/net/nbl/nbl_dispatch.c b/drivers/net/nbl/nbl_dispatch.c
index 52d37ba7fe..9bf6412cec 100644
--- a/drivers/net/nbl/nbl_dispatch.c
+++ b/drivers/net/nbl/nbl_dispatch.c
@@ -80,6 +80,50 @@ static int nbl_disp_chan_enable_mailbox_irq_req(void *priv, u16 vector_id, bool
 	return chan_ops->send_msg(NBL_DISP_MGT_TO_CHAN_PRIV(disp_mgt), &chan_send);
 }
 
+static int nbl_disp_get_global_vector(void *priv, u16 vsi_id,
+				      u16 local_vector_id, u16 *global_vector_id)
+{
+	struct nbl_dispatch_mgt *disp_mgt = (struct nbl_dispatch_mgt *)priv;
+	struct nbl_resource_ops *res_ops = NBL_DISP_MGT_TO_RES_OPS(disp_mgt);
+	int ret = 0;
+
+	ret = NBL_OPS_CALL(res_ops->get_global_vector,
+			   (NBL_DISP_MGT_TO_RES_PRIV(disp_mgt),
+			    vsi_id, local_vector_id, global_vector_id));
+	return ret;
+}
+
+static int nbl_disp_chan_get_global_vector_req(void *priv, u16 vsi_id,
+					       u16 local_vector_id, u16 *global_vector_id)
+{
+	struct nbl_dispatch_mgt *disp_mgt = (struct nbl_dispatch_mgt *)priv;
+	const struct nbl_channel_ops *chan_ops = NBL_DISP_MGT_TO_CHAN_OPS(disp_mgt);
+	struct nbl_chan_param_get_global_vector param = {0};
+	struct nbl_chan_param_get_global_vector result = {0};
+	struct nbl_chan_send_info chan_send;
+	int ret;
+
+	param.vsi_id = vsi_id;
+	param.vector_id = local_vector_id;
+
+	NBL_CHAN_SEND(chan_send, 0, NBL_CHAN_MSG_GET_GLOBAL_VECTOR,
+		      &param, sizeof(param), &result, sizeof(result), 1);
+	ret = chan_ops->send_msg(NBL_DISP_MGT_TO_CHAN_PRIV(disp_mgt), &chan_send);
+	if (!ret)
+		*global_vector_id = result.vector_id;
+
+	return ret;
+}
+
+static u8 *nbl_disp_get_msix_irq_enable_info(void *priv, u16 global_vector_id, u32 *irq_data)
+{
+	struct nbl_dispatch_mgt *disp_mgt = (struct nbl_dispatch_mgt *)priv;
+	struct nbl_resource_ops *res_ops = NBL_DISP_MGT_TO_RES_OPS(disp_mgt);
+
+	return NBL_OPS_CALL(res_ops->get_msix_irq_enable_info,
+			    (NBL_DISP_MGT_TO_RES_PRIV(disp_mgt), global_vector_id, irq_data));
+}
+
 static int nbl_disp_alloc_txrx_queues(void *priv, u16 vsi_id, u16 queue_num)
 {
 	struct nbl_dispatch_mgt *disp_mgt = (struct nbl_dispatch_mgt *)priv;
@@ -1035,6 +1079,12 @@ do {									\
 			 NBL_DISP_CTRL_LVL_MGT, NBL_CHAN_MSG_MAILBOX_ENABLE_IRQ,		\
 			 nbl_disp_chan_enable_mailbox_irq_req,					\
 			 NULL);				\
+	NBL_DISP_SET_OPS(get_global_vector, nbl_disp_get_global_vector,				\
+			 NBL_DISP_CTRL_LVL_MGT, NBL_CHAN_MSG_GET_GLOBAL_VECTOR,			\
+			 nbl_disp_chan_get_global_vector_req, NULL);				\
+	NBL_DISP_SET_OPS(get_msix_irq_enable_info, nbl_disp_get_msix_irq_enable_info,		\
+			 NBL_DISP_CTRL_LVL_NET, -1,						\
+			 NULL, NULL);								\
 	NBL_DISP_SET_OPS(alloc_txrx_queues, nbl_disp_alloc_txrx_queues,	\
 			 NBL_DISP_CTRL_LVL_MGT,				\
 			 NBL_CHAN_MSG_ALLOC_TXRX_QUEUES,		\
diff --git a/drivers/net/nbl/nbl_ethdev.c b/drivers/net/nbl/nbl_ethdev.c
index d269ea8058..875a93f4b2 100644
--- a/drivers/net/nbl/nbl_ethdev.c
+++ b/drivers/net/nbl/nbl_ethdev.c
@@ -88,6 +88,19 @@ static int nbl_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 		NBL_LOG(ERR, "Secondary process is not supported.");
 		return -ENOTSUP;
 	}
+
+	if (pci_dev->kdrv == RTE_PCI_KDRV_UIO_GENERIC) {
+		NBL_LOG(ERR, "uio_pci_generic is not supported.");
+		return -ENOTSUP;
+	}
+
+	if (pci_dev->kdrv == RTE_PCI_KDRV_IGB_UIO) {
+		if (pci_dev->id.device_id != NBL_DEVICE_ID_M18100_VF) {
+			NBL_LOG(ERR, "Only VF support igb_uio.");
+			return -ENOTSUP;
+		}
+	}
+
 	return rte_eth_dev_pci_generic_probe(pci_dev, sizeof(struct nbl_adapter),
 					     nbl_eth_dev_init);
 }
diff --git a/drivers/net/nbl/nbl_hw/nbl_hw_leonis/nbl_hw_leonis_snic.c b/drivers/net/nbl/nbl_hw/nbl_hw_leonis/nbl_hw_leonis_snic.c
index 9e89a3be5f..58ebe8a4d4 100644
--- a/drivers/net/nbl/nbl_hw/nbl_hw_leonis/nbl_hw_leonis_snic.c
+++ b/drivers/net/nbl/nbl_hw/nbl_hw_leonis/nbl_hw_leonis_snic.c
@@ -138,6 +138,15 @@ static void nbl_hw_update_mailbox_queue_tail_ptr(void *priv, u16 tail_ptr, u8 tx
 	rte_delay_us(NBL_NOTIFY_DELAY_MIN_TIME_FOR_REGS);
 }
 
+static u8 *nbl_phy_get_msix_irq_enable_info(void *priv, u16 global_vector_id, u32 *irq_data)
+{
+	struct nbl_hw_mgt *hw_mgt = (struct nbl_hw_mgt *)priv;
+
+	*irq_data = (global_vector_id & 0x1FFF);
+
+	return (hw_mgt->hw_addr + NBL_PCOMPLETER_MSIX_NOTIFY_OFFSET);
+}
+
 const struct nbl_hw_ops nbl_hw_ops = {
 	.update_tail_ptr		= nbl_hw_update_tail_ptr,
 	.get_tail_ptr			= nbl_hw_get_tail_ptr,
@@ -149,6 +158,9 @@ const struct nbl_hw_ops nbl_hw_ops = {
 	.stop_mailbox_txq		= nbl_hw_stop_mailbox_txq,
 	.get_mailbox_rx_tail_ptr	= nbl_hw_get_mailbox_rx_tail_ptr,
 	.update_mailbox_queue_tail_ptr	= nbl_hw_update_mailbox_queue_tail_ptr,
+
+	/* irq */
+	.get_msix_irq_enable_info	= nbl_phy_get_msix_irq_enable_info,
 };
 
 static int nbl_hw_setup_ops(struct nbl_hw_ops_tbl **hw_ops_tbl,
diff --git a/drivers/net/nbl/nbl_hw/nbl_hw_leonis/nbl_hw_leonis_snic.h b/drivers/net/nbl/nbl_hw/nbl_hw_leonis/nbl_hw_leonis_snic.h
index fc276e83d6..9275cd5482 100644
--- a/drivers/net/nbl/nbl_hw/nbl_hw_leonis/nbl_hw_leonis_snic.h
+++ b/drivers/net/nbl/nbl_hw/nbl_hw_leonis/nbl_hw_leonis_snic.h
@@ -50,4 +50,13 @@ struct nbl_mailbox_qinfo_cfg_dbg_tbl {
 	u16 tx_tail_ptr;
 };
 
+#define NBL_PCOMPLETER_MSIX_NOTIFY_OFFSET	(0x1020)
+
+struct nbl_msix_notify {
+	u32 glb_msix_idx:13;
+	u32 rsv1:3;
+	u32 mask:1;
+	u32 rsv2:15;
+};
+
 #endif
diff --git a/drivers/net/nbl/nbl_hw/nbl_hw_leonis/nbl_res_leonis.c b/drivers/net/nbl/nbl_hw/nbl_hw_leonis/nbl_res_leonis.c
index 5d40d4f5f8..189f8feb56 100644
--- a/drivers/net/nbl/nbl_hw/nbl_hw_leonis/nbl_res_leonis.c
+++ b/drivers/net/nbl/nbl_hw/nbl_hw_leonis/nbl_res_leonis.c
@@ -115,9 +115,19 @@ static int nbl_get_xstats_names(__rte_unused void *priv,
 	return 0;
 }
 
+static u8 *nbl_res_get_msix_irq_enable_info(void *priv, u16 global_vector_id, u32 *irq_data)
+{
+	struct nbl_resource_mgt *res_mgt = (struct nbl_resource_mgt *)priv;
+	const struct nbl_hw_ops *hw_ops = NBL_RES_MGT_TO_HW_OPS(res_mgt);
+
+	return hw_ops->get_msix_irq_enable_info(NBL_RES_MGT_TO_HW_PRIV(res_mgt),
+						global_vector_id, irq_data);
+}
+
 static struct nbl_resource_ops nbl_res_ops = {
 	.get_hw_xstats_cnt = nbl_get_xstats_cnt,
 	.get_hw_xstats_names = nbl_get_xstats_names,
+	.get_msix_irq_enable_info = nbl_res_get_msix_irq_enable_info,
 };
 
 static bool is_ops_inited;
diff --git a/drivers/net/nbl/nbl_include/nbl_def_channel.h b/drivers/net/nbl/nbl_include/nbl_def_channel.h
index 55880737f1..d31e3bc772 100644
--- a/drivers/net/nbl/nbl_include/nbl_def_channel.h
+++ b/drivers/net/nbl/nbl_include/nbl_def_channel.h
@@ -314,6 +314,11 @@ struct nbl_chan_param_enable_mailbox_irq {
 	bool enable_msix;
 };
 
+struct nbl_chan_param_get_global_vector {
+	u16 vsi_id;
+	u16 vector_id;
+};
+
 struct nbl_chan_param_register_net_info {
 	u16 pf_bdf;
 	u64 vf_bar_start;
diff --git a/drivers/net/nbl/nbl_include/nbl_def_dispatch.h b/drivers/net/nbl/nbl_include/nbl_def_dispatch.h
index 45e7504a07..79c3518795 100644
--- a/drivers/net/nbl/nbl_include/nbl_def_dispatch.h
+++ b/drivers/net/nbl/nbl_include/nbl_def_dispatch.h
@@ -23,6 +23,9 @@ struct nbl_dispatch_ops {
 				  bool net_msix_mask_en);
 	int (*destroy_msix_map)(void *priv);
 	int (*enable_mailbox_irq)(void *p, u16 vector_id, bool enable_msix);
+	int (*get_global_vector)(void *priv, u16 vsi_id,
+				 u16 local_vector_id, u16 *global_vector_id);
+	u8 *(*get_msix_irq_enable_info)(void *priv, u16 global_vector_id, u32 *irq_data);
 	void (*get_resource_pt_ops)(void *priv, struct nbl_resource_pt_ops *pt_ops, bool offload);
 	int (*register_net)(void *priv,
 			    struct nbl_register_net_param *register_param,
diff --git a/drivers/net/nbl/nbl_include/nbl_def_hw.h b/drivers/net/nbl/nbl_include/nbl_def_hw.h
index 285ca98570..7bf05276cc 100644
--- a/drivers/net/nbl/nbl_include/nbl_def_hw.h
+++ b/drivers/net/nbl/nbl_include/nbl_def_hw.h
@@ -22,6 +22,9 @@ struct nbl_hw_ops {
 	void (*stop_mailbox_txq)(void *priv);
 	uint16_t (*get_mailbox_rx_tail_ptr)(void *priv);
 	void (*update_mailbox_queue_tail_ptr)(void *priv, uint16_t tail_ptr, uint8_t txrx);
+
+	/* irq */
+	u8 *(*get_msix_irq_enable_info)(void *priv, u16 global_vector_id, u32 *irq_data);
 };
 
 struct nbl_hw_ops_tbl {
diff --git a/drivers/net/nbl/nbl_include/nbl_def_resource.h b/drivers/net/nbl/nbl_include/nbl_def_resource.h
index 6935598789..f044927bce 100644
--- a/drivers/net/nbl/nbl_include/nbl_def_resource.h
+++ b/drivers/net/nbl/nbl_include/nbl_def_resource.h
@@ -21,6 +21,9 @@ struct nbl_resource_ops {
 				  bool net_msix_mask_en);
 	int (*destroy_msix_map)(void *priv, u16 func_id);
 	int (*enable_mailbox_irq)(void *priv, u16 func_id, u16 vector_id, bool enable_msix);
+	int (*get_global_vector)(void *priv, u16 vsi_id,
+				 u16 local_vector_id, u16 *global_vector_id);
+	u8 *(*get_msix_irq_enable_info)(void *priv, u16 global_vector_id, u32 *irq_data);
 	void (*get_resource_pt_ops)(void *priv, struct nbl_resource_pt_ops *pt_ops, bool offload);
 	int (*register_net)(void *priv,
 			    struct nbl_register_net_param *register_param,
-- 
2.34.1



More information about the dev mailing list