drivers/gpu/nova-core/gsp/hal/gh100.rs

Source file repositories/reference/linux-study-clean/drivers/gpu/nova-core/gsp/hal/gh100.rs

File Facts

System
Linux kernel
Corpus path
drivers/gpu/nova-core/gsp/hal/gh100.rs
Extension
.rs
Size
5702 bytes
Lines
193
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct GspMbox {
    mbox0: u32,
    mbox1: u32,
}

impl GspMbox {
    /// Reads both mailboxes from the GSP falcon.
    fn read(gsp_falcon: &Falcon<GspEngine>, bar: Bar0<'_>) -> Self {
        Self {
            mbox0: gsp_falcon.read_mailbox0(bar),
            mbox1: gsp_falcon.read_mailbox1(bar),
        }
    }

    /// Combines mailbox0 and mailbox1 into a 64-bit address.
    fn combined_addr(&self) -> u64 {
        (u64::from(self.mbox1) << 32) | u64::from(self.mbox0)
    }

    /// Returns `true` if GSP lockdown has been released or a GSP-FMC error happened.
    ///
    /// Returns `true` both on successful lockdown release and on GSP-FMC-reported errors, since
    /// either condition should stop the poll loop.
    fn lockdown_released_or_error(
        &self,
        gsp_falcon: &Falcon<GspEngine>,
        bar: Bar0<'_>,
        fmc_boot_params_addr: u64,
    ) -> bool {
        // GSP-FMC normally clears the boot parameters address from the mailboxes early during
        // boot. If the address is still there, keep polling rather than treating it as an error.
        // Any other non-zero mailbox0 value is a GSP-FMC error code.
        if self.mbox0 != 0 {
            return self.combined_addr() != fmc_boot_params_addr;
        }

        !gsp_falcon.riscv_branch_privilege_lockdown(bar)
    }
}

/// 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>,
    fmc_boot_params_addr: u64,
) -> Result {
    dev_dbg!(dev, "Waiting for GSP lockdown release\n");

    let mbox = read_poll_timeout(
        || {
            // 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) {
                false => None,
                true => Some(GspMbox::read(gsp_falcon, bar)),
            })
        },
        |mbox| match mbox {
            None => false,
            Some(mbox) => mbox.lockdown_released_or_error(gsp_falcon, bar, fmc_boot_params_addr),
        },
        Delta::from_millis(10),
        Delta::from_secs(30),
    )
    .inspect_err(|_| {
        dev_err!(dev, "GSP lockdown release timeout\n");
    })?
    .ok_or(EIO)?;

    // If polling stopped with a non-zero mailbox0, it was not the boot parameters address
    // anymore and therefore represents a GSP-FMC error code.
    if mbox.mbox0 != 0 {
        dev_err!(dev, "GSP-FMC boot failed (mbox: {:#x})\n", mbox.mbox0);
        return Err(EIO);
    }

    dev_dbg!(dev, "GSP lockdown released\n");
    Ok(())
}

struct FspUnloadBundle;

impl UnloadBundle for FspUnloadBundle {
    fn run(
        &self,
        dev: &device::Device<device::Bound>,
        bar: Bar0<'_>,
        gsp_falcon: &Falcon<GspEngine>,
        _sec2_falcon: &Falcon<Sec2>,

Annotation

Implementation Notes