mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 14:33:24 -04:00
gpu: nova-core: gsp: pass GspBootContext to unload methods
`GspBootContext` contains the resources required to boot the GSP. As it turns out, this is also the context required for unloading it. Reflect that fact by replacing the arguments of `Gsp::unload` and `UnloadBundle::run` with the `GspBootContext`. This symmetry between `Gsp::boot` and `Gsp::unload` will also be convenient when we want to make these methods generic over the boot context corresponding to the boot method used. Reviewed-by: Eliot Courtney <ecourtney@nvidia.com> Link: https://patch.msgid.link/20260709-nova-bootcontext-v6-4-520cbf8b9b50@nvidia.com Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
This commit is contained in:
@@ -269,7 +269,9 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
#[pin_data(PinnedDrop)]
|
||||
struct GspResources<'gpu> {
|
||||
/// Device owning the GPU.
|
||||
device: &'gpu device::Device<device::Bound>,
|
||||
device: &'gpu pci::Device<device::Bound>,
|
||||
/// Details about the chipset.
|
||||
spec: Spec,
|
||||
/// MMIO mapping of PCI BAR 0.
|
||||
bar: Bar0<'gpu>,
|
||||
/// GSP falcon instance, used for GSP boot up and cleanup.
|
||||
@@ -312,7 +314,16 @@ fn drop(self: Pin<&mut Self>) {
|
||||
.gsp
|
||||
.as_ref()
|
||||
.get_ref()
|
||||
.unload(device, bar, &*this.gsp_falcon, &*this.sec2_falcon, bundle)
|
||||
.unload(
|
||||
GspBootContext {
|
||||
pdev: device,
|
||||
bar,
|
||||
chipset: this.spec.chipset,
|
||||
gsp_falcon: &*this.gsp_falcon,
|
||||
sec2_falcon: &*this.sec2_falcon,
|
||||
},
|
||||
bundle,
|
||||
)
|
||||
.inspect_err(|e| dev_err!(device, "failed to unload GSP: {:?}\n", e));
|
||||
}
|
||||
}
|
||||
@@ -344,7 +355,9 @@ pub(crate) fn new(
|
||||
sysmem_flush: SysmemFlush::register(pdev.as_ref(), bar, spec.chipset)?,
|
||||
|
||||
gsp_resources <- try_pin_init!(GspResources {
|
||||
device: pdev.as_ref(),
|
||||
device: pdev,
|
||||
|
||||
spec: *spec,
|
||||
|
||||
bar,
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
use kernel::{
|
||||
bits,
|
||||
device,
|
||||
dma::Coherent,
|
||||
io::poll::read_poll_timeout,
|
||||
prelude::*,
|
||||
@@ -15,7 +14,6 @@
|
||||
driver::Bar0,
|
||||
falcon::{
|
||||
gsp::Gsp,
|
||||
sec2::Sec2,
|
||||
Falcon, //
|
||||
},
|
||||
fb::FbLayout,
|
||||
@@ -47,7 +45,6 @@ pub(crate) fn boot(
|
||||
let bar = ctx.bar;
|
||||
let chipset = ctx.chipset;
|
||||
let gsp_falcon = ctx.gsp_falcon;
|
||||
let sec2_falcon = ctx.sec2_falcon;
|
||||
let dev = pdev.as_ref();
|
||||
let hal = super::hal::gsp_hal(chipset);
|
||||
|
||||
@@ -61,9 +58,11 @@ pub(crate) fn boot(
|
||||
// Perform the chipset-specific boot sequence, and retrieve the unload bundle.
|
||||
let unload_bundle = hal.boot(&self, &ctx, &fb_layout, &wpr_meta)?;
|
||||
|
||||
let unload_guard = ScopeGuard::new_with_data(unload_bundle, |unload_bundle| {
|
||||
let _ = self.unload(dev, bar, gsp_falcon, sec2_falcon, unload_bundle);
|
||||
});
|
||||
let unload_guard =
|
||||
ScopeGuard::new_with_data((ctx, unload_bundle), |(ctx, unload_bundle)| {
|
||||
let _ = self.unload(ctx, unload_bundle);
|
||||
});
|
||||
let ctx = &unload_guard.0;
|
||||
|
||||
gsp_falcon.write_os_version(gsp_fw.bootloader.app_version);
|
||||
|
||||
@@ -82,12 +81,12 @@ pub(crate) fn boot(
|
||||
self.cmdq
|
||||
.send_command_no_wait(bar, commands::SetRegistry::new()?)?;
|
||||
|
||||
hal.post_boot(&self, &ctx, &gsp_fw)?;
|
||||
hal.post_boot(&self, ctx, &gsp_fw)?;
|
||||
|
||||
// Wait until GSP is fully initialized.
|
||||
commands::wait_gsp_init_done(&self.cmdq)?;
|
||||
|
||||
Ok(unload_guard.dismiss())
|
||||
Ok(unload_guard.dismiss().1)
|
||||
}
|
||||
|
||||
/// Shut down the GSP and wait until it is offline.
|
||||
@@ -116,17 +115,16 @@ fn shutdown_gsp(
|
||||
/// This stops all activity on the GSP.
|
||||
pub(crate) fn unload(
|
||||
&self,
|
||||
dev: &device::Device<device::Bound>,
|
||||
bar: Bar0<'_>,
|
||||
gsp_falcon: &Falcon<'_, Gsp>,
|
||||
sec2_falcon: &Falcon<'_, Sec2>,
|
||||
ctx: super::GspBootContext<'_>,
|
||||
unload_bundle: Option<super::UnloadBundle>,
|
||||
) -> Result {
|
||||
let dev = ctx.dev();
|
||||
|
||||
// Shut down the GSP. Keep going even in case of error.
|
||||
let mut res = Self::shutdown_gsp(
|
||||
&self.cmdq,
|
||||
bar,
|
||||
gsp_falcon,
|
||||
ctx.bar,
|
||||
ctx.gsp_falcon,
|
||||
commands::PowerStateLevel::Level0,
|
||||
)
|
||||
.inspect_err(|e| dev_err!(dev, "GSP shutdown failed: {:?}\n", e));
|
||||
@@ -136,7 +134,7 @@ pub(crate) fn unload(
|
||||
res = res.and(
|
||||
unload_bundle
|
||||
.0
|
||||
.run(dev, bar, gsp_falcon, sec2_falcon)
|
||||
.run(&ctx)
|
||||
.inspect_err(|e| dev_err!(dev, "Unload bundle failed: {:?}\n", e)),
|
||||
);
|
||||
} else {
|
||||
|
||||
@@ -5,18 +5,11 @@
|
||||
mod tu102;
|
||||
|
||||
use kernel::{
|
||||
device,
|
||||
dma::Coherent,
|
||||
prelude::*, //
|
||||
};
|
||||
|
||||
use crate::{
|
||||
driver::Bar0,
|
||||
falcon::{
|
||||
gsp::Gsp as GspEngine,
|
||||
sec2::Sec2,
|
||||
Falcon, //
|
||||
},
|
||||
fb::FbLayout,
|
||||
firmware::gsp::GspFirmware,
|
||||
gpu::{
|
||||
@@ -37,13 +30,7 @@
|
||||
/// required for unloading is prepared at load time, and stored here until it needs to be run.
|
||||
pub(super) trait UnloadBundle: Send {
|
||||
/// Performs the steps required to properly reset the GSP after it has been stopped.
|
||||
fn run(
|
||||
&self,
|
||||
dev: &device::Device<device::Bound>,
|
||||
bar: Bar0<'_>,
|
||||
gsp_falcon: &Falcon<'_, GspEngine>,
|
||||
sec2_falcon: &Falcon<'_, Sec2>,
|
||||
) -> Result;
|
||||
fn run(&self, ctx: &GspBootContext<'_>) -> Result;
|
||||
}
|
||||
|
||||
/// Trait implemented by GSP HALs.
|
||||
|
||||
@@ -12,10 +12,8 @@
|
||||
};
|
||||
|
||||
use crate::{
|
||||
driver::Bar0,
|
||||
falcon::{
|
||||
gsp::Gsp as GspEngine,
|
||||
sec2::Sec2,
|
||||
Falcon, //
|
||||
},
|
||||
fb::FbLayout,
|
||||
@@ -117,22 +115,16 @@ fn wait_for_gsp_lockdown_release(
|
||||
struct FspUnloadBundle;
|
||||
|
||||
impl UnloadBundle for FspUnloadBundle {
|
||||
fn run(
|
||||
&self,
|
||||
dev: &device::Device<device::Bound>,
|
||||
_bar: Bar0<'_>,
|
||||
gsp_falcon: &Falcon<'_, GspEngine>,
|
||||
_sec2_falcon: &Falcon<'_, Sec2>,
|
||||
) -> Result {
|
||||
fn run(&self, ctx: &GspBootContext<'_>) -> Result {
|
||||
// GSP falcon does most of the work of resetting, so just wait for it to finish.
|
||||
read_poll_timeout(
|
||||
|| Ok(gsp_falcon.is_riscv_active()),
|
||||
|| Ok(ctx.gsp_falcon.is_riscv_active()),
|
||||
|&active| !active,
|
||||
Delta::from_millis(10),
|
||||
Delta::from_secs(5),
|
||||
)
|
||||
.map(|_| ())
|
||||
.inspect_err(|_| dev_err!(dev, "GSP falcon failed to halt\n"))
|
||||
.inspect_err(|_| dev_err!(ctx.dev(), "GSP falcon failed to halt\n"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +146,6 @@ fn boot(
|
||||
let bar = ctx.bar;
|
||||
let chipset = ctx.chipset;
|
||||
let gsp_falcon = ctx.gsp_falcon;
|
||||
let sec2_falcon = ctx.sec2_falcon;
|
||||
|
||||
let unload_bundle = crate::gsp::UnloadBundle(
|
||||
KBox::new(FspUnloadBundle, GFP_KERNEL)? as KBox<dyn UnloadBundle>
|
||||
@@ -174,7 +165,7 @@ fn boot(
|
||||
// to make sure that boot args are kept alive until halt, in case they are still being
|
||||
// accessed.
|
||||
let unload_guard = ScopeGuard::new_with_data(unload_bundle, |unload_bundle| {
|
||||
let _ = unload_bundle.0.run(dev, bar, gsp_falcon, sec2_falcon);
|
||||
let _ = unload_bundle.0.run(ctx);
|
||||
});
|
||||
|
||||
fsp.boot_fmc(dev, fb_layout, &args)?;
|
||||
|
||||
@@ -121,18 +121,15 @@ fn build(
|
||||
}
|
||||
|
||||
impl UnloadBundle for Sec2UnloadBundle {
|
||||
fn run(
|
||||
&self,
|
||||
dev: &device::Device<device::Bound>,
|
||||
bar: Bar0<'_>,
|
||||
gsp_falcon: &Falcon<'_, GspEngine>,
|
||||
sec2_falcon: &Falcon<'_, Sec2>,
|
||||
) -> Result {
|
||||
fn run(&self, ctx: &GspBootContext<'_>) -> Result {
|
||||
let dev = ctx.dev();
|
||||
let bar = ctx.bar;
|
||||
|
||||
// Run FWSEC-SB to reset the GSP falcon to its pre-libos state.
|
||||
// Log errors but keep going if it fails.
|
||||
let fwsec_sb_res = self
|
||||
.fwsec_sb
|
||||
.run(dev, bar, gsp_falcon)
|
||||
.run(dev, bar, ctx.gsp_falcon)
|
||||
.inspect_err(|e| dev_err!(dev, "FWSEC-SB failed to run: {:?}\n", e));
|
||||
|
||||
// Remove WPR2 region if set.
|
||||
@@ -142,12 +139,14 @@ fn run(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
sec2_falcon.reset()?;
|
||||
sec2_falcon.load(&self.booter_unloader)?;
|
||||
ctx.sec2_falcon.reset()?;
|
||||
ctx.sec2_falcon.load(&self.booter_unloader)?;
|
||||
|
||||
// Sentinel value to confirm that Booter Unloader has run.
|
||||
const MAILBOX_SENTINEL: u32 = 0xff;
|
||||
let (mbox0, _) = sec2_falcon.boot(Some(MAILBOX_SENTINEL), Some(MAILBOX_SENTINEL))?;
|
||||
let (mbox0, _) = ctx
|
||||
.sec2_falcon
|
||||
.boot(Some(MAILBOX_SENTINEL), Some(MAILBOX_SENTINEL))?;
|
||||
if mbox0 != 0 {
|
||||
dev_err!(dev, "Booter Unloader returned error 0x{:x}\n", mbox0);
|
||||
return Err(EINVAL);
|
||||
@@ -293,7 +292,7 @@ fn boot(
|
||||
// Run the unload bundle to try and recover the GSP if an error occurs.
|
||||
let unload_guard = ScopeGuard::new_with_data(unload_bundle, |unload_bundle| {
|
||||
if let Some(unload_bundle) = unload_bundle {
|
||||
let _ = unload_bundle.0.run(dev, bar, gsp_falcon, sec2_falcon);
|
||||
let _ = unload_bundle.0.run(ctx);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user