gpu: nova-core: use lifetime for Bar

Take advantage of the lifetime-parameterized pci::Bar<'bound> to hold
the BAR mapping directly in NovaCore<'bound>, and pass a borrowed
reference to Gpu<'bound>.

This eliminates the Arc<Devres<Bar0>> indirection, removes runtime
revocation checks for BAR access, and simplifies Gpu::unbind().

Reviewed-by: Eliot Courtney <ecourtney@nvidia.com>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Tested-by: Alexandre Courbot <acourbot@nvidia.com>
Link: https://patch.msgid.link/20260525225838.276108-2-dakr@kernel.org
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
This commit is contained in:
Danilo Krummrich 2026-05-26 00:58:29 +02:00
parent a3e50e7279
commit 88b70f5a05
2 changed files with 28 additions and 37 deletions

View File

@ -13,12 +13,9 @@
},
prelude::*,
sizes::SZ_16M,
sync::{
atomic::{
Atomic,
Relaxed, //
},
Arc,
sync::atomic::{
Atomic,
Relaxed, //
},
types::ForLt,
};
@ -31,7 +28,8 @@
#[pin_data]
pub(crate) struct NovaCore<'bound> {
#[pin]
pub(crate) gpu: Gpu,
pub(crate) gpu: Gpu<'bound>,
bar: pci::Bar<'bound, BAR0_SIZE>,
#[allow(clippy::type_complexity)]
_reg: auxiliary::Registration<'bound, ForLt!(())>,
}
@ -48,7 +46,7 @@ pub(crate) struct NovaCore<'bound> {
// DMA addresses. These systems should be quite rare.
const GPU_DMA_BITS: u32 = 47;
pub(crate) type Bar0 = pci::Bar<'static, BAR0_SIZE>;
pub(crate) type Bar0 = kernel::io::Mmio<BAR0_SIZE>;
kernel::pci_device_table!(
PCI_TABLE,
@ -95,14 +93,14 @@ fn probe<'bound>(
// other threads of execution.
unsafe { pdev.dma_set_mask_and_coherent(DmaMask::new::<GPU_DMA_BITS>())? };
let bar = Arc::new(
pdev.iomap_region_sized::<BAR0_SIZE>(0, c"nova-core/bar0")?
.into_devres()?,
GFP_KERNEL,
)?;
Ok(try_pin_init!(NovaCore {
gpu <- Gpu::new(pdev, bar.clone(), bar.access(pdev.as_ref())?),
bar: pdev.iomap_region_sized::<BAR0_SIZE>(0, c"nova-core/bar0")?,
// TODO: Use `&bar` self-referential pin-init syntax once available.
//
// SAFETY: `bar` is initialized before this expression is evaluated
// (`try_pin_init!()` initializes fields in declaration order), lives at a pinned
// stable address, and is dropped after `gpu` (struct field drop order).
gpu <- Gpu::new(pdev, unsafe { &*core::ptr::from_ref(bar) }),
_reg: auxiliary::Registration::new(
pdev.as_ref(),
c"nova-drm",
@ -116,7 +114,7 @@ fn probe<'bound>(
})
}
fn unbind<'bound>(pdev: &'bound pci::Device<Core<'_>>, this: Pin<&Self::Data<'bound>>) {
this.gpu.unbind(pdev.as_ref());
fn unbind<'bound>(_pdev: &'bound pci::Device<Core<'_>>, this: Pin<&Self::Data<'bound>>) {
this.gpu.unbind();
}
}

View File

@ -2,13 +2,11 @@
use kernel::{
device,
devres::Devres,
fmt,
io::Io,
num::Bounded,
pci,
prelude::*,
sync::Arc, //
prelude::*, //
};
use crate::{
@ -246,10 +244,10 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
/// Structure holding the resources required to operate the GPU.
#[pin_data]
pub(crate) struct Gpu {
pub(crate) struct Gpu<'gpu> {
spec: Spec,
/// MMIO mapping of PCI BAR 0
bar: Arc<Devres<Bar0>>,
/// MMIO mapping of PCI BAR 0.
bar: &'gpu Bar0,
/// System memory page required for flushing all pending GPU-side memory writes done through
/// PCIE into system memory, via sysmembar (A GPU-initiated HW memory-barrier operation).
sysmem_flush: SysmemFlush,
@ -262,12 +260,11 @@ pub(crate) struct Gpu {
gsp: Gsp,
}
impl Gpu {
pub(crate) fn new<'a>(
pdev: &'a pci::Device<device::Bound>,
devres_bar: Arc<Devres<Bar0>>,
bar: &'a Bar0,
) -> impl PinInit<Self, Error> + 'a {
impl<'gpu> Gpu<'gpu> {
pub(crate) fn new(
pdev: &'gpu pci::Device<device::Bound>,
bar: &'gpu Bar0,
) -> impl PinInit<Self, Error> + 'gpu {
try_pin_init!(Self {
spec: Spec::new(pdev.as_ref(), bar).inspect(|spec| {
dev_info!(pdev,"NVIDIA ({})\n", spec);
@ -279,6 +276,8 @@ pub(crate) fn new<'a>(
.inspect_err(|_| dev_err!(pdev, "GFW boot did not complete\n"))?;
},
bar,
sysmem_flush: SysmemFlush::register(pdev.as_ref(), bar, spec.chipset)?,
gsp_falcon: Falcon::new(
@ -292,19 +291,13 @@ pub(crate) fn new<'a>(
gsp <- Gsp::new(pdev),
_: { gsp.boot(pdev, bar, spec.chipset, gsp_falcon, sec2_falcon)? },
bar: devres_bar,
})
}
/// Called when the corresponding [`Device`](device::Device) is unbound.
///
/// Note: This method must only be called from `Driver::unbind`.
pub(crate) fn unbind(&self, dev: &device::Device<device::Core<'_>>) {
kernel::warn_on!(self
.bar
.access(dev)
.inspect(|bar| self.sysmem_flush.unregister(bar))
.is_err());
pub(crate) fn unbind(&self) {
self.sysmem_flush.unregister(self.bar);
}
}