diff options
| author | Alexandre Courbot <acourbot@nvidia.com> | 2025-06-19 22:23:58 +0900 |
|---|---|---|
| committer | Danilo Krummrich <dakr@kernel.org> | 2025-06-23 19:55:53 +0200 |
| commit | 6554ad65b5891e52689061606e277a69e44462c4 (patch) | |
| tree | 19aec225982b4a045250e5d637736b98f0e60d52 /drivers/gpu/nova-core/fb.rs | |
| parent | 9bcc046a929f73358bf23678306b31d927a7e088 (diff) | |
| download | linux-next-6554ad65b5891e52689061606e277a69e44462c4.tar.gz linux-next-6554ad65b5891e52689061606e277a69e44462c4.zip | |
gpu: nova-core: register sysmem flush page
Reserve a page of system memory so sysmembar can perform a read on it if
a system write occurred since the last flush. Do this early as it can be
required to e.g. reset the GPU falcons.
Chipsets capabilities differ in that respect, so this commit also
introduces the FB HAL.
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
Link: https://lore.kernel.org/r/20250619-nova-frts-v6-14-ecf41ef99252@nvidia.com
[ * Use kernel::page::PAGE_SIZE instead of kernel::bindings::PAGE_SIZE.
* Get rid of the Option for SysmemFlush.
* Slightly reword SysmemFlush doc-comments.
- Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Diffstat (limited to 'drivers/gpu/nova-core/fb.rs')
| -rw-r--r-- | drivers/gpu/nova-core/fb.rs | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/drivers/gpu/nova-core/fb.rs b/drivers/gpu/nova-core/fb.rs new file mode 100644 index 000000000000..bfe3ed063572 --- /dev/null +++ b/drivers/gpu/nova-core/fb.rs @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0 + +use kernel::prelude::*; +use kernel::types::ARef; +use kernel::{dev_warn, device}; + +use crate::dma::DmaObject; +use crate::driver::Bar0; +use crate::gpu::Chipset; + +mod hal; + +/// Type holding the sysmem flush memory page, a page of memory to be written into the +/// `NV_PFB_NISO_FLUSH_SYSMEM_ADDR*` registers and used to maintain memory coherency. +/// +/// 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 { + /// Chipset we are operating on. + chipset: Chipset, + device: ARef<device::Device>, + /// Keep the page alive as long as we need it. + page: DmaObject, +} + +impl SysmemFlush { + /// Allocate a memory page and register it as the sysmem flush page. + pub(crate) fn register( + dev: &device::Device<device::Bound>, + bar: &Bar0, + chipset: Chipset, + ) -> Result<Self> { + let page = DmaObject::new(dev, kernel::page::PAGE_SIZE)?; + + hal::fb_hal(chipset).write_sysmem_flush_page(bar, page.dma_handle())?; + + Ok(Self { + chipset, + device: dev.into(), + 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) { + 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| { + dev_warn!( + &self.device, + "failed to unregister sysmem flush page: {:?}", + e + ) + }); + } else { + // Another page has been registered after us for some reason - warn as this is a bug. + dev_warn!( + &self.device, + "attempt to unregister a sysmem flush page that is not active\n" + ); + } + } +} |
