Currently, `FmcBootArgs` takes DMA handles directly, rather than references to the `Coherent` for them. This is error prone, so instead store lifetime'd references to the `Coherent` allocation.
Signed-off-by: Eliot Courtney <[email protected]> --- drivers/gpu/nova-core/fsp.rs | 32 ++++++++++++++++++++------------ drivers/gpu/nova-core/gsp.rs | 6 ++---- drivers/gpu/nova-core/gsp/hal/gh100.rs | 19 +++++++------------ 3 files changed, 29 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/nova-core/fsp.rs b/drivers/gpu/nova-core/fsp.rs index f0c595175c9c..5b782aa2e3fd 100644 --- a/drivers/gpu/nova-core/fsp.rs +++ b/drivers/gpu/nova-core/fsp.rs @@ -40,7 +40,11 @@ FIRMWARE_VERSION, // }, gpu::Chipset, - gsp::GspFmcBootParams, + gsp::{ + GspFmcBootParams, + GspFwWprMeta, + LibosMemoryRegionInitArgument, // + }, mctp::{ MctpHeader, NvdmHeader, @@ -134,7 +138,7 @@ impl FspCotMessage { fn new<'a>( fb_layout: &FbLayout, fsp_fw: &'a FspFirmware, - args: &'a FmcBootArgs, + args: &'a FmcBootArgs<'_>, ) -> Result<impl Init<Self> + 'a> { // frts_vidmem_offset is measured from the end of FB, so FRTS sits at // (end of FB) - frts_vidmem_offset. @@ -188,35 +192,39 @@ impl MessageToFsp for FspCotMessage { } /// Bundled arguments for FMC boot via FSP Chain of Trust. -pub(crate) struct FmcBootArgs { +pub(crate) struct FmcBootArgs<'a> { chipset: Chipset, fmc_boot_params: Coherent<GspFmcBootParams>, resume: bool, + // Additional dependencies required to be kept alive for FMC boot. + _wpr_meta: &'a Coherent<GspFwWprMeta>, + _libos: &'a Coherent<[LibosMemoryRegionInitArgument]>, } -impl FmcBootArgs { +impl<'a> FmcBootArgs<'a> { /// Builds FMC boot arguments, allocating the DMA-coherent boot parameter /// structure that FSP will read. pub(crate) fn new( dev: &device::Device<device::Bound>, chipset: Chipset, - wpr_meta_addr: u64, - libos_addr: u64, + wpr_meta: &'a Coherent<GspFwWprMeta>, + libos: &'a Coherent<[LibosMemoryRegionInitArgument]>, resume: bool, ) -> Result<Self> { - let init = GspFmcBootParams::new(wpr_meta_addr, libos_addr); + let init = GspFmcBootParams::new(wpr_meta.dma_handle(), libos.dma_handle()); Ok(Self { chipset, fmc_boot_params: Coherent::<GspFmcBootParams>::init(dev, GFP_KERNEL, init)?, resume, + _wpr_meta: wpr_meta, + _libos: libos, }) } - /// DMA address of the FMC boot parameters, needed after boot for lockdown - /// release polling. - pub(crate) fn boot_params_dma_handle(&self) -> u64 { - self.fmc_boot_params.dma_handle() + /// Returns the FMC boot parameters allocation. + pub(crate) fn boot_params(&self) -> &Coherent<GspFmcBootParams> { + &self.fmc_boot_params } } @@ -332,7 +340,7 @@ pub(crate) fn boot_fmc( &mut self, dev: &device::Device<device::Bound>, fb_layout: &FbLayout, - args: &FmcBootArgs, + args: &FmcBootArgs<'_>, ) -> Result { dev_dbg!(dev, "Starting FSP boot sequence for {}\n", args.chipset); diff --git a/drivers/gpu/nova-core/gsp.rs b/drivers/gpu/nova-core/gsp.rs index e89366b425fb..f0242126e202 100644 --- a/drivers/gpu/nova-core/gsp.rs +++ b/drivers/gpu/nova-core/gsp.rs @@ -28,6 +28,7 @@ pub(crate) use fw::{ GspFmcBootParams, GspFwWprMeta, + LibosMemoryRegionInitArgument, LibosParams, // }; @@ -45,10 +46,7 @@ }, gsp::{ cmdq::Cmdq, - fw::{ - GspArgumentsPadded, - LibosMemoryRegionInitArgument, // - }, + fw::GspArgumentsPadded, // }, num, }; diff --git a/drivers/gpu/nova-core/gsp/hal/gh100.rs b/drivers/gpu/nova-core/gsp/hal/gh100.rs index de786871c8ec..270703d0f5c6 100644 --- a/drivers/gpu/nova-core/gsp/hal/gh100.rs +++ b/drivers/gpu/nova-core/gsp/hal/gh100.rs @@ -24,6 +24,7 @@ }, Gsp, GspBootContext, + GspFmcBootParams, GspFwWprMeta, // }, }; @@ -55,13 +56,13 @@ fn combined_addr(&self) -> u64 { fn lockdown_released_or_error( &self, gsp_falcon: &Falcon<'_, GspEngine>, - fmc_boot_params_addr: u64, + fmc_boot_params: &Coherent<GspFmcBootParams>, ) -> bool { // GSP-FMC normally clears the boot parameters address from the mailboxes early during // boot. If the address is still there, keep polling rather than treating it as an error. // Any other non-zero mailbox0 value is a GSP-FMC error code. if self.mbox0 != 0 { - return self.combined_addr() != fmc_boot_params_addr; + return self.combined_addr() != fmc_boot_params.dma_handle(); } !gsp_falcon.riscv_branch_privilege_lockdown() @@ -72,7 +73,7 @@ fn lockdown_released_or_error( fn wait_for_gsp_lockdown_release( dev: &device::Device<device::Bound>, gsp_falcon: &Falcon<'_, GspEngine>, - fmc_boot_params_addr: u64, + fmc_boot_params: &Coherent<GspFmcBootParams>, ) -> Result { dev_dbg!(dev, "Waiting for GSP lockdown release\n"); @@ -87,7 +88,7 @@ fn wait_for_gsp_lockdown_release( }, |mbox| match mbox { None => false, - Some(mbox) => mbox.lockdown_released_or_error(gsp_falcon, fmc_boot_params_addr), + Some(mbox) => mbox.lockdown_released_or_error(gsp_falcon, fmc_boot_params), }, Delta::from_millis(10), Delta::from_secs(30), @@ -148,19 +149,13 @@ fn boot( let fsp = ctx.fsp.as_mut().ok_or(ENODEV)?; - let args = FmcBootArgs::new( - dev, - chipset, - wpr_meta.dma_handle(), - gsp.libos.dma_handle(), - false, - )?; + let args = FmcBootArgs::new(dev, chipset, wpr_meta, &gsp.libos, false)?; // Keep the result as we want to wait for lockdown release even in case of error, to make // sure `args` is not accessed by the GSP anymore. let res = fsp.boot_fmc(dev, fb_layout, &args); - wait_for_gsp_lockdown_release(dev, gsp_falcon, args.boot_params_dma_handle())?; + wait_for_gsp_lockdown_release(dev, gsp_falcon, args.boot_params())?; res.map(|()| Some(unload_bundle)) } -- 2.54.0
