gpu: nova-core: add Falcon HAL method load_method()

Some GPUs do not support using DMA to transfer code/data from system
memory to Falcon memory, and instead must use programmed I/O (PIO).
Add a function to the Falcon HAL to indicate whether a given GPU's
Falcons support DMA for this purpose.

Signed-off-by: Timur Tabi <ttabi@nvidia.com>
Reviewed-by: Gary Guo <gary@garyguo.net>
Acked-by: Danilo Krummrich <dakr@kernel.org>
Link: https://patch.msgid.link/20260122222848.2555890-10-ttabi@nvidia.com
[acourbot@nvidia.com: add short code to call into the HAL.]
[acourbot@nvidia.com: make `dma_load` private as per feedback.]
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
This commit is contained in:
Timur Tabi 2026-01-22 16:28:44 -06:00 committed by Alexandre Courbot
parent a75718afc9
commit ab2aad252f
6 changed files with 34 additions and 3 deletions

View File

@ -23,6 +23,7 @@
use crate::{
dma::DmaObject,
driver::Bar0,
falcon::hal::LoadMethod,
gpu::Chipset,
num::{
FromSafeCast,
@ -514,7 +515,7 @@ fn dma_wr<F: FalconFirmware<Target = E>>(
}
/// Perform a DMA load into `IMEM` and `DMEM` of `fw`, and prepare the falcon to run it.
pub(crate) fn dma_load<F: FalconFirmware<Target = E>>(&self, bar: &Bar0, fw: &F) -> Result {
fn dma_load<F: FalconFirmware<Target = E>>(&self, bar: &Bar0, fw: &F) -> Result {
// The Non-Secure section only exists on firmware used by Turing and GA100, and
// those platforms do not use DMA.
if fw.imem_ns_load_params().is_some() {
@ -639,6 +640,14 @@ pub(crate) fn is_riscv_active(&self, bar: &Bar0) -> bool {
self.hal.is_riscv_active(bar)
}
// Load a firmware image into Falcon memory
pub(crate) fn load<F: FalconFirmware<Target = E>>(&self, bar: &Bar0, fw: &F) -> Result {
match self.hal.load_method() {
LoadMethod::Dma => self.dma_load(bar, fw),
LoadMethod::Pio => Err(ENOTSUPP),
}
}
/// Write the application version to the OS register.
pub(crate) fn write_os_version(&self, bar: &Bar0, app_version: u32) {
regs::NV_PFALCON_FALCON_OS::default()

View File

@ -15,6 +15,15 @@
mod ga102;
mod tu102;
/// Method used to load data into falcon memory. Some GPU architectures need
/// PIO and others can use DMA.
pub(crate) enum LoadMethod {
/// Programmed I/O
Pio,
/// Direct Memory Access
Dma,
}
/// Hardware Abstraction Layer for Falcon cores.
///
/// Implements chipset-specific low-level operations. The trait is generic against [`FalconEngine`]
@ -48,6 +57,9 @@ fn signature_reg_fuse_version(
/// Reset the falcon engine.
fn reset_eng(&self, bar: &Bar0) -> Result;
/// returns the method needed to load data into Falcon memory
fn load_method(&self) -> LoadMethod;
}
/// Returns a boxed falcon HAL adequate for `chipset`.

View File

@ -12,6 +12,7 @@
use crate::{
driver::Bar0,
falcon::{
hal::LoadMethod,
Falcon,
FalconBromParams,
FalconEngine,
@ -151,4 +152,8 @@ fn reset_eng(&self, bar: &Bar0) -> Result {
Ok(())
}
fn load_method(&self) -> LoadMethod {
LoadMethod::Dma
}
}

View File

@ -11,6 +11,7 @@
use crate::{
driver::Bar0,
falcon::{
hal::LoadMethod,
Falcon,
FalconBromParams,
FalconEngine, //
@ -69,4 +70,8 @@ fn reset_eng(&self, bar: &Bar0) -> Result {
Ok(())
}
fn load_method(&self) -> LoadMethod {
LoadMethod::Pio
}
}

View File

@ -428,7 +428,7 @@ pub(crate) fn run(
.reset(bar)
.inspect_err(|e| dev_err!(dev, "Failed to reset GSP falcon: {:?}\n", e))?;
falcon
.dma_load(bar, self)
.load(bar, self)
.inspect_err(|e| dev_err!(dev, "Failed to load FWSEC firmware: {:?}\n", e))?;
let (mbox0, _) = falcon
.boot(bar, Some(0), None)

View File

@ -183,7 +183,7 @@ pub(crate) fn boot(
);
sec2_falcon.reset(bar)?;
sec2_falcon.dma_load(bar, &booter_loader)?;
sec2_falcon.load(bar, &booter_loader)?;
let wpr_handle = wpr_meta.dma_handle();
let (mbox0, mbox1) = sec2_falcon.boot(
bar,