gpu: nova-core: unregister sysmem flush page from Drop

Now that SysmemFlush can borrow the Bar via HRT lifetime, store a
&'bound Bar0 reference and implement Drop to automatically unregister
the sysmem flush page. This removes the need for manual unregister()
calls and the Gpu::unbind() method.

Reported-by: Eliot Courtney <ecourtney@nvidia.com>
Closes: https://lore.kernel.org/all/20260409-fix-systemflush-v1-1-a1d6c968f17c@nvidia.com/
Fixes: 6554ad65b5 ("gpu: nova-core: register sysmem flush page")
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-3-dakr@kernel.org
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
This commit is contained in:
Danilo Krummrich 2026-05-26 00:58:30 +02:00
parent 88b70f5a05
commit d8143c9e98
3 changed files with 11 additions and 24 deletions

View File

@ -113,8 +113,4 @@ fn probe<'bound>(
}))
})
}
fn unbind<'bound>(_pdev: &'bound pci::Device<Core<'_>>, this: Pin<&Self::Data<'bound>>) {
this.gpu.unbind();
}
}

View File

@ -43,21 +43,20 @@
/// Because of this, the sysmem flush memory page must be registered as early as possible during
/// driver initialization, and before any falcon is reset.
///
/// Users are responsible for manually calling [`Self::unregister`] before dropping this object,
/// otherwise the GPU might still use it even after it has been freed.
pub(crate) struct SysmemFlush {
pub(crate) struct SysmemFlush<'sys> {
/// Chipset we are operating on.
chipset: Chipset,
device: ARef<device::Device>,
bar: &'sys Bar0,
/// Keep the page alive as long as we need it.
page: CoherentHandle,
}
impl SysmemFlush {
impl<'sys> SysmemFlush<'sys> {
/// Allocate a memory page and register it as the sysmem flush page.
pub(crate) fn register(
dev: &device::Device<device::Bound>,
bar: &Bar0,
bar: &'sys Bar0,
chipset: Chipset,
) -> Result<Self> {
let page = CoherentHandle::alloc(dev, kernel::page::PAGE_SIZE, GFP_KERNEL)?;
@ -67,19 +66,18 @@ pub(crate) fn register(
Ok(Self {
chipset,
device: dev.into(),
bar,
page,
})
}
}
/// Unregister the managed sysmem flush page.
///
/// In order to gracefully tear down the GPU, users must make sure to call this method before
/// dropping the object.
pub(crate) fn unregister(&self, bar: &Bar0) {
impl Drop for SysmemFlush<'_> {
fn drop(&mut self) {
let hal = hal::fb_hal(self.chipset);
if hal.read_sysmem_flush_page(bar) == self.page.dma_handle() {
let _ = hal.write_sysmem_flush_page(bar, 0).inspect_err(|e| {
if hal.read_sysmem_flush_page(self.bar) == self.page.dma_handle() {
let _ = hal.write_sysmem_flush_page(self.bar, 0).inspect_err(|e| {
dev_warn!(
&self.device,
"failed to unregister sysmem flush page: {:?}\n",

View File

@ -250,7 +250,7 @@ pub(crate) struct Gpu<'gpu> {
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,
sysmem_flush: SysmemFlush<'gpu>,
/// GSP falcon instance, used for GSP boot up and cleanup.
gsp_falcon: Falcon<GspFalcon>,
/// SEC2 falcon instance, used for GSP boot up and cleanup.
@ -293,11 +293,4 @@ pub(crate) fn new(
_: { gsp.boot(pdev, bar, spec.chipset, gsp_falcon, sec2_falcon)? },
})
}
/// Called when the corresponding [`Device`](device::Device) is unbound.
///
/// Note: This method must only be called from `Driver::unbind`.
pub(crate) fn unbind(&self) {
self.sysmem_flush.unregister(self.bar);
}
}