From: Danilo Krummrich Date: Mon, 25 May 2026 22:58:30 +0000 (+0200) Subject: gpu: nova-core: unregister sysmem flush page from Drop X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d8143c9e988be01c9471f1cf0551208992d49918;p=thirdparty%2Fkernel%2Flinux.git 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 Closes: https://lore.kernel.org/all/20260409-fix-systemflush-v1-1-a1d6c968f17c@nvidia.com/ Fixes: 6554ad65b589 ("gpu: nova-core: register sysmem flush page") Reviewed-by: Eliot Courtney Reviewed-by: Alexandre Courbot Tested-by: Alexandre Courbot Link: https://patch.msgid.link/20260525225838.276108-3-dakr@kernel.org Signed-off-by: Danilo Krummrich --- diff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver.rs index d4cf4379ee87c..cff5034c2dcd2 100644 --- a/drivers/gpu/nova-core/driver.rs +++ b/drivers/gpu/nova-core/driver.rs @@ -113,8 +113,4 @@ impl pci::Driver for NovaCoreDriver { })) }) } - - fn unbind<'bound>(_pdev: &'bound pci::Device>, this: Pin<&Self::Data<'bound>>) { - this.gpu.unbind(); - } } diff --git a/drivers/gpu/nova-core/fb.rs b/drivers/gpu/nova-core/fb.rs index 6ee87050ce691..3b3271790cc97 100644 --- a/drivers/gpu/nova-core/fb.rs +++ b/drivers/gpu/nova-core/fb.rs @@ -43,21 +43,20 @@ mod hal; /// 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, + 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, - bar: &Bar0, + bar: &'sys Bar0, chipset: Chipset, ) -> Result { let page = CoherentHandle::alloc(dev, kernel::page::PAGE_SIZE, GFP_KERNEL)?; @@ -67,19 +66,18 @@ impl SysmemFlush { 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", diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs index 108dd094e354d..cf134cab49cd7 100644 --- a/drivers/gpu/nova-core/gpu.rs +++ b/drivers/gpu/nova-core/gpu.rs @@ -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, /// SEC2 falcon instance, used for GSP boot up and cleanup. @@ -293,11 +293,4 @@ impl<'gpu> Gpu<'gpu> { _: { 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); - } }