diff options
| author | Alexandre Courbot <acourbot@nvidia.com> | 2025-06-19 22:24:07 +0900 |
|---|---|---|
| committer | Danilo Krummrich <dakr@kernel.org> | 2025-06-23 22:03:36 +0200 |
| commit | 859aa3d940585db3f3513964020c2a42614804dc (patch) | |
| tree | fafa1b4228537c2aa966d61543f1e50fcbabca62 /drivers/gpu/nova-core/gpu.rs | |
| parent | 31f0feefb49a219687a1233e68146db834417d75 (diff) | |
gpu: nova-core: load and run FWSEC-FRTS
With all the required pieces in place, load FWSEC-FRTS onto the GSP
falcon, run it, and check that it successfully carved out the WPR2
region out of framebuffer memory.
Reviewed-by: Lyude Paul <lyude@redhat.com>
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
Link: https://lore.kernel.org/r/20250619-nova-frts-v6-23-ecf41ef99252@nvidia.com
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Diffstat (limited to 'drivers/gpu/nova-core/gpu.rs')
| -rw-r--r-- | drivers/gpu/nova-core/gpu.rs | 90 |
1 files changed, 80 insertions, 10 deletions
diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs index c53e6135ca7d..43c8120559a7 100644 --- a/drivers/gpu/nova-core/gpu.rs +++ b/drivers/gpu/nova-core/gpu.rs @@ -184,6 +184,85 @@ impl PinnedDrop for Gpu { } impl Gpu { + /// Helper function to load and run the FWSEC-FRTS firmware and confirm that it has properly + /// created the WPR2 region. + /// + /// TODO: this needs to be moved into a larger type responsible for booting the whole GSP + /// (`GspBooter`?). + fn run_fwsec_frts( + dev: &device::Device<device::Bound>, + falcon: &Falcon<Gsp>, + bar: &Bar0, + bios: &Vbios, + fb_layout: &FbLayout, + ) -> Result<()> { + // Check that the WPR2 region does not already exists - if it does, we cannot run + // FWSEC-FRTS until the GPU is reset. + if regs::NV_PFB_PRI_MMU_WPR2_ADDR_HI::read(bar).higher_bound() != 0 { + dev_err!( + dev, + "WPR2 region already exists - GPU needs to be reset to proceed\n" + ); + return Err(EBUSY); + } + + let fwsec_frts = FwsecFirmware::new( + dev, + falcon, + bar, + bios, + FwsecCommand::Frts { + frts_addr: fb_layout.frts.start, + frts_size: fb_layout.frts.end - fb_layout.frts.start, + }, + )?; + + // Run FWSEC-FRTS to create the WPR2 region. + fwsec_frts.run(dev, falcon, bar)?; + + // SCRATCH_E contains the error code for FWSEC-FRTS. + let frts_status = regs::NV_PBUS_SW_SCRATCH_0E::read(bar).frts_err_code(); + if frts_status != 0 { + dev_err!( + dev, + "FWSEC-FRTS returned with error code {:#x}", + frts_status + ); + + return Err(EIO); + } + + // Check that the WPR2 region has been created as we requested. + let (wpr2_lo, wpr2_hi) = ( + regs::NV_PFB_PRI_MMU_WPR2_ADDR_LO::read(bar).lower_bound(), + regs::NV_PFB_PRI_MMU_WPR2_ADDR_HI::read(bar).higher_bound(), + ); + + match (wpr2_lo, wpr2_hi) { + (_, 0) => { + dev_err!(dev, "WPR2 region not created after running FWSEC-FRTS\n"); + + Err(EIO) + } + (wpr2_lo, _) if wpr2_lo != fb_layout.frts.start => { + dev_err!( + dev, + "WPR2 region created at unexpected address {:#x}; expected {:#x}\n", + wpr2_lo, + fb_layout.frts.start, + ); + + Err(EIO) + } + (wpr2_lo, wpr2_hi) => { + dev_dbg!(dev, "WPR2: {:#x}-{:#x}\n", wpr2_lo, wpr2_hi); + dev_dbg!(dev, "GPU instance built\n"); + + Ok(()) + } + } + } + pub(crate) fn new( pdev: &pci::Device<device::Bound>, devres_bar: Devres<Bar0>, @@ -222,16 +301,7 @@ impl Gpu { let bios = Vbios::new(pdev, bar)?; - let _fwsec_frts = FwsecFirmware::new( - pdev.as_ref(), - &gsp_falcon, - bar, - &bios, - FwsecCommand::Frts { - frts_addr: fb_layout.frts.start, - frts_size: fb_layout.frts.end - fb_layout.frts.start, - }, - )?; + Self::run_fwsec_frts(pdev.as_ref(), &gsp_falcon, bar, &bios, &fb_layout)?; Ok(pin_init!(Self { spec, |