Skip to contentSkip to conversation

net/cpfl: fix VF ID calculation for vCPF

PATCH Applied Atul Patel 2 participants 6 messages Aug 28 – Sep 10 Network drivers

lore
Share & tools
lore

Atul Patel

author
#0 lore raw

PATCH 1/1 net/cpfl: fix VF ID calculation for vCPF

The VF ID was incorrectly set to only the PCI function number, which fails when VFs span multiple PCI devices (device IDs > 0). Calculate the VF ID as (device_id * 8) + function to correctly map VFs across devices.

Fixes f1ab44fb0ebf ("net/cpfl: add vCPF port info")
---
 drivers/net/intel/cpfl/cpfl_ethdev.c |  3 ++-
 drivers/net/intel/cpfl/cpfl_ethdev.h | 10 ++++++++++
 2 files changed, 12 insertions(+), 1 deletion(-)
drivers/net/intel/cpfl/cpfl_ethdev.c +2 -1
index 4315adb68c..01e1b57cc8 100644
@@ -2839,7 +2839,8 @@ cpfl_dev_vport_init(struct rte_eth_dev *dev, void *init_params)
 		pci_dev = RTE_CLASS_TO_BUS_DEVICE(dev, *pci_dev);
 		vi.func_type = VCPF_CPCHNL2_FTYPE_LAN_VF;
 		vi.pf_id = CPFL_HOST0_CPF_ID;
-		vi.vf_id = pci_dev->addr.function;
+		vi.vf_id = VCPF_VF_ID_FROM_PCI(pci_dev->addr.devid,
+						pci_dev->addr.function);
 
 		v_id.vport_id = cpfl_vport->base.vport_info.info.vport_id;
 		v_id.vport_type = cpfl_vport->base.vport_info.info.vport_type;
drivers/net/intel/cpfl/cpfl_ethdev.h +10 -0
index d41aa93191..97ec128128 100644
@@ -103,6 +103,16 @@
 	((((type) & 0x3) << 14) + (((host_id) & 0x1) << 13) +	\
 	 (((pf_id) & 0x1) << 12) + ((vf_id) & 0xfff))
 
+/* Max VFs per PCI device (functions 0-7) */
+#define VCPF_VFS_PER_PCI_DEV	8
+
+/* Calculate VF ID from PCI device and function IDs.
+ * VFs span multiple PCI devices, e.g.:
+ *   device 0: VF 0-7, device 1: VF 8-15, etc.
+ */
+#define VCPF_VF_ID_FROM_PCI(device_id, function) \
+	(((device_id) * VCPF_VFS_PER_PCI_DEV) + (function))
+
 struct cpfl_vport_param {
 	struct cpfl_adapter_ext *adapter;
 	uint16_t devarg_id; /* arg id from user */
Signature · 1 line
2.34.1
#1 lore raw
Quoted 5 lines · Atul Patel

The VF ID was incorrectly set to only the PCI function number, which fails when VFs span multiple PCI devices (device IDs > 0). Calculate the VF ID as (device_id * 8) + function to correctly map VFs across devices.

Is this saying that the vf_id's need to be globally unique across the whole system, or is there some other subtlety that I'm missing here? Just trying to understand the context of this patch, thanks. Most other devices the vf id is local only to the relevant PF, i.e. each device has its own vf 0 etc. Is that not the case here?

/Bruce

Quoted 48 lines
Fixes f1ab44fb0ebf ("net/cpfl: add vCPF port info")
---
 drivers/net/intel/cpfl/cpfl_ethdev.c |  3 ++-
 drivers/net/intel/cpfl/cpfl_ethdev.h | 10 ++++++++++
 2 files changed, 12 insertions(+), 1 deletion(-)
drivers/net/intel/cpfl/cpfl_ethdev.c +2 -1
index 4315adb68c..01e1b57cc8 100644
@@ -2839,7 +2839,8 @@ cpfl_dev_vport_init(struct rte_eth_dev *dev, void *init_params)
 		pci_dev = RTE_CLASS_TO_BUS_DEVICE(dev, *pci_dev);
 		vi.func_type = VCPF_CPCHNL2_FTYPE_LAN_VF;
 		vi.pf_id = CPFL_HOST0_CPF_ID;
-		vi.vf_id = pci_dev->addr.function;
+		vi.vf_id = VCPF_VF_ID_FROM_PCI(pci_dev->addr.devid,
+						pci_dev->addr.function);
 
 		v_id.vport_id = cpfl_vport->base.vport_info.info.vport_id;
 		v_id.vport_type = cpfl_vport->base.vport_info.info.vport_type;
drivers/net/intel/cpfl/cpfl_ethdev.h +10 -0
index d41aa93191..97ec128128 100644
@@ -103,6 +103,16 @@
 	((((type) & 0x3) << 14) + (((host_id) & 0x1) << 13) +	\
 	 (((pf_id) & 0x1) << 12) + ((vf_id) & 0xfff))
 
+/* Max VFs per PCI device (functions 0-7) */
+#define VCPF_VFS_PER_PCI_DEV	8
+
+/* Calculate VF ID from PCI device and function IDs.
+ * VFs span multiple PCI devices, e.g.:
+ *   device 0: VF 0-7, device 1: VF 8-15, etc.
+ */
+#define VCPF_VF_ID_FROM_PCI(device_id, function) \
+	(((device_id) * VCPF_VFS_PER_PCI_DEV) + (function))
+
 struct cpfl_vport_param {
 	struct cpfl_adapter_ext *adapter;
 	uint16_t devarg_id; /* arg id from user */
Signature · 1 line
2.34.1
#2 lore raw

Hi Bruce,

Thanks for the review,
No, the vf_id is not meant to be globally unique across the system - it stays local to the PF, same as other devices. The pf_id here is fixed to a single CPF (CPFL_HOST0_CPF_ID), and the control plane expects the vf_id in struct cpchnl2_func_id to be relative to that PF (the header even documents it as "indexing is relative to PF specified above").

The subtlety is purely in how those VFs are presented on the host side in the vCPF model. The VFs belonging to that one PF are exposed to the host spread across multiple PCI devices, with 8 functions each. So the PCI function number alone isn't enough to recover the PF-relative vf_id - it wraps every 8 functions.

For example, with VFs enumerated on bus 0000:af:
PCI BDF device function -> vf_id

0000:af:00.0     0        0             0
0000:af:00.1     0        1             1
...
0000:af:00.7     0        7             7
0000:af:01.0     1        0             8
0000:af:01.1     1        1             9
...
0000:af:01.7     1        7            15
0000:af:02.0     2        0            16

The macro just reconstructs that PF-relative index from the PCI address:
vf_id = device * 8 + function

The previous code used pci_dev->addr.function directly, so it only worked for the first device (VF 0-7) and collided for every VF on a subsequent device - e.g. 0000:af:01.0 (VF 8) was incorrectly reported as VF 0.

Thanks,
Atul

-----Original Message-----
From: Richardson, Bruce <[email protected]>
Sent: Friday, September 4, 2026 4:06 PM
To: Patel, Atul <[email protected]>
Cc: Singh, Aman Deep <[email protected]>; [email protected]; Shetty, Praveen <[email protected]>; Shukla, Dhananjay <[email protected]>
Subject: Re: [PATCH] net/cpfl: fix VF ID calculation for vCPF

Quoted 5 lines · Atul Patel

The VF ID was incorrectly set to only the PCI function number, which fails when VFs span multiple PCI devices (device IDs > 0). Calculate the VF ID as (device_id * 8) + function to correctly map VFs across devices.

Is this saying that the vf_id's need to be globally unique across the whole system, or is there some other subtlety that I'm missing here? Just trying to understand the context of this patch, thanks. Most other devices the vf id is local only to the relevant PF, i.e. each device has its own vf 0 etc. Is that not the case here?

/Bruce

Quoted 50 lines
Fixes f1ab44fb0ebf ("net/cpfl: add vCPF port info")
---
 drivers/net/intel/cpfl/cpfl_ethdev.c |  3 ++-  
drivers/net/intel/cpfl/cpfl_ethdev.h | 10 ++++++++++
 2 files changed, 12 insertions(+), 1 deletion(-)
drivers/net/intel/cpfl/cpfl_ethdev.c +2 -1
index 4315adb68c..01e1b57cc8 100644
@@ -2839,7 +2839,8 @@ cpfl_dev_vport_init(struct rte_eth_dev *dev, void *init_params)
 		pci_dev = RTE_CLASS_TO_BUS_DEVICE(dev, *pci_dev);
 		vi.func_type = VCPF_CPCHNL2_FTYPE_LAN_VF;
 		vi.pf_id = CPFL_HOST0_CPF_ID;
-		vi.vf_id = pci_dev->addr.function;
+		vi.vf_id = VCPF_VF_ID_FROM_PCI(pci_dev->addr.devid,
+						pci_dev->addr.function);
 
 		v_id.vport_id = cpfl_vport->base.vport_info.info.vport_id;
 		v_id.vport_type = cpfl_vport->base.vport_info.info.vport_type;
drivers/net/intel/cpfl/cpfl_ethdev.h +10 -1
index d41aa93191..97ec128128 100644
@@ -103,6 +103,16 @@
 	((((type) & 0x3) << 14) + (((host_id) & 0x1) << 13) +	\
 	 (((pf_id) & 0x1) << 12) + ((vf_id) & 0xfff))
 
+/* Max VFs per PCI device (functions 0-7) */
+#define VCPF_VFS_PER_PCI_DEV	8
+
+/* Calculate VF ID from PCI device and function IDs.
+ * VFs span multiple PCI devices, e.g.:
+ *   device 0: VF 0-7, device 1: VF 8-15, etc.
+ */
+#define VCPF_VF_ID_FROM_PCI(device_id, function) \
+	(((device_id) * VCPF_VFS_PER_PCI_DEV) + (function))
+
 struct cpfl_vport_param {
 	struct cpfl_adapter_ext *adapter;
 	uint16_t devarg_id; /* arg id from user */
--

2.34.1

#3 lore raw
Quoted 19 lines · Atul

Hi Bruce,

Thanks for the review,
No, the vf_id is not meant to be globally unique across the system - it stays local to the PF, same as other devices. The pf_id here is fixed to a single CPF (CPFL_HOST0_CPF_ID), and the control plane expects the vf_id in struct cpchnl2_func_id to be relative to that PF (the header even documents it as "indexing is relative to PF specified above").

The subtlety is purely in how those VFs are presented on the host side in the vCPF model. The VFs belonging to that one PF are exposed to the host spread across multiple PCI devices, with 8 functions each. So the PCI function number alone isn't enough to recover the PF-relative vf_id - it wraps every 8 functions.

For example, with VFs enumerated on bus 0000:af:
PCI BDF device function -> vf_id

0000:af:00.0     0        0             0
0000:af:00.1     0        1             1
...
0000:af:00.7     0        7             7
0000:af:01.0     1        0             8
0000:af:01.1     1        1             9
...
0000:af:01.7     1        7            15
0000:af:02.0     2        0            16
Quoted 5 lines

The macro just reconstructs that PF-relative index from the PCI address:
vf_id = device * 8 + function

The previous code used pci_dev->addr.function directly, so it only worked for the first device (VF 0-7) and collided for every VF on a subsequent device - e.g. 0000:af:01.0 (VF 8) was incorrectly reported as VF 0.

Thanks, that is clear now.

/Bruce

Acked-by on v1 1/1
#4 lore raw
In reply to Atul Patel
Quoted 11 lines · Atul Patel

The VF ID was incorrectly set to only the PCI function number, which fails when VFs span multiple PCI devices (device IDs > 0). Calculate the VF ID as (device_id * 8) + function to correctly map VFs across devices.

Fixes f1ab44fb0ebf ("net/cpfl: add vCPF port info")

---

#5 lore raw
Quoted 6 lines · Bruce Richardson
Quoted 5 lines · Atul Patel

The VF ID was incorrectly set to only the PCI function number, which fails when VFs span multiple PCI devices (device IDs > 0). Calculate the VF ID as (device_id * 8) + function to correctly map VFs across devices.

Quoted 7 lines
Quoted 6 lines
Fixes f1ab44fb0ebf ("net/cpfl: add vCPF port info")

---

Applied to dpdk-next-net-intel.
Thanks,
/Bruce