]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
gpu: nova-core: add Falcon HAL method load_method()
authorTimur Tabi <ttabi@nvidia.com>
Thu, 22 Jan 2026 22:28:44 +0000 (16:28 -0600)
committerAlexandre Courbot <acourbot@nvidia.com>
Sat, 24 Jan 2026 01:48:59 +0000 (10:48 +0900)
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>
drivers/gpu/nova-core/falcon.rs
drivers/gpu/nova-core/falcon/hal.rs
drivers/gpu/nova-core/falcon/hal/ga102.rs
drivers/gpu/nova-core/falcon/hal/tu102.rs
drivers/gpu/nova-core/firmware/fwsec.rs
drivers/gpu/nova-core/gsp/boot.rs

index e43563068e75bc235c4c9325a0178dbe9a2271a1..37bfee1d094926d9fe5d2a4cf778dfdc5bcbde76 100644 (file)
@@ -23,6 +23,7 @@ use kernel::{
 use crate::{
     dma::DmaObject,
     driver::Bar0,
+    falcon::hal::LoadMethod,
     gpu::Chipset,
     num::{
         FromSafeCast,
@@ -514,7 +515,7 @@ impl<E: FalconEngine + 'static> Falcon<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 @@ impl<E: FalconEngine + 'static> Falcon<E> {
         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()
index c886ba03d1f65d84cc49bc00462da1b431118830..89babd5f93257aea5f75305fefc8c5ed631798cc 100644 (file)
@@ -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<E: FalconEngine>: 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`.
index 39863813a2bf10715b0f48ddce94c620efe8dc79..8f62df10da0a5b02c3b7d665473672bcd1510105 100644 (file)
@@ -12,6 +12,7 @@ use kernel::{
 use crate::{
     driver::Bar0,
     falcon::{
+        hal::LoadMethod,
         Falcon,
         FalconBromParams,
         FalconEngine,
@@ -151,4 +152,8 @@ impl<E: FalconEngine> FalconHal<E> for Ga102<E> {
 
         Ok(())
     }
+
+    fn load_method(&self) -> LoadMethod {
+        LoadMethod::Dma
+    }
 }
index 23fbf61105725b031309328415c78c8334371f5a..7de6f24cc0a0b4d8d35b829cf08e315a77d1bde7 100644 (file)
@@ -11,6 +11,7 @@ use kernel::{
 use crate::{
     driver::Bar0,
     falcon::{
+        hal::LoadMethod,
         Falcon,
         FalconBromParams,
         FalconEngine, //
@@ -69,4 +70,8 @@ impl<E: FalconEngine> FalconHal<E> for Tu102<E> {
 
         Ok(())
     }
+
+    fn load_method(&self) -> LoadMethod {
+        LoadMethod::Pio
+    }
 }
index e4009faba6c5a79ca448edd1b3827dbe0c460fe8..6fc5a008bb472a6400aebbb2ab3db5cd7f1d8365 100644 (file)
@@ -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)
index 581b412554dca7b127cc20325c60553c403cdccd..be427fe26a5840f11c57b2b72b9cc1d3495bd1d2 100644 (file)
@@ -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,