[PATCH 13/14] gpu: nova-core: publish typed SR-IOV PF data for VF drivers
From: Zhi Wang
Date: Tue Sep 15 2026 - 16:59:59 EST
Nova-core is the PF-side GPU driver, but it does not implement the PCI
callback for `sriov_numvfs`. Userspace therefore cannot enable or
disable VFs on GPUs bound to the driver, and no typed PF data is
available before a VF is created.
Embed a `VfRegistration` in the pinned `NovaCore` driver data and
publish unit data, `()`, as a typed readiness marker on SR-IOV PFs. The
registration remains inactive on conventional PCI functions and rejects
VFs, so nova-core can keep using the ordinary `pci::Driver` abstraction
with or without `CONFIG_PCI_IOV`.
Implement `sriov_configure()` using the verified PF view and pinned
driver data. Managed SR-IOV removes every VF before the inline
registration and the rest of `NovaCore` are dropped.
Signed-off-by: Zhi Wang <zhiw@xxxxxxxxxx>
---
drivers/gpu/nova-core/driver.rs | 33 ++++++++++++++++++++++++++++++---
1 file changed, 30 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver.rs
index a5b9a50cbaca..1373417386a2 100644
--- a/drivers/gpu/nova-core/driver.rs
+++ b/drivers/gpu/nova-core/driver.rs
@@ -35,6 +35,10 @@
#[pin_data]
pub(crate) struct NovaCore<'bound> {
+ #[cfg(CONFIG_PCI_IOV)]
+ #[allow(clippy::type_complexity)]
+ #[pin]
+ _vf_registration: pci::VfRegistration<'bound, CovariantForLt!(())>,
#[pin]
pub(crate) gpu: Gpu<'bound>,
bar: pci::Bar<'bound, BAR0_SIZE>,
@@ -107,10 +111,18 @@ fn probe<'bound>(
pin_init::pin_init_scope(move || {
dev_dbg!(pdev, "Probe Nova Core GPU driver.\n");
- pdev.enable_device_mem()?;
- pdev.set_master();
-
Ok(try_pin_init!(NovaCore {
+ #[cfg(CONFIG_PCI_IOV)]
+ // SAFETY:
+ // - probe has exclusive access before SR-IOV can be enabled;
+ // - the registration is pinned in driver data and is its first field;
+ // - no other registration is created for this device; and
+ // - the PCI adapter uses managed SR-IOV.
+ _vf_registration <- unsafe { pci::VfRegistration::new(pdev, Ok(())) },
+ _: {
+ pdev.enable_device_mem()?;
+ pdev.set_master();
+ },
bar: pdev.iomap_region_sized::<BAR0_SIZE>(0, c"nova-core/bar0")?,
bar1: {
let bar1_idx = bar1_resource_index(pdev)?;
@@ -149,4 +161,19 @@ fn probe<'bound>(
}))
})
}
+
+ #[cfg(CONFIG_PCI_IOV)]
+ fn sriov_configure<'bound>(
+ dev: &'bound pci::sriov::Device<Core<'_>>,
+ _this: Pin<&Self::Data<'bound>>,
+ nr_virtfn: i32,
+ ) -> Result<i32> {
+ if nr_virtfn == 0 {
+ dev.disable_sriov();
+ } else {
+ dev.enable_sriov(nr_virtfn)?;
+ }
+
+ Ok(nr_virtfn)
+ }
}