[PATCH v2] gpu: nova-core: falcon: store bar and dev in falcon
From: Tim Kovalenko
Date: Thu Jun 25 2026 - 22:25:21 EST
Store the bound device and `BAR0` mapping in `Falcon` instead of passing
them through every `Falcon` operation. This simplifies the `Falcon` API and
removes repeated `dev`/`bar` plumbing from reset, load, boot, mailbox, DMA,
and GSP/FSP-specific Falcon helpers.
`FalconHal` now receives a reference to a `Falcon` and uses its methods and
members instead of passing them individually.
Suggested-by: Alexandre Courbot <acourbot@xxxxxxxxxx>
Link: https://rust-for-linux.zulipchat.com/#narrow/channel/509436-Nova/topic/Storing.20driver-bound.20references.20into.20sub-devices/near/599137882
Signed-off-by: Tim Kovalenko <tim.kovalenko@xxxxxxxxx>
---
Changes in v2:
- Removed the ad-hoc `set_fbif_transcfg_phys_sysmem` method in falcon, it can be re-implemented
in a better way in the future.
- Made `FalconHal` receive `Falcon` instead of `bar` and/or `falcon`
separately. This allows for simpler usage of the said hal.
- Link to v1: https://lore.kernel.org/r/20260624-drm-bar-refactor-v1-1-7062899163c5@xxxxxxxxx
---
drivers/gpu/nova-core/falcon.rs | 195 +++++++++------------
drivers/gpu/nova-core/falcon/fsp.rs | 44 ++---
drivers/gpu/nova-core/falcon/gsp.rs | 21 +--
drivers/gpu/nova-core/falcon/hal.rs | 14 +-
drivers/gpu/nova-core/falcon/hal/ga102.rs | 29 +--
drivers/gpu/nova-core/falcon/hal/tu102.rs | 24 +--
drivers/gpu/nova-core/firmware/booter.rs | 25 +--
drivers/gpu/nova-core/firmware/fwsec.rs | 19 +-
drivers/gpu/nova-core/firmware/fwsec/bootloader.rs | 15 +-
drivers/gpu/nova-core/fsp.rs | 23 ++-
drivers/gpu/nova-core/gpu.rs | 9 +-
drivers/gpu/nova-core/gsp.rs | 4 +-
drivers/gpu/nova-core/gsp/boot.rs | 22 +--
drivers/gpu/nova-core/gsp/hal.rs | 4 +-
drivers/gpu/nova-core/gsp/hal/gh100.rs | 32 ++--
drivers/gpu/nova-core/gsp/hal/tu102.rs | 68 +++----
drivers/gpu/nova-core/gsp/sequencer.rs | 31 ++--
17 files changed, 263 insertions(+), 316 deletions(-)
diff --git a/drivers/gpu/nova-core/falcon.rs b/drivers/gpu/nova-core/falcon.rs
index 94c7696a6493..78948cc8bff3 100644
--- a/drivers/gpu/nova-core/falcon.rs
+++ b/drivers/gpu/nova-core/falcon.rs
@@ -5,10 +5,7 @@
use hal::FalconHal;
use kernel::{
- device::{
- self,
- Device, //
- },
+ device,
dma::{
Coherent,
CoherentBox,
@@ -24,7 +21,6 @@
Io,
},
prelude::*,
- sync::aref::ARef,
time::Delta,
};
@@ -358,41 +354,47 @@ pub(crate) trait FalconFirmware {
}
/// Contains the base parameters common to all Falcon instances.
-pub(crate) struct Falcon<E: FalconEngine> {
+pub(crate) struct Falcon<'a, E: FalconEngine> {
hal: KBox<dyn FalconHal<E>>,
- dev: ARef<device::Device>,
+ dev: &'a device::Device<device::Bound>,
+ bar: Bar0<'a>,
}
-impl<E: FalconEngine + 'static> Falcon<E> {
+impl<'a, E: FalconEngine + 'static> Falcon<'a, E> {
/// Create a new falcon instance.
- pub(crate) fn new(dev: &device::Device, chipset: Chipset) -> Result<Self> {
+ pub(crate) fn new(
+ dev: &'a device::Device<device::Bound>,
+ chipset: Chipset,
+ bar: Bar0<'a>,
+ ) -> Result<Self> {
Ok(Self {
hal: hal::falcon_hal(chipset)?,
- dev: dev.into(),
+ dev,
+ bar,
})
}
/// Resets DMA-related registers.
- pub(crate) fn dma_reset(&self, bar: Bar0<'_>) {
- bar.update(regs::NV_PFALCON_FBIF_CTL::of::<E>(), |v| {
+ pub(crate) fn dma_reset(&self) {
+ self.bar.update(regs::NV_PFALCON_FBIF_CTL::of::<E>(), |v| {
v.with_allow_phys_no_ctx(true)
});
- bar.write(
+ self.bar.write(
WithBase::of::<E>(),
regs::NV_PFALCON_FALCON_DMACTL::zeroed(),
);
}
/// Reset the controller, select the falcon core, and wait for memory scrubbing to complete.
- pub(crate) fn reset(&self, bar: Bar0<'_>) -> Result {
- self.hal.reset_eng(bar)?;
- self.hal.select_core(self, bar)?;
- self.hal.reset_wait_mem_scrubbing(bar)?;
+ pub(crate) fn reset(&self) -> Result {
+ self.hal.reset_eng(self)?;
+ self.hal.select_core(self)?;
+ self.hal.reset_wait_mem_scrubbing(self)?;
- bar.write(
+ self.bar.write(
WithBase::of::<E>(),
- regs::NV_PFALCON_FALCON_RM::from(bar.read(regs::NV_PMC_BOOT_0).into_raw()),
+ regs::NV_PFALCON_FALCON_RM::from(self.bar.read(regs::NV_PMC_BOOT_0).into_raw()),
);
Ok(())
@@ -404,18 +406,14 @@ pub(crate) fn reset(&self, bar: Bar0<'_>) -> Result {
/// Write a slice to Falcon IMEM memory using programmed I/O (PIO).
///
/// Returns `EINVAL` if `img.len()` is not a multiple of 4.
- fn pio_wr_imem_slice(
- &self,
- bar: Bar0<'_>,
- load_offsets: FalconPioImemLoadTarget<'_>,
- ) -> Result {
+ fn pio_wr_imem_slice(&self, load_offsets: FalconPioImemLoadTarget<'_>) -> Result {
// Rejecting misaligned images here allows us to avoid checking
// inside the loops.
if load_offsets.data.len() % 4 != 0 {
return Err(EINVAL);
}
- bar.write(
+ self.bar.write(
WithBase::of::<E>().at(Self::PIO_PORT),
regs::NV_PFALCON_FALCON_IMEMC::zeroed()
.with_secure(load_offsets.secure)
@@ -426,13 +424,13 @@ fn pio_wr_imem_slice(
for (n, block) in load_offsets.data.chunks(MEM_BLOCK_ALIGNMENT).enumerate() {
let n = u16::try_from(n)?;
let tag: u16 = load_offsets.start_tag.checked_add(n).ok_or(ERANGE)?;
- bar.write(
+ self.bar.write(
WithBase::of::<E>().at(Self::PIO_PORT),
regs::NV_PFALCON_FALCON_IMEMT::zeroed().with_tag(tag),
);
for word in block.chunks_exact(4) {
let w = [word[0], word[1], word[2], word[3]];
- bar.write(
+ self.bar.write(
WithBase::of::<E>().at(Self::PIO_PORT),
regs::NV_PFALCON_FALCON_IMEMD::zeroed().with_data(u32::from_le_bytes(w)),
);
@@ -445,18 +443,14 @@ fn pio_wr_imem_slice(
/// Write a slice to Falcon DMEM memory using programmed I/O (PIO).
///
/// Returns `EINVAL` if `img.len()` is not a multiple of 4.
- fn pio_wr_dmem_slice(
- &self,
- bar: Bar0<'_>,
- load_offsets: FalconPioDmemLoadTarget<'_>,
- ) -> Result {
+ fn pio_wr_dmem_slice(&self, load_offsets: FalconPioDmemLoadTarget<'_>) -> Result {
// Rejecting misaligned images here allows us to avoid checking
// inside the loops.
if load_offsets.data.len() % 4 != 0 {
return Err(EINVAL);
}
- bar.write(
+ self.bar.write(
WithBase::of::<E>().at(Self::PIO_PORT),
regs::NV_PFALCON_FALCON_DMEMC::zeroed()
.with_aincw(true)
@@ -465,7 +459,7 @@ fn pio_wr_dmem_slice(
for word in load_offsets.data.chunks_exact(4) {
let w = [word[0], word[1], word[2], word[3]];
- bar.write(
+ self.bar.write(
WithBase::of::<E>().at(Self::PIO_PORT),
regs::NV_PFALCON_FALCON_DMEMD::zeroed().with_data(u32::from_le_bytes(w)),
);
@@ -477,29 +471,28 @@ fn pio_wr_dmem_slice(
/// Perform a PIO copy into `IMEM` and `DMEM` of `fw`, and prepare the falcon to run it.
pub(crate) fn pio_load<F: FalconFirmware<Target = E> + FalconPioLoadable>(
&self,
- bar: Bar0<'_>,
fw: &F,
) -> Result {
- bar.update(regs::NV_PFALCON_FBIF_CTL::of::<E>(), |v| {
+ self.bar.update(regs::NV_PFALCON_FBIF_CTL::of::<E>(), |v| {
v.with_allow_phys_no_ctx(true)
});
- bar.write(
+ self.bar.write(
WithBase::of::<E>(),
regs::NV_PFALCON_FALCON_DMACTL::zeroed(),
);
if let Some(imem_ns) = fw.imem_ns_load_params() {
- self.pio_wr_imem_slice(bar, imem_ns)?;
+ self.pio_wr_imem_slice(imem_ns)?;
}
if let Some(imem_sec) = fw.imem_sec_load_params() {
- self.pio_wr_imem_slice(bar, imem_sec)?;
+ self.pio_wr_imem_slice(imem_sec)?;
}
- self.pio_wr_dmem_slice(bar, fw.dmem_load_params())?;
+ self.pio_wr_dmem_slice(fw.dmem_load_params())?;
- self.hal.program_brom(self, bar, &fw.brom_params());
+ self.hal.program_brom(self, &fw.brom_params());
- bar.write(
+ self.bar.write(
WithBase::of::<E>(),
regs::NV_PFALCON_FALCON_BOOTVEC::zeroed().with_value(fw.boot_addr()),
);
@@ -513,7 +506,6 @@ pub(crate) fn pio_load<F: FalconFirmware<Target = E> + FalconPioLoadable>(
/// `sec` is set if the loaded firmware is expected to run in secure mode.
fn dma_wr(
&self,
- bar: Bar0<'_>,
dma_obj: &Coherent<[u8]>,
target_mem: FalconMem,
load_offsets: FalconDmaLoadTarget,
@@ -571,7 +563,7 @@ fn dma_wr(
// Set up the base source DMA address.
- bar.write(
+ self.bar.write(
WithBase::of::<E>(),
regs::NV_PFALCON_FALCON_DMATRFBASE::zeroed().with_base(
// CAST: `as u32` is used on purpose since we do want to strip the upper bits,
@@ -579,7 +571,7 @@ fn dma_wr(
(dma_start >> 8) as u32,
),
);
- bar.write(
+ self.bar.write(
WithBase::of::<E>(),
regs::NV_PFALCON_FALCON_DMATRFBASE1::zeroed().try_with_base(dma_start >> 40)?,
);
@@ -590,23 +582,23 @@ fn dma_wr(
for pos in (0..num_transfers).map(|i| i * DMA_LEN) {
// Perform a transfer of size `DMA_LEN`.
- bar.write(
+ self.bar.write(
WithBase::of::<E>(),
regs::NV_PFALCON_FALCON_DMATRFMOFFS::zeroed()
.try_with_offs(load_offsets.dst_start + pos)?,
);
- bar.write(
+ self.bar.write(
WithBase::of::<E>(),
regs::NV_PFALCON_FALCON_DMATRFFBOFFS::zeroed().with_offs(src_start + pos),
);
- bar.write(WithBase::of::<E>(), cmd);
+ self.bar.write(WithBase::of::<E>(), cmd);
// Wait for the transfer to complete.
// TIMEOUT: arbitrarily large value, no DMA transfer to the falcon's small memories
// should ever take that long.
read_poll_timeout(
- || Ok(bar.read(regs::NV_PFALCON_FALCON_DMATRFCMD::of::<E>())),
+ || Ok(self.bar.read(regs::NV_PFALCON_FALCON_DMATRFCMD::of::<E>())),
|r| r.idle(),
Delta::ZERO,
Delta::from_secs(2),
@@ -617,12 +609,7 @@ fn dma_wr(
}
/// Perform a DMA load into `IMEM` and `DMEM` of `fw`, and prepare the falcon to run it.
- fn dma_load<F: FalconFirmware<Target = E> + FalconDmaLoadable>(
- &self,
- dev: &Device<device::Bound>,
- bar: Bar0<'_>,
- fw: &F,
- ) -> Result {
+ fn dma_load<F: FalconFirmware<Target = E> + FalconDmaLoadable>(&self, fw: &F) -> Result {
// DMA object with firmware content as the source of the DMA engine.
let dma_obj = {
let fw_slice = fw.as_slice();
@@ -630,7 +617,7 @@ fn dma_load<F: FalconFirmware<Target = E> + FalconDmaLoadable>(
// DMA copies are done in chunks of `MEM_BLOCK_ALIGNMENT`, so pad the length
// accordingly and fill with `0`.
let mut dma_obj = CoherentBox::zeroed_slice(
- dev,
+ self.dev,
fw_slice.len().next_multiple_of(MEM_BLOCK_ALIGNMENT),
GFP_KERNEL,
)?;
@@ -642,24 +629,20 @@ fn dma_load<F: FalconFirmware<Target = E> + FalconDmaLoadable>(
dma_obj.into()
};
- self.dma_reset(bar);
- bar.update(regs::NV_PFALCON_FBIF_TRANSCFG::of::<E>().at(0), |v| {
- v.with_target(FalconFbifTarget::CoherentSysmem)
- .with_mem_type(FalconFbifMemType::Physical)
- });
+ self.dma_reset();
+ self.bar
+ .update(regs::NV_PFALCON_FBIF_TRANSCFG::of::<E>().at(0), |v| {
+ v.with_target(FalconFbifTarget::CoherentSysmem)
+ .with_mem_type(FalconFbifMemType::Physical)
+ });
- self.dma_wr(
- bar,
- &dma_obj,
- FalconMem::ImemSecure,
- fw.imem_sec_load_params(),
- )?;
- self.dma_wr(bar, &dma_obj, FalconMem::Dmem, fw.dmem_load_params())?;
+ self.dma_wr(&dma_obj, FalconMem::ImemSecure, fw.imem_sec_load_params())?;
+ self.dma_wr(&dma_obj, FalconMem::Dmem, fw.dmem_load_params())?;
- self.hal.program_brom(self, bar, &fw.brom_params());
+ self.hal.program_brom(self, &fw.brom_params());
// Set `BootVec` to start of non-secure code.
- bar.write(
+ self.bar.write(
WithBase::of::<E>(),
regs::NV_PFALCON_FALCON_BOOTVEC::zeroed().with_value(fw.boot_addr()),
);
@@ -668,10 +651,10 @@ fn dma_load<F: FalconFirmware<Target = E> + FalconDmaLoadable>(
}
/// Wait until the falcon CPU is halted.
- pub(crate) fn wait_till_halted(&self, bar: Bar0<'_>) -> Result<()> {
+ pub(crate) fn wait_till_halted(&self) -> Result<()> {
// TIMEOUT: arbitrarily large value, firmwares should complete in less than 2 seconds.
read_poll_timeout(
- || Ok(bar.read(regs::NV_PFALCON_FALCON_CPUCTL::of::<E>())),
+ || Ok(self.bar.read(regs::NV_PFALCON_FALCON_CPUCTL::of::<E>())),
|r| r.halted(),
Delta::ZERO,
Delta::from_secs(2),
@@ -681,16 +664,17 @@ pub(crate) fn wait_till_halted(&self, bar: Bar0<'_>) -> Result<()> {
}
/// Start the falcon CPU.
- pub(crate) fn start(&self, bar: Bar0<'_>) -> Result<()> {
- match bar
+ pub(crate) fn start(&self) -> Result<()> {
+ match self
+ .bar
.read(regs::NV_PFALCON_FALCON_CPUCTL::of::<E>())
.alias_en()
{
- true => bar.write(
+ true => self.bar.write(
WithBase::of::<E>(),
regs::NV_PFALCON_FALCON_CPUCTL_ALIAS::zeroed().with_startcpu(true),
),
- false => bar.write(
+ false => self.bar.write(
WithBase::of::<E>(),
regs::NV_PFALCON_FALCON_CPUCTL::zeroed().with_startcpu(true),
),
@@ -700,16 +684,16 @@ pub(crate) fn start(&self, bar: Bar0<'_>) -> Result<()> {
}
/// Writes values to the mailbox registers if provided.
- pub(crate) fn write_mailboxes(&self, bar: Bar0<'_>, mbox0: Option<u32>, mbox1: Option<u32>) {
+ pub(crate) fn write_mailboxes(&self, mbox0: Option<u32>, mbox1: Option<u32>) {
if let Some(mbox0) = mbox0 {
- bar.write(
+ self.bar.write(
WithBase::of::<E>(),
regs::NV_PFALCON_FALCON_MAILBOX0::zeroed().with_value(mbox0),
);
}
if let Some(mbox1) = mbox1 {
- bar.write(
+ self.bar.write(
WithBase::of::<E>(),
regs::NV_PFALCON_FALCON_MAILBOX1::zeroed().with_value(mbox1),
);
@@ -717,21 +701,23 @@ pub(crate) fn write_mailboxes(&self, bar: Bar0<'_>, mbox0: Option<u32>, mbox1: O
}
/// Reads the value from `mbox0` register.
- pub(crate) fn read_mailbox0(&self, bar: Bar0<'_>) -> u32 {
- bar.read(regs::NV_PFALCON_FALCON_MAILBOX0::of::<E>())
+ pub(crate) fn read_mailbox0(&self) -> u32 {
+ self.bar
+ .read(regs::NV_PFALCON_FALCON_MAILBOX0::of::<E>())
.value()
}
/// Reads the value from `mbox1` register.
- pub(crate) fn read_mailbox1(&self, bar: Bar0<'_>) -> u32 {
- bar.read(regs::NV_PFALCON_FALCON_MAILBOX1::of::<E>())
+ pub(crate) fn read_mailbox1(&self) -> u32 {
+ self.bar
+ .read(regs::NV_PFALCON_FALCON_MAILBOX1::of::<E>())
.value()
}
/// Reads values from both mailbox registers.
- pub(crate) fn read_mailboxes(&self, bar: Bar0<'_>) -> (u32, u32) {
- let mbox0 = self.read_mailbox0(bar);
- let mbox1 = self.read_mailbox1(bar);
+ pub(crate) fn read_mailboxes(&self) -> (u32, u32) {
+ let mbox0 = self.read_mailbox0();
+ let mbox1 = self.read_mailbox1();
(mbox0, mbox1)
}
@@ -743,54 +729,43 @@ pub(crate) fn read_mailboxes(&self, bar: Bar0<'_>) -> (u32, u32) {
///
/// Wait up to two seconds for the firmware to complete, and return its exit status read from
/// the `MBOX0` and `MBOX1` registers.
- pub(crate) fn boot(
- &self,
- bar: Bar0<'_>,
- mbox0: Option<u32>,
- mbox1: Option<u32>,
- ) -> Result<(u32, u32)> {
- self.write_mailboxes(bar, mbox0, mbox1);
- self.start(bar)?;
- self.wait_till_halted(bar)?;
- Ok(self.read_mailboxes(bar))
+ pub(crate) fn boot(&self, mbox0: Option<u32>, mbox1: Option<u32>) -> Result<(u32, u32)> {
+ self.write_mailboxes(mbox0, mbox1);
+ self.start()?;
+ self.wait_till_halted()?;
+ Ok(self.read_mailboxes())
}
/// Returns the fused version of the signature to use in order to run a HS firmware on this
/// falcon instance. `engine_id_mask` and `ucode_id` are obtained from the firmware header.
pub(crate) fn signature_reg_fuse_version(
&self,
- bar: Bar0<'_>,
engine_id_mask: u16,
ucode_id: u8,
) -> Result<u32> {
self.hal
- .signature_reg_fuse_version(self, bar, engine_id_mask, ucode_id)
+ .signature_reg_fuse_version(self, engine_id_mask, ucode_id)
}
/// Check if the RISC-V core is active.
///
/// Returns `true` if the RISC-V core is active, `false` otherwise.
- pub(crate) fn is_riscv_active(&self, bar: Bar0<'_>) -> bool {
- self.hal.is_riscv_active(bar)
+ pub(crate) fn is_riscv_active(&self) -> bool {
+ self.hal.is_riscv_active(self)
}
/// Load a firmware image into Falcon memory, using the preferred method for the current
/// chipset.
- pub(crate) fn load<F: FalconFirmware<Target = E> + FalconDmaLoadable>(
- &self,
- dev: &Device<device::Bound>,
- bar: Bar0<'_>,
- fw: &F,
- ) -> Result {
+ pub(crate) fn load<F: FalconFirmware<Target = E> + FalconDmaLoadable>(&self, fw: &F) -> Result {
match self.hal.load_method() {
- LoadMethod::Dma => self.dma_load(dev, bar, fw),
- LoadMethod::Pio => self.pio_load(bar, &fw.try_as_pio_loadable()?),
+ LoadMethod::Dma => self.dma_load(fw),
+ LoadMethod::Pio => self.pio_load(&fw.try_as_pio_loadable()?),
}
}
/// Write the application version to the OS register.
- pub(crate) fn write_os_version(&self, bar: Bar0<'_>, app_version: u32) {
- bar.write(
+ pub(crate) fn write_os_version(&self, app_version: u32) {
+ self.bar.write(
WithBase::of::<E>(),
regs::NV_PFALCON_FALCON_OS::zeroed().with_value(app_version),
);
diff --git a/drivers/gpu/nova-core/falcon/fsp.rs b/drivers/gpu/nova-core/falcon/fsp.rs
index 52cdb84ef0e8..53b1079843ae 100644
--- a/drivers/gpu/nova-core/falcon/fsp.rs
+++ b/drivers/gpu/nova-core/falcon/fsp.rs
@@ -21,7 +21,6 @@
};
use crate::{
- driver::Bar0,
falcon::{
Falcon,
FalconEngine,
@@ -48,18 +47,18 @@ impl RegisterBase<PFalcon2Base> for Fsp {
impl FalconEngine for Fsp {}
-impl Falcon<Fsp> {
+impl<'a> Falcon<'a, Fsp> {
/// Writes `data` to FSP external memory at offset `0`.
///
/// `data` is interpreted as little-endian 32-bit words. Returns `EINVAL`
/// if the `data` length is not 4-byte aligned.
- fn write_emem(&mut self, bar: Bar0<'_>, data: &[u8]) -> Result {
+ fn write_emem(&mut self, data: &[u8]) -> Result {
if data.len() % 4 != 0 {
return Err(EINVAL);
}
// Begin a write burst at offset `0`, auto-incrementing on each write.
- bar.write(
+ self.bar.write(
WithBase::of::<Fsp>(),
regs::NV_PFALCON_FALCON_EMEMC::zeroed().with_aincw(true),
);
@@ -68,7 +67,7 @@ fn write_emem(&mut self, bar: Bar0<'_>, data: &[u8]) -> Result {
let value = u32::from_le_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]);
// Write the next 32-bit `value`; hardware advances the offset.
- bar.write(
+ self.bar.write(
WithBase::of::<Fsp>(),
regs::NV_PFALCON_FALCON_EMEMD::zeroed().with_data(value),
);
@@ -81,20 +80,23 @@ fn write_emem(&mut self, bar: Bar0<'_>, data: &[u8]) -> Result {
///
/// `data` is stored as little-endian 32-bit words. Returns `EINVAL` if
/// the `data` length is not 4-byte aligned.
- fn read_emem(&mut self, bar: Bar0<'_>, data: &mut [u8]) -> Result {
+ fn read_emem(&mut self, data: &mut [u8]) -> Result {
if data.len() % 4 != 0 {
return Err(EINVAL);
}
// Begin a read burst at offset `0`, auto-incrementing on each read.
- bar.write(
+ self.bar.write(
WithBase::of::<Fsp>(),
regs::NV_PFALCON_FALCON_EMEMC::zeroed().with_aincr(true),
);
for chunk in data.chunks_exact_mut(4) {
// Read the next 32-bit word; hardware advances the offset.
- let value = bar.read(regs::NV_PFALCON_FALCON_EMEMD::of::<Fsp>()).data();
+ let value = self
+ .bar
+ .read(regs::NV_PFALCON_FALCON_EMEMD::of::<Fsp>())
+ .data();
chunk.copy_from_slice(&value.to_le_bytes());
}
@@ -107,9 +109,9 @@ fn read_emem(&mut self, bar: Bar0<'_>, data: &mut [u8]) -> Result {
///
/// The FSP message queue is not circular. Pointers are reset to 0 after each
/// message exchange, so `tail >= head` is always true when data is present.
- fn poll_msgq(&self, bar: Bar0<'_>) -> u32 {
- let head = bar.read(regs::NV_PFSP_MSGQ_HEAD::at(0)).val();
- let tail = bar.read(regs::NV_PFSP_MSGQ_TAIL::at(0)).val();
+ fn poll_msgq(&self) -> u32 {
+ let head = self.bar.read(regs::NV_PFSP_MSGQ_HEAD::at(0)).val();
+ let tail = self.bar.read(regs::NV_PFSP_MSGQ_TAIL::at(0)).val();
if head == tail {
return 0;
@@ -122,20 +124,20 @@ fn poll_msgq(&self, bar: Bar0<'_>) -> u32 {
/// Writes `packet` to FSP EMEM and updates the queue pointers to notify FSP.
///
/// Returns `EINVAL` if `packet` is empty or its length is not 4-byte aligned.
- pub(crate) fn send_msg(&mut self, bar: Bar0<'_>, packet: &[u8]) -> Result {
+ pub(crate) fn send_msg(&mut self, packet: &[u8]) -> Result {
if packet.is_empty() {
return Err(EINVAL);
}
- self.write_emem(bar, packet)?;
+ self.write_emem(packet)?;
// Update queue pointers. TAIL points at the last DWORD written.
let tail_offset = u32::try_from(packet.len() - 4).map_err(|_| EINVAL)?;
- bar.write(
+ self.bar.write(
Array::at(0),
regs::NV_PFSP_QUEUE_TAIL::zeroed().with_address(tail_offset),
);
- bar.write(
+ self.bar.write(
Array::at(0),
regs::NV_PFSP_QUEUE_HEAD::zeroed().with_address(0),
);
@@ -148,9 +150,9 @@ pub(crate) fn send_msg(&mut self, bar: Bar0<'_>, packet: &[u8]) -> Result {
///
/// Returns `ETIMEDOUT` if no message was available until timeout, or a regular error code if a
/// memory allocation error occurred.
- pub(crate) fn recv_msg(&mut self, bar: Bar0<'_>) -> Result<KVec<u8>> {
+ pub(crate) fn recv_msg(&mut self) -> Result<KVec<u8>> {
let msg_size = read_poll_timeout(
- || Ok(self.poll_msgq(bar)),
+ || Ok(self.poll_msgq()),
|&size| size > 0,
Delta::from_millis(10),
Delta::from_millis(FSP_MSG_TIMEOUT_MS),
@@ -160,11 +162,13 @@ pub(crate) fn recv_msg(&mut self, bar: Bar0<'_>) -> Result<KVec<u8>> {
let mut buffer = KVec::<u8>::new();
buffer.resize(msg_size, 0, GFP_KERNEL)?;
- self.read_emem(bar, &mut buffer)?;
+ self.read_emem(&mut buffer)?;
// Reset message queue pointers after reading.
- bar.write(Array::at(0), regs::NV_PFSP_MSGQ_TAIL::zeroed().with_val(0));
- bar.write(Array::at(0), regs::NV_PFSP_MSGQ_HEAD::zeroed().with_val(0));
+ self.bar
+ .write(Array::at(0), regs::NV_PFSP_MSGQ_TAIL::zeroed().with_val(0));
+ self.bar
+ .write(Array::at(0), regs::NV_PFSP_MSGQ_HEAD::zeroed().with_val(0));
Ok(buffer)
}
diff --git a/drivers/gpu/nova-core/falcon/gsp.rs b/drivers/gpu/nova-core/falcon/gsp.rs
index f788b87bd951..ae32f401aeb0 100644
--- a/drivers/gpu/nova-core/falcon/gsp.rs
+++ b/drivers/gpu/nova-core/falcon/gsp.rs
@@ -14,7 +14,6 @@
};
use crate::{
- driver::Bar0,
falcon::{
Falcon,
FalconEngine,
@@ -37,20 +36,20 @@ impl RegisterBase<PFalcon2Base> for Gsp {
impl FalconEngine for Gsp {}
-impl Falcon<Gsp> {
+impl<'a> Falcon<'a, Gsp> {
/// Clears the SWGEN0 bit in the Falcon's IRQ status clear register to
/// allow GSP to signal CPU for processing new messages in message queue.
- pub(crate) fn clear_swgen0_intr(&self, bar: Bar0<'_>) {
- bar.write(
+ pub(crate) fn clear_swgen0_intr(&self) {
+ self.bar.write(
WithBase::of::<Gsp>(),
regs::NV_PFALCON_FALCON_IRQSCLR::zeroed().with_swgen0(true),
);
}
/// Checks if GSP reload/resume has completed during the boot process.
- pub(crate) fn check_reload_completed(&self, bar: Bar0<'_>, timeout: Delta) -> Result<bool> {
+ pub(crate) fn check_reload_completed(&self, timeout: Delta) -> Result<bool> {
read_poll_timeout(
- || Ok(bar.read(regs::NV_PGC6_BSI_SECURE_SCRATCH_14)),
+ || Ok(self.bar.read(regs::NV_PGC6_BSI_SECURE_SCRATCH_14)),
|val| val.boot_stage_3_handoff(),
Delta::ZERO,
timeout,
@@ -59,19 +58,21 @@ pub(crate) fn check_reload_completed(&self, bar: Bar0<'_>, timeout: Delta) -> Re
}
/// Returns whether the RISC-V branch privilege lockdown bit is set.
- pub(crate) fn riscv_branch_privilege_lockdown(&self, bar: Bar0<'_>) -> bool {
- bar.read(regs::NV_PFALCON_FALCON_HWCFG2::of::<Gsp>())
+ pub(crate) fn riscv_branch_privilege_lockdown(&self) -> bool {
+ self.bar
+ .read(regs::NV_PFALCON_FALCON_HWCFG2::of::<Gsp>())
.riscv_br_priv_lockdown()
}
/// Returns whether GSP registers can be read by the CPU.
- pub(crate) fn priv_target_mask_released(&self, bar: Bar0<'_>) -> bool {
+ pub(crate) fn priv_target_mask_released(&self) -> bool {
/// Pattern returned by GSP register reads while the PRIV target mask still blocks CPU
/// access. The low byte varies; the upper 24 bits are fixed.
const LOCKED_PATTERN: u32 = 0xbadf_4100;
const LOCKED_MASK: u32 = 0xffff_ff00;
- let hwcfg2 = bar
+ let hwcfg2 = self
+ .bar
.read(regs::NV_PFALCON_FALCON_HWCFG2::of::<Gsp>())
.into_raw();
diff --git a/drivers/gpu/nova-core/falcon/hal.rs b/drivers/gpu/nova-core/falcon/hal.rs
index 89b56823906b..ee4a017f3a4c 100644
--- a/drivers/gpu/nova-core/falcon/hal.rs
+++ b/drivers/gpu/nova-core/falcon/hal.rs
@@ -3,7 +3,6 @@
use kernel::prelude::*;
use crate::{
- driver::Bar0,
falcon::{
Falcon,
FalconBromParams,
@@ -34,7 +33,7 @@ pub(crate) enum LoadMethod {
/// registers.
pub(crate) trait FalconHal<E: FalconEngine>: Send + Sync {
/// Activates the Falcon core if the engine is a risvc/falcon dual engine.
- fn select_core(&self, _falcon: &Falcon<E>, _bar: Bar0<'_>) -> Result {
+ fn select_core(&self, _falcon: &Falcon<'_, E>) -> Result {
Ok(())
}
@@ -42,24 +41,23 @@ fn select_core(&self, _falcon: &Falcon<E>, _bar: Bar0<'_>) -> Result {
/// falcon instance. `engine_id_mask` and `ucode_id` are obtained from the firmware header.
fn signature_reg_fuse_version(
&self,
- falcon: &Falcon<E>,
- bar: Bar0<'_>,
+ falcon: &Falcon<'_, E>,
engine_id_mask: u16,
ucode_id: u8,
) -> Result<u32>;
/// Program the boot ROM registers prior to starting a secure firmware.
- fn program_brom(&self, falcon: &Falcon<E>, bar: Bar0<'_>, params: &FalconBromParams);
+ fn program_brom(&self, falcon: &Falcon<'_, E>, params: &FalconBromParams);
/// Check if the RISC-V core is active.
/// Returns `true` if the RISC-V core is active, `false` otherwise.
- fn is_riscv_active(&self, bar: Bar0<'_>) -> bool;
+ fn is_riscv_active(&self, falcon: &Falcon<'_, E>) -> bool;
/// Wait for memory scrubbing to complete.
- fn reset_wait_mem_scrubbing(&self, bar: Bar0<'_>) -> Result;
+ fn reset_wait_mem_scrubbing(&self, falcon: &Falcon<'_, E>) -> Result;
/// Reset the falcon engine.
- fn reset_eng(&self, bar: Bar0<'_>) -> Result;
+ fn reset_eng(&self, falcon: &Falcon<'_, E>) -> Result;
/// Returns the method used to load data into the falcon's memory.
///
diff --git a/drivers/gpu/nova-core/falcon/hal/ga102.rs b/drivers/gpu/nova-core/falcon/hal/ga102.rs
index cf6ce47e6b25..fe821ded5fa1 100644
--- a/drivers/gpu/nova-core/falcon/hal/ga102.rs
+++ b/drivers/gpu/nova-core/falcon/hal/ga102.rs
@@ -115,33 +115,34 @@ pub(super) fn new() -> Self {
}
impl<E: FalconEngine> FalconHal<E> for Ga102<E> {
- fn select_core(&self, _falcon: &Falcon<E>, bar: Bar0<'_>) -> Result {
- select_core_ga102::<E>(bar)
+ fn select_core(&self, falcon: &Falcon<'_, E>) -> Result {
+ select_core_ga102::<E>(falcon.bar)
}
fn signature_reg_fuse_version(
&self,
- falcon: &Falcon<E>,
- bar: Bar0<'_>,
+ falcon: &Falcon<'_, E>,
engine_id_mask: u16,
ucode_id: u8,
) -> Result<u32> {
- signature_reg_fuse_version_ga102(&falcon.dev, bar, engine_id_mask, ucode_id)
+ signature_reg_fuse_version_ga102(falcon.dev, falcon.bar, engine_id_mask, ucode_id)
}
- fn program_brom(&self, _falcon: &Falcon<E>, bar: Bar0<'_>, params: &FalconBromParams) {
- program_brom_ga102::<E>(bar, params);
+ fn program_brom(&self, falcon: &Falcon<'_, E>, params: &FalconBromParams) {
+ program_brom_ga102::<E>(falcon.bar, params);
}
- fn is_riscv_active(&self, bar: Bar0<'_>) -> bool {
- bar.read(regs::NV_PRISCV_RISCV_CPUCTL::of::<E>())
+ fn is_riscv_active(&self, falcon: &Falcon<'_, E>) -> bool {
+ falcon
+ .bar
+ .read(regs::NV_PRISCV_RISCV_CPUCTL::of::<E>())
.active_stat()
}
- fn reset_wait_mem_scrubbing(&self, bar: Bar0<'_>) -> Result {
+ fn reset_wait_mem_scrubbing(&self, falcon: &Falcon<'_, E>) -> Result {
// TIMEOUT: memory scrubbing should complete in less than 20ms.
read_poll_timeout(
- || Ok(bar.read(regs::NV_PFALCON_FALCON_HWCFG2::of::<E>())),
+ || Ok(falcon.bar.read(regs::NV_PFALCON_FALCON_HWCFG2::of::<E>())),
|r| r.mem_scrubbing_done(),
Delta::ZERO,
Delta::from_millis(20),
@@ -149,7 +150,9 @@ fn reset_wait_mem_scrubbing(&self, bar: Bar0<'_>) -> Result {
.map(|_| ())
}
- fn reset_eng(&self, bar: Bar0<'_>) -> Result {
+ fn reset_eng(&self, falcon: &Falcon<'_, E>) -> Result {
+ let bar = falcon.bar;
+
let _ = bar.read(regs::NV_PFALCON_FALCON_HWCFG2::of::<E>());
// According to OpenRM's `kflcnPreResetWait_GA102` documentation, HW sometimes does not set
@@ -162,7 +165,7 @@ fn reset_eng(&self, bar: Bar0<'_>) -> Result {
);
regs::NV_PFALCON_FALCON_ENGINE::reset_engine::<E>(bar);
- self.reset_wait_mem_scrubbing(bar)?;
+ self.reset_wait_mem_scrubbing(falcon)?;
Ok(())
}
diff --git a/drivers/gpu/nova-core/falcon/hal/tu102.rs b/drivers/gpu/nova-core/falcon/hal/tu102.rs
index 3aaee3869312..34bf9f3f44c7 100644
--- a/drivers/gpu/nova-core/falcon/hal/tu102.rs
+++ b/drivers/gpu/nova-core/falcon/hal/tu102.rs
@@ -13,7 +13,6 @@
};
use crate::{
- driver::Bar0,
falcon::{
hal::LoadMethod,
Falcon,
@@ -34,31 +33,32 @@ pub(super) fn new() -> Self {
}
impl<E: FalconEngine> FalconHal<E> for Tu102<E> {
- fn select_core(&self, _falcon: &Falcon<E>, _bar: Bar0<'_>) -> Result {
+ fn select_core(&self, _falcon: &Falcon<'_, E>) -> Result {
Ok(())
}
fn signature_reg_fuse_version(
&self,
- _falcon: &Falcon<E>,
- _bar: Bar0<'_>,
+ _falcon: &Falcon<'_, E>,
_engine_id_mask: u16,
_ucode_id: u8,
) -> Result<u32> {
Ok(0)
}
- fn program_brom(&self, _falcon: &Falcon<E>, _bar: Bar0<'_>, _params: &FalconBromParams) {}
+ fn program_brom(&self, _falcon: &Falcon<'_, E>, _params: &FalconBromParams) {}
- fn is_riscv_active(&self, bar: Bar0<'_>) -> bool {
- bar.read(regs::NV_PRISCV_RISCV_CORE_SWITCH_RISCV_STATUS::of::<E>())
+ fn is_riscv_active(&self, falcon: &Falcon<'_, E>) -> bool {
+ falcon
+ .bar
+ .read(regs::NV_PRISCV_RISCV_CORE_SWITCH_RISCV_STATUS::of::<E>())
.active_stat()
}
- fn reset_wait_mem_scrubbing(&self, bar: Bar0<'_>) -> Result {
+ fn reset_wait_mem_scrubbing(&self, falcon: &Falcon<'_, E>) -> Result {
// TIMEOUT: memory scrubbing should complete in less than 10ms.
read_poll_timeout(
- || Ok(bar.read(regs::NV_PFALCON_FALCON_DMACTL::of::<E>())),
+ || Ok(falcon.bar.read(regs::NV_PFALCON_FALCON_DMACTL::of::<E>())),
|r| r.mem_scrubbing_done(),
Delta::ZERO,
Delta::from_millis(10),
@@ -66,9 +66,9 @@ fn reset_wait_mem_scrubbing(&self, bar: Bar0<'_>) -> Result {
.map(|_| ())
}
- fn reset_eng(&self, bar: Bar0<'_>) -> Result {
- regs::NV_PFALCON_FALCON_ENGINE::reset_engine::<E>(bar);
- self.reset_wait_mem_scrubbing(bar)?;
+ fn reset_eng(&self, falcon: &Falcon<'_, E>) -> Result {
+ regs::NV_PFALCON_FALCON_ENGINE::reset_engine::<E>(falcon.bar);
+ self.reset_wait_mem_scrubbing(falcon)?;
Ok(())
}
diff --git a/drivers/gpu/nova-core/firmware/booter.rs b/drivers/gpu/nova-core/firmware/booter.rs
index d9313ac361af..acb7f4d8a532 100644
--- a/drivers/gpu/nova-core/firmware/booter.rs
+++ b/drivers/gpu/nova-core/firmware/booter.rs
@@ -15,7 +15,6 @@
};
use crate::{
- driver::Bar0,
falcon::{
sec2::Sec2,
Falcon,
@@ -293,8 +292,7 @@ pub(crate) fn new(
kind: BooterKind,
chipset: Chipset,
ver: &str,
- falcon: &Falcon<<Self as FalconFirmware>::Target>,
- bar: Bar0<'_>,
+ falcon: &Falcon<'_, <Self as FalconFirmware>::Target>,
) -> Result<Self> {
let fw_name = match kind {
BooterKind::Loader => "booter_load",
@@ -339,11 +337,8 @@ pub(crate) fn new(
} else {
// Obtain the version from the fuse register, and extract the corresponding
// signature.
- let reg_fuse_version = falcon.signature_reg_fuse_version(
- bar,
- brom_params.engine_id_mask,
- brom_params.ucode_id,
- )?;
+ let reg_fuse_version = falcon
+ .signature_reg_fuse_version(brom_params.engine_id_mask, brom_params.ucode_id)?;
// `0` means the last signature should be used.
const FUSE_VERSION_USE_LAST_SIG: u32 = 0;
@@ -405,18 +400,14 @@ pub(crate) fn new(
pub(crate) fn run<T>(
&self,
dev: &device::Device<device::Bound>,
- bar: Bar0<'_>,
- sec2_falcon: &Falcon<Sec2>,
+ sec2_falcon: &Falcon<'_, Sec2>,
wpr_meta: &Coherent<T>,
) -> Result {
- sec2_falcon.reset(bar)?;
- sec2_falcon.load(dev, bar, self)?;
+ sec2_falcon.reset()?;
+ sec2_falcon.load(self)?;
let wpr_handle = wpr_meta.dma_handle();
- let (mbox0, mbox1) = sec2_falcon.boot(
- bar,
- Some(wpr_handle as u32),
- Some((wpr_handle >> 32) as u32),
- )?;
+ let (mbox0, mbox1) =
+ sec2_falcon.boot(Some(wpr_handle as u32), Some((wpr_handle >> 32) as u32))?;
dev_dbg!(dev, "SEC2 MBOX0: {:#x}, MBOX1: {:#x}\n", mbox0, mbox1);
if mbox0 != 0 {
diff --git a/drivers/gpu/nova-core/firmware/fwsec.rs b/drivers/gpu/nova-core/firmware/fwsec.rs
index 199ae2adb664..95e0dd77746b 100644
--- a/drivers/gpu/nova-core/firmware/fwsec.rs
+++ b/drivers/gpu/nova-core/firmware/fwsec.rs
@@ -27,7 +27,6 @@
};
use crate::{
- driver::Bar0,
falcon::{
gsp::Gsp,
Falcon,
@@ -320,8 +319,7 @@ impl FwsecFirmware {
/// command.
pub(crate) fn new(
dev: &Device<device::Bound>,
- falcon: &Falcon<Gsp>,
- bar: Bar0<'_>,
+ falcon: &Falcon<'_, Gsp>,
bios: &Vbios,
cmd: FwsecCommand,
) -> Result<Self> {
@@ -337,7 +335,7 @@ pub(crate) fn new(
.ok_or(EINVAL)?;
let desc_sig_versions = u32::from(desc.signature_versions());
let reg_fuse_version =
- falcon.signature_reg_fuse_version(bar, desc.engine_id_mask(), desc.ucode_id())?;
+ falcon.signature_reg_fuse_version(desc.engine_id_mask(), desc.ucode_id())?;
dev_dbg!(
dev,
"desc_sig_versions: {:#x}, reg_fuse_version: {}\n",
@@ -390,21 +388,16 @@ pub(crate) fn new(
/// This must only be called on chipsets that do not need the FWSEC bootloader (i.e., where
/// [`Chipset::needs_fwsec_bootloader()`](crate::gpu::Chipset::needs_fwsec_bootloader) returns
/// `false`). On chipsets that do, use [`bootloader::FwsecFirmwareWithBl`] instead.
- pub(crate) fn run(
- &self,
- dev: &Device<device::Bound>,
- falcon: &Falcon<Gsp>,
- bar: Bar0<'_>,
- ) -> Result<()> {
+ pub(crate) fn run(&self, dev: &Device<device::Bound>, falcon: &Falcon<'_, Gsp>) -> Result<()> {
// Reset falcon, load the firmware, and run it.
falcon
- .reset(bar)
+ .reset()
.inspect_err(|e| dev_err!(dev, "Failed to reset GSP falcon: {:?}\n", e))?;
falcon
- .load(dev, bar, self)
+ .load(self)
.inspect_err(|e| dev_err!(dev, "Failed to load FWSEC firmware: {:?}\n", e))?;
let (mbox0, _) = falcon
- .boot(bar, Some(0), None)
+ .boot(Some(0), None)
.inspect_err(|e| dev_err!(dev, "Failed to boot FWSEC firmware: {:?}\n", e))?;
if mbox0 != 0 {
dev_err!(dev, "FWSEC firmware returned error {}\n", mbox0);
diff --git a/drivers/gpu/nova-core/firmware/fwsec/bootloader.rs b/drivers/gpu/nova-core/firmware/fwsec/bootloader.rs
index ac1558a83b83..d9fafd2eea5b 100644
--- a/drivers/gpu/nova-core/firmware/fwsec/bootloader.rs
+++ b/drivers/gpu/nova-core/firmware/fwsec/bootloader.rs
@@ -12,10 +12,7 @@
Device, //
},
dma::Coherent,
- io::{
- register::WithBase, //
- Io,
- },
+ io::{register::WithBase, Io},
prelude::*,
ptr::{
Alignable,
@@ -50,7 +47,7 @@
FIRMWARE_VERSION, //
},
gpu::Chipset,
- num::FromSafeCast,
+ num::FromSafeCast, //
regs,
};
@@ -278,15 +275,15 @@ pub(crate) fn new(
pub(crate) fn run(
&self,
dev: &Device<device::Bound>,
- falcon: &Falcon<Gsp>,
+ falcon: &Falcon<'_, Gsp>,
bar: Bar0<'_>,
) -> Result<()> {
// Reset falcon, load the firmware, and run it.
falcon
- .reset(bar)
+ .reset()
.inspect_err(|e| dev_err!(dev, "Failed to reset GSP falcon: {:?}\n", e))?;
falcon
- .pio_load(bar, self)
+ .pio_load(self)
.inspect_err(|e| dev_err!(dev, "Failed to load FWSEC firmware: {:?}\n", e))?;
// Configure DMA index for the bootloader to fetch the FWSEC firmware from system memory.
@@ -301,7 +298,7 @@ pub(crate) fn run(
);
let (mbox0, _) = falcon
- .boot(bar, Some(0), None)
+ .boot(Some(0), None)
.inspect_err(|e| dev_err!(dev, "Failed to boot FWSEC firmware: {:?}\n", e))?;
if mbox0 != 0 {
dev_err!(dev, "FWSEC firmware returned error {}\n", mbox0);
diff --git a/drivers/gpu/nova-core/fsp.rs b/drivers/gpu/nova-core/fsp.rs
index 4b97d1fb505e..574e1627e63c 100644
--- a/drivers/gpu/nova-core/fsp.rs
+++ b/drivers/gpu/nova-core/fsp.rs
@@ -224,27 +224,27 @@ pub(crate) fn boot_params_dma_handle(&self) -> u64 {
/// An `Fsp` is produced by [`Fsp::wait_secure_boot`], which only returns once FSP secure boot
/// has completed. It owns the FSP falcon and the FMC firmware, which are used for the subsequent
/// Chain of Trust boot.
-pub(crate) struct Fsp {
- falcon: Falcon<FspEngine>,
+pub(crate) struct Fsp<'a> {
+ falcon: Falcon<'a, FspEngine>,
fsp_fw: FspFirmware,
}
-impl Fsp {
+impl<'a> Fsp<'a> {
/// Waits for FSP secure boot completion, then returns the [`Fsp`] interface.
///
/// Polls the thermal scratch register until FSP signals boot completion or the timeout
/// elapses. Returning an [`Fsp`] only on success guarantees, at the API level, that the
/// interface is not used before secure boot has completed.
pub(crate) fn wait_secure_boot(
- dev: &device::Device<device::Bound>,
- bar: Bar0<'_>,
+ dev: &'a device::Device<device::Bound>,
+ bar: Bar0<'a>,
chipset: Chipset,
- ) -> Result<Fsp> {
+ ) -> Result<Fsp<'a>> {
/// FSP secure boot completion timeout in milliseconds.
const FSP_SECURE_BOOT_TIMEOUT_MS: i64 = 5000;
let hal = hal::fsp_hal(chipset).ok_or(ENOTSUPP)?;
- let falcon = Falcon::<FspEngine>::new(dev, chipset)?;
+ let falcon = Falcon::<FspEngine>::new(dev, chipset, bar)?;
let fsp_fw = FspFirmware::new(dev, chipset, FIRMWARE_VERSION)?;
read_poll_timeout(
@@ -262,13 +262,13 @@ pub(crate) fn wait_secure_boot(
/// Sends a message to FSP and waits for the response.
/// Returns the full response buffer on success.
- fn send_sync_fsp<M>(&mut self, dev: &device::Device, bar: Bar0<'_>, msg: &M) -> Result<KVec<u8>>
+ fn send_sync_fsp<M>(&mut self, dev: &device::Device, msg: &M) -> Result<KVec<u8>>
where
M: MessageToFsp,
{
- self.falcon.send_msg(bar, msg.as_bytes())?;
+ self.falcon.send_msg(msg.as_bytes())?;
- let response_buf = self.falcon.recv_msg(bar).inspect_err(|e| {
+ let response_buf = self.falcon.recv_msg().inspect_err(|e| {
dev_err!(dev, "FSP response error: {:?}\n", e);
})?;
@@ -330,7 +330,6 @@ fn send_sync_fsp<M>(&mut self, dev: &device::Device, bar: Bar0<'_>, msg: &M) ->
pub(crate) fn boot_fmc(
&mut self,
dev: &device::Device<device::Bound>,
- bar: Bar0<'_>,
fb_layout: &FbLayout,
args: &FmcBootArgs,
) -> Result {
@@ -341,7 +340,7 @@ pub(crate) fn boot_fmc(
GFP_KERNEL,
)?;
- let _response_buf = self.send_sync_fsp(dev, bar, &*msg)?;
+ let _response_buf = self.send_sync_fsp(dev, &*msg)?;
dev_dbg!(dev, "FSP Chain of Trust completed successfully\n");
Ok(())
diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs
index 4d76be429e75..43c3f4f8df71 100644
--- a/drivers/gpu/nova-core/gpu.rs
+++ b/drivers/gpu/nova-core/gpu.rs
@@ -273,9 +273,9 @@ struct GspResources<'gpu> {
/// MMIO mapping of PCI BAR 0.
bar: Bar0<'gpu>,
/// GSP falcon instance, used for GSP boot up and cleanup.
- gsp_falcon: Falcon<GspFalcon>,
+ gsp_falcon: Falcon<'gpu, GspFalcon>,
/// SEC2 falcon instance, used for GSP boot up and cleanup.
- sec2_falcon: Falcon<Sec2Falcon>,
+ sec2_falcon: Falcon<'gpu, Sec2Falcon>,
/// GSP runtime data.
#[pin]
gsp: Gsp,
@@ -351,10 +351,11 @@ pub(crate) fn new(
gsp_falcon: Falcon::new(
pdev.as_ref(),
spec.chipset,
+ bar
)
- .inspect(|falcon| falcon.clear_swgen0_intr(bar))?,
+ .inspect(|falcon| falcon.clear_swgen0_intr())?,
- sec2_falcon: Falcon::new(pdev.as_ref(), spec.chipset)?,
+ sec2_falcon: Falcon::new(pdev.as_ref(), spec.chipset, bar)?,
gsp <- Gsp::new(pdev),
diff --git a/drivers/gpu/nova-core/gsp.rs b/drivers/gpu/nova-core/gsp.rs
index 73e93403601c..b4ac4156056e 100644
--- a/drivers/gpu/nova-core/gsp.rs
+++ b/drivers/gpu/nova-core/gsp.rs
@@ -57,8 +57,8 @@ pub(crate) struct GspBootContext<'a> {
pub(crate) pdev: &'a pci::Device<device::Bound>,
pub(crate) bar: Bar0<'a>,
pub(crate) chipset: Chipset,
- pub(crate) gsp_falcon: &'a Falcon<GspFalcon>,
- pub(crate) sec2_falcon: &'a Falcon<Sec2Falcon>,
+ pub(crate) gsp_falcon: &'a Falcon<'a, GspFalcon>,
+ pub(crate) sec2_falcon: &'a Falcon<'a, Sec2Falcon>,
}
impl<'a> GspBootContext<'a> {
diff --git a/drivers/gpu/nova-core/gsp/boot.rs b/drivers/gpu/nova-core/gsp/boot.rs
index bb2000b7a78b..ab0491b57944 100644
--- a/drivers/gpu/nova-core/gsp/boot.rs
+++ b/drivers/gpu/nova-core/gsp/boot.rs
@@ -37,8 +37,8 @@ pub(super) struct BootUnloadArgs<'a> {
gsp: &'a super::Gsp,
dev: &'a device::Device<device::Bound>,
bar: Bar0<'a>,
- gsp_falcon: &'a Falcon<Gsp>,
- sec2_falcon: &'a Falcon<Sec2>,
+ gsp_falcon: &'a Falcon<'a, Gsp>,
+ sec2_falcon: &'a Falcon<'a, Sec2>,
unload_bundle: Option<super::UnloadBundle>,
}
@@ -56,8 +56,8 @@ pub(super) fn new(
gsp: &'a super::Gsp,
dev: &'a device::Device<device::Bound>,
bar: Bar0<'a>,
- gsp_falcon: &'a Falcon<Gsp>,
- sec2_falcon: &'a Falcon<Sec2>,
+ gsp_falcon: &'a Falcon<'a, Gsp>,
+ sec2_falcon: &'a Falcon<'a, Sec2>,
unload_bundle: Option<super::UnloadBundle>,
) -> Self {
Self {
@@ -120,17 +120,17 @@ pub(crate) fn boot(
// Perform the chipset-specific boot sequence, and retrieve the unload bundle.
let unload_guard = hal.boot(&self, &ctx, &fb_layout, &wpr_meta)?;
- gsp_falcon.write_os_version(bar, gsp_fw.bootloader.app_version);
+ gsp_falcon.write_os_version(gsp_fw.bootloader.app_version);
// Poll for RISC-V to become active before continuing.
read_poll_timeout(
- || Ok(gsp_falcon.is_riscv_active(bar)),
+ || Ok(gsp_falcon.is_riscv_active()),
|val: &bool| *val,
Delta::from_millis(10),
Delta::from_secs(5),
)?;
- dev_dbg!(pdev, "RISC-V active? {}\n", gsp_falcon.is_riscv_active(bar),);
+ dev_dbg!(pdev, "RISC-V active? {}\n", gsp_falcon.is_riscv_active(),);
self.cmdq
.send_command_no_wait(bar, commands::SetSystemInfo::new(pdev, chipset))?;
@@ -149,7 +149,7 @@ pub(crate) fn boot(
fn shutdown_gsp(
cmdq: &Cmdq,
bar: Bar0<'_>,
- gsp_falcon: &Falcon<Gsp>,
+ gsp_falcon: &Falcon<'_, Gsp>,
mode: commands::PowerStateLevel,
) -> Result {
// Command to shut the GSP down.
@@ -158,7 +158,7 @@ fn shutdown_gsp(
// Wait until GSP signals it is suspended.
const LIBOS_INTERRUPT_PROCESSOR_SUSPENDED: u32 = bits::bit_u32(31);
read_poll_timeout(
- || Ok(gsp_falcon.read_mailbox0(bar)),
+ || Ok(gsp_falcon.read_mailbox0()),
|&mb0| mb0 & LIBOS_INTERRUPT_PROCESSOR_SUSPENDED != 0,
Delta::from_millis(10),
Delta::from_secs(5),
@@ -173,8 +173,8 @@ pub(crate) fn unload(
&self,
dev: &device::Device<device::Bound>,
bar: Bar0<'_>,
- gsp_falcon: &Falcon<Gsp>,
- sec2_falcon: &Falcon<Sec2>,
+ gsp_falcon: &Falcon<'_, Gsp>,
+ sec2_falcon: &Falcon<'_, Sec2>,
unload_bundle: Option<super::UnloadBundle>,
) -> Result {
// Shut down the GSP. Keep going even in case of error.
diff --git a/drivers/gpu/nova-core/gsp/hal.rs b/drivers/gpu/nova-core/gsp/hal.rs
index 51a277fe97bb..d3e47ef206de 100644
--- a/drivers/gpu/nova-core/gsp/hal.rs
+++ b/drivers/gpu/nova-core/gsp/hal.rs
@@ -42,8 +42,8 @@ fn run(
&self,
dev: &device::Device<device::Bound>,
bar: Bar0<'_>,
- gsp_falcon: &Falcon<GspEngine>,
- sec2_falcon: &Falcon<Sec2>,
+ gsp_falcon: &Falcon<'_, GspEngine>,
+ sec2_falcon: &Falcon<'_, Sec2>,
) -> Result;
}
diff --git a/drivers/gpu/nova-core/gsp/hal/gh100.rs b/drivers/gpu/nova-core/gsp/hal/gh100.rs
index 2187e11168b2..1d06405a32f6 100644
--- a/drivers/gpu/nova-core/gsp/hal/gh100.rs
+++ b/drivers/gpu/nova-core/gsp/hal/gh100.rs
@@ -42,10 +42,10 @@ struct GspMbox {
impl GspMbox {
/// Reads both mailboxes from the GSP falcon.
- fn read(gsp_falcon: &Falcon<GspEngine>, bar: Bar0<'_>) -> Self {
+ fn read(gsp_falcon: &Falcon<'_, GspEngine>) -> Self {
Self {
- mbox0: gsp_falcon.read_mailbox0(bar),
- mbox1: gsp_falcon.read_mailbox1(bar),
+ mbox0: gsp_falcon.read_mailbox0(),
+ mbox1: gsp_falcon.read_mailbox1(),
}
}
@@ -60,8 +60,7 @@ fn combined_addr(&self) -> u64 {
/// either condition should stop the poll loop.
fn lockdown_released_or_error(
&self,
- gsp_falcon: &Falcon<GspEngine>,
- bar: Bar0<'_>,
+ gsp_falcon: &Falcon<'_, GspEngine>,
fmc_boot_params_addr: u64,
) -> bool {
// GSP-FMC normally clears the boot parameters address from the mailboxes early during
@@ -71,15 +70,14 @@ fn lockdown_released_or_error(
return self.combined_addr() != fmc_boot_params_addr;
}
- !gsp_falcon.riscv_branch_privilege_lockdown(bar)
+ !gsp_falcon.riscv_branch_privilege_lockdown()
}
}
/// Waits for GSP lockdown to be released after FSP Chain of Trust.
fn wait_for_gsp_lockdown_release(
dev: &device::Device<device::Bound>,
- bar: Bar0<'_>,
- gsp_falcon: &Falcon<GspEngine>,
+ gsp_falcon: &Falcon<'_, GspEngine>,
fmc_boot_params_addr: u64,
) -> Result {
dev_dbg!(dev, "Waiting for GSP lockdown release\n");
@@ -88,14 +86,14 @@ fn wait_for_gsp_lockdown_release(
|| {
// While the PRIV target mask is still locked to FSP, GSP register and mailbox reads
// are not meaningful. Wait until HWCFG2 says the CPU can read them.
- Ok(match gsp_falcon.priv_target_mask_released(bar) {
+ Ok(match gsp_falcon.priv_target_mask_released() {
false => None,
- true => Some(GspMbox::read(gsp_falcon, bar)),
+ true => Some(GspMbox::read(gsp_falcon)),
})
},
|mbox| match mbox {
None => false,
- Some(mbox) => mbox.lockdown_released_or_error(gsp_falcon, bar, fmc_boot_params_addr),
+ Some(mbox) => mbox.lockdown_released_or_error(gsp_falcon, fmc_boot_params_addr),
},
Delta::from_millis(10),
Delta::from_secs(30),
@@ -122,13 +120,13 @@ impl UnloadBundle for FspUnloadBundle {
fn run(
&self,
dev: &device::Device<device::Bound>,
- bar: Bar0<'_>,
- gsp_falcon: &Falcon<GspEngine>,
- _sec2_falcon: &Falcon<Sec2>,
+ _bar: Bar0<'_>,
+ gsp_falcon: &Falcon<'_, GspEngine>,
+ _sec2_falcon: &Falcon<'_, Sec2>,
) -> 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(bar)),
+ || Ok(gsp_falcon.is_riscv_active()),
|&active| !active,
Delta::from_millis(10),
Delta::from_secs(5),
@@ -176,9 +174,9 @@ fn boot<'a>(
false,
)?;
- fsp.boot_fmc(dev, bar, fb_layout, &args)?;
+ fsp.boot_fmc(dev, fb_layout, &args)?;
- wait_for_gsp_lockdown_release(dev, bar, gsp_falcon, args.boot_params_dma_handle())?;
+ wait_for_gsp_lockdown_release(dev, gsp_falcon, args.boot_params_dma_handle())?;
Ok(unload_guard)
}
diff --git a/drivers/gpu/nova-core/gsp/hal/tu102.rs b/drivers/gpu/nova-core/gsp/hal/tu102.rs
index f8a8541704ee..ff71b45b5432 100644
--- a/drivers/gpu/nova-core/gsp/hal/tu102.rs
+++ b/drivers/gpu/nova-core/gsp/hal/tu102.rs
@@ -62,12 +62,11 @@ impl FwsecUnloadFirmware {
/// Loads the FWSEC SB firmware, as well as its bootloader if `chipset` requires it.
fn new(
dev: &device::Device<device::Bound>,
- bar: Bar0<'_>,
chipset: Chipset,
bios: &Vbios,
- gsp_falcon: &Falcon<GspEngine>,
+ gsp_falcon: &Falcon<'_, GspEngine>,
) -> Result<Self> {
- let fwsec_sb = FwsecFirmware::new(dev, gsp_falcon, bar, bios, FwsecCommand::Sb)?;
+ let fwsec_sb = FwsecFirmware::new(dev, gsp_falcon, bios, FwsecCommand::Sb)?;
Ok(if chipset.needs_fwsec_bootloader() {
Self::WithBl(FwsecFirmwareWithBl::new(fwsec_sb, dev, chipset)?)
@@ -81,10 +80,10 @@ fn run(
&self,
dev: &device::Device<device::Bound>,
bar: Bar0<'_>,
- gsp_falcon: &Falcon<GspEngine>,
+ gsp_falcon: &Falcon<'_, GspEngine>,
) -> Result {
match self {
- Self::WithoutBl(fw) => fw.run(dev, gsp_falcon, bar),
+ Self::WithoutBl(fw) => fw.run(dev, gsp_falcon),
Self::WithBl(fw) => fw.run(dev, gsp_falcon, bar),
}
}
@@ -101,22 +100,20 @@ impl Sec2UnloadBundle {
/// Load and prepare the resources required to properly reset the GSP after it has been stopped.
fn build(
dev: &device::Device<device::Bound>,
- bar: Bar0<'_>,
chipset: Chipset,
bios: &Vbios,
- gsp_falcon: &Falcon<GspEngine>,
- sec2_falcon: &Falcon<Sec2>,
+ gsp_falcon: &Falcon<'_, GspEngine>,
+ sec2_falcon: &Falcon<'_, Sec2>,
) -> Result<KBox<dyn UnloadBundle>> {
KBox::new(
Self {
- fwsec_sb: FwsecUnloadFirmware::new(dev, bar, chipset, bios, gsp_falcon)?,
+ fwsec_sb: FwsecUnloadFirmware::new(dev, chipset, bios, gsp_falcon)?,
booter_unloader: BooterFirmware::new(
dev,
BooterKind::Unloader,
chipset,
FIRMWARE_VERSION,
sec2_falcon,
- bar,
)?,
},
GFP_KERNEL,
@@ -131,8 +128,8 @@ fn run(
&self,
dev: &device::Device<device::Bound>,
bar: Bar0<'_>,
- gsp_falcon: &Falcon<GspEngine>,
- sec2_falcon: &Falcon<Sec2>,
+ gsp_falcon: &Falcon<'_, GspEngine>,
+ sec2_falcon: &Falcon<'_, Sec2>,
) -> Result {
// Run FWSEC-SB to reset the GSP falcon to its pre-libos state.
// Log errors but keep going if it fails.
@@ -148,13 +145,12 @@ fn run(
return Ok(());
}
- sec2_falcon.reset(bar)?;
- sec2_falcon.load(dev, bar, &self.booter_unloader)?;
+ sec2_falcon.reset()?;
+ 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(bar, Some(MAILBOX_SENTINEL), Some(MAILBOX_SENTINEL))?;
+ let (mbox0, _) = 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);
@@ -183,7 +179,7 @@ fn run(
fn run_fwsec_frts(
dev: &device::Device<device::Bound>,
chipset: Chipset,
- falcon: &Falcon<GspEngine>,
+ falcon: &Falcon<'_, GspEngine>,
bar: Bar0<'_>,
bios: &Vbios,
fb_layout: &FbLayout,
@@ -202,7 +198,6 @@ fn run_fwsec_frts(
let fwsec_frts = FwsecFirmware::new(
dev,
falcon,
- bar,
bios,
FwsecCommand::Frts {
frts_addr: fb_layout.frts.start,
@@ -216,7 +211,7 @@ fn run_fwsec_frts(
fwsec_frts_bl.run(dev, falcon, bar)?;
} else {
// Load and run FWSEC-FRTS directly.
- fwsec_frts.run(dev, falcon, bar)?;
+ fwsec_frts.run(dev, falcon)?;
}
// SCRATCH_E contains the error code for FWSEC-FRTS.
@@ -286,18 +281,17 @@ fn boot<'a>(
//
// If the unload bundle creation fails, the GPU will need to be reset before the driver can
// be probed again.
- let unload_bundle =
- Sec2UnloadBundle::build(dev, bar, chipset, &bios, gsp_falcon, sec2_falcon)
- .inspect_err(|e| {
- dev_warn!(dev, "Failed to prepare unload firmware: {:?}\n", e);
- dev_warn!(dev, "The GSP won't be able to unload properly on unbind.\n");
- dev_warn!(
- dev,
- "The GPU will need to be reset before the driver can bind again.\n"
- );
- })
- .ok()
- .map(crate::gsp::UnloadBundle);
+ let unload_bundle = Sec2UnloadBundle::build(dev, chipset, &bios, gsp_falcon, sec2_falcon)
+ .inspect_err(|e| {
+ dev_warn!(dev, "Failed to prepare unload firmware: {:?}\n", e);
+ dev_warn!(dev, "The GSP won't be able to unload properly on unbind.\n");
+ dev_warn!(
+ dev,
+ "The GPU will need to be reset before the driver can bind again.\n"
+ );
+ })
+ .ok()
+ .map(crate::gsp::UnloadBundle);
// Wrap the unload bundle into a drop guard so it is automatically run upon failure.
let unload_guard =
@@ -308,13 +302,10 @@ fn boot<'a>(
run_fwsec_frts(dev, chipset, gsp_falcon, bar, &bios, fb_layout)?;
}
- gsp_falcon.reset(bar)?;
+ gsp_falcon.reset()?;
let libos_handle = gsp.libos.dma_handle();
- let (mbox0, mbox1) = gsp_falcon.boot(
- bar,
- Some(libos_handle as u32),
- Some((libos_handle >> 32) as u32),
- )?;
+ let (mbox0, mbox1) =
+ gsp_falcon.boot(Some(libos_handle as u32), Some((libos_handle >> 32) as u32))?;
dev_dbg!(dev, "GSP MBOX0: {:#x}, MBOX1: {:#x}\n", mbox0, mbox1);
dev_dbg!(
@@ -328,9 +319,8 @@ fn boot<'a>(
chipset,
FIRMWARE_VERSION,
sec2_falcon,
- bar,
)?
- .run(dev, bar, sec2_falcon, wpr_meta)?;
+ .run(dev, sec2_falcon, wpr_meta)?;
Ok(unload_guard)
}
diff --git a/drivers/gpu/nova-core/gsp/sequencer.rs b/drivers/gpu/nova-core/gsp/sequencer.rs
index e0850d21adca..13983d42b12b 100644
--- a/drivers/gpu/nova-core/gsp/sequencer.rs
+++ b/drivers/gpu/nova-core/gsp/sequencer.rs
@@ -133,9 +133,9 @@ pub(crate) struct GspSequencer<'a> {
/// `Bar0` for register access.
bar: Bar0<'a>,
/// SEC2 falcon for core operations.
- sec2_falcon: &'a Falcon<Sec2>,
+ sec2_falcon: &'a Falcon<'a, Sec2>,
/// GSP falcon for core operations.
- gsp_falcon: &'a Falcon<Gsp>,
+ gsp_falcon: &'a Falcon<'a, Gsp>,
/// LibOS DMA handle address.
libos_dma_handle: u64,
/// Bootloader application version.
@@ -213,16 +213,16 @@ fn run(&self, seq: &GspSequencer<'_>) -> Result {
GspSeqCmd::DelayUs(cmd) => cmd.run(seq),
GspSeqCmd::RegStore(cmd) => cmd.run(seq),
GspSeqCmd::CoreReset => {
- seq.gsp_falcon.reset(seq.bar)?;
- seq.gsp_falcon.dma_reset(seq.bar);
+ seq.gsp_falcon.reset()?;
+ seq.gsp_falcon.dma_reset();
Ok(())
}
GspSeqCmd::CoreStart => {
- seq.gsp_falcon.start(seq.bar)?;
+ seq.gsp_falcon.start()?;
Ok(())
}
GspSeqCmd::CoreWaitForHalt => {
- seq.gsp_falcon.wait_till_halted(seq.bar)?;
+ seq.gsp_falcon.wait_till_halted()?;
Ok(())
}
GspSeqCmd::CoreResume => {
@@ -231,35 +231,32 @@ fn run(&self, seq: &GspSequencer<'_>) -> Result {
// sequencer will start both.
// Reset the GSP to prepare it for resuming.
- seq.gsp_falcon.reset(seq.bar)?;
+ seq.gsp_falcon.reset()?;
// Write the libOS DMA handle to GSP mailboxes.
seq.gsp_falcon.write_mailboxes(
- seq.bar,
Some(seq.libos_dma_handle as u32),
Some((seq.libos_dma_handle >> 32) as u32),
);
// Start the SEC2 falcon which will trigger GSP-RM to resume on the GSP.
- seq.sec2_falcon.start(seq.bar)?;
+ seq.sec2_falcon.start()?;
// Poll until GSP-RM reload/resume has completed (up to 2 seconds).
- seq.gsp_falcon
- .check_reload_completed(seq.bar, Delta::from_secs(2))?;
+ seq.gsp_falcon.check_reload_completed(Delta::from_secs(2))?;
// Verify SEC2 completed successfully by checking its mailbox for errors.
- let mbox0 = seq.sec2_falcon.read_mailbox0(seq.bar);
+ let mbox0 = seq.sec2_falcon.read_mailbox0();
if mbox0 != 0 {
dev_err!(seq.dev, "Sequencer: sec2 errors: {:?}\n", mbox0);
return Err(EIO);
}
// Configure GSP with the bootloader version.
- seq.gsp_falcon
- .write_os_version(seq.bar, seq.bootloader_app_version);
+ seq.gsp_falcon.write_os_version(seq.bootloader_app_version);
// Verify the GSP's RISC-V core is active indicating successful GSP boot.
- if !seq.gsp_falcon.is_riscv_active(seq.bar) {
+ if !seq.gsp_falcon.is_riscv_active() {
dev_err!(seq.dev, "Sequencer: RISC-V core is not active\n");
return Err(EIO);
}
@@ -345,9 +342,9 @@ pub(crate) struct GspSequencerParams<'a> {
/// LibOS DMA handle address.
pub(crate) libos_dma_handle: u64,
/// GSP falcon for core operations.
- pub(crate) gsp_falcon: &'a Falcon<Gsp>,
+ pub(crate) gsp_falcon: &'a Falcon<'a, Gsp>,
/// SEC2 falcon for core operations.
- pub(crate) sec2_falcon: &'a Falcon<Sec2>,
+ pub(crate) sec2_falcon: &'a Falcon<'a, Sec2>,
/// Device for logging.
pub(crate) dev: &'a device::Device,
/// BAR0 for register access.
---
base-commit: fa8cc4e3067f958ea2057f37a8a6f9c6b10a9c03
change-id: 20260624-drm-bar-refactor-90435f04c9ea
Best regards,
--
Tim Kovalenko <tim.kovalenko@xxxxxxxxx>