From ab2aad252fe21347674cf969a5e9d44d69e403bb Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Thu, 22 Jan 2026 16:28:44 -0600 Subject: [PATCH] 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 Reviewed-by: Gary Guo Acked-by: Danilo Krummrich 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 --- drivers/gpu/nova-core/falcon.rs | 11 ++++++++++- drivers/gpu/nova-core/falcon/hal.rs | 12 ++++++++++++ drivers/gpu/nova-core/falcon/hal/ga102.rs | 5 +++++ drivers/gpu/nova-core/falcon/hal/tu102.rs | 5 +++++ drivers/gpu/nova-core/firmware/fwsec.rs | 2 +- drivers/gpu/nova-core/gsp/boot.rs | 2 +- 6 files changed, 34 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/nova-core/falcon.rs b/drivers/gpu/nova-core/falcon.rs index e43563068e75..37bfee1d0949 100644 --- a/drivers/gpu/nova-core/falcon.rs +++ b/drivers/gpu/nova-core/falcon.rs @@ -23,6 +23,7 @@ use kernel::{ use crate::{ dma::DmaObject, driver::Bar0, + falcon::hal::LoadMethod, gpu::Chipset, num::{ FromSafeCast, @@ -514,7 +515,7 @@ impl Falcon { } /// Perform a DMA load into `IMEM` and `DMEM` of `fw`, and prepare the falcon to run it. - pub(crate) fn dma_load>(&self, bar: &Bar0, fw: &F) -> Result { + fn dma_load>(&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 @@ impl Falcon { self.hal.is_riscv_active(bar) } + // Load a firmware image into Falcon memory + pub(crate) fn load>(&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() diff --git a/drivers/gpu/nova-core/falcon/hal.rs b/drivers/gpu/nova-core/falcon/hal.rs index c886ba03d1f6..89babd5f9325 100644 --- a/drivers/gpu/nova-core/falcon/hal.rs +++ b/drivers/gpu/nova-core/falcon/hal.rs @@ -15,6 +15,15 @@ use crate::{ 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 @@ pub(crate) trait FalconHal: Send + Sync { /// 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`. diff --git a/drivers/gpu/nova-core/falcon/hal/ga102.rs b/drivers/gpu/nova-core/falcon/hal/ga102.rs index 39863813a2bf..8f62df10da0a 100644 --- a/drivers/gpu/nova-core/falcon/hal/ga102.rs +++ b/drivers/gpu/nova-core/falcon/hal/ga102.rs @@ -12,6 +12,7 @@ use kernel::{ use crate::{ driver::Bar0, falcon::{ + hal::LoadMethod, Falcon, FalconBromParams, FalconEngine, @@ -151,4 +152,8 @@ impl FalconHal for Ga102 { Ok(()) } + + fn load_method(&self) -> LoadMethod { + LoadMethod::Dma + } } diff --git a/drivers/gpu/nova-core/falcon/hal/tu102.rs b/drivers/gpu/nova-core/falcon/hal/tu102.rs index 23fbf6110572..7de6f24cc0a0 100644 --- a/drivers/gpu/nova-core/falcon/hal/tu102.rs +++ b/drivers/gpu/nova-core/falcon/hal/tu102.rs @@ -11,6 +11,7 @@ use kernel::{ use crate::{ driver::Bar0, falcon::{ + hal::LoadMethod, Falcon, FalconBromParams, FalconEngine, // @@ -69,4 +70,8 @@ impl FalconHal for Tu102 { Ok(()) } + + fn load_method(&self) -> LoadMethod { + LoadMethod::Pio + } } diff --git a/drivers/gpu/nova-core/firmware/fwsec.rs b/drivers/gpu/nova-core/firmware/fwsec.rs index e4009faba6c5..6fc5a008bb47 100644 --- a/drivers/gpu/nova-core/firmware/fwsec.rs +++ b/drivers/gpu/nova-core/firmware/fwsec.rs @@ -428,7 +428,7 @@ impl FwsecFirmware { .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) diff --git a/drivers/gpu/nova-core/gsp/boot.rs b/drivers/gpu/nova-core/gsp/boot.rs index 581b412554dc..be427fe26a58 100644 --- a/drivers/gpu/nova-core/gsp/boot.rs +++ b/drivers/gpu/nova-core/gsp/boot.rs @@ -183,7 +183,7 @@ impl super::Gsp { ); 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, -- 2.47.3