drivers/gpu/nova-core/falcon.rs

Source file repositories/reference/linux-study-clean/drivers/gpu/nova-core/falcon.rs

File Facts

System
Linux kernel
Corpus path
drivers/gpu/nova-core/falcon.rs
Extension
.rs
Size
26000 bytes
Lines
799
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

pub(crate) fn dma_reset(&self, bar: Bar0<'_>) {
        bar.update(regs::NV_PFALCON_FBIF_CTL::of::<E>(), |v| {
            v.with_allow_phys_no_ctx(true)
        });

        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)?;

        bar.write(
            WithBase::of::<E>(),
            regs::NV_PFALCON_FALCON_RM::from(bar.read(regs::NV_PMC_BOOT_0).into_raw()),
        );

        Ok(())
    }

    /// Falcons supports up to four ports, but we only ever use one, so just hard-code it.
    const PIO_PORT: usize = 0;

    /// 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 {
        // Rejecting misaligned images here allows us to avoid checking
        // inside the loops.
        if load_offsets.data.len() % 4 != 0 {
            return Err(EINVAL);
        }

        bar.write(
            WithBase::of::<E>().at(Self::PIO_PORT),
            regs::NV_PFALCON_FALCON_IMEMC::zeroed()
                .with_secure(load_offsets.secure)
                .with_aincw(true)
                .with_offs(load_offsets.dst_start),
        );

        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(
                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(
                    WithBase::of::<E>().at(Self::PIO_PORT),
                    regs::NV_PFALCON_FALCON_IMEMD::zeroed().with_data(u32::from_le_bytes(w)),
                );
            }
        }

        Ok(())
    }

    /// 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 {
        // Rejecting misaligned images here allows us to avoid checking
        // inside the loops.
        if load_offsets.data.len() % 4 != 0 {
            return Err(EINVAL);
        }

        bar.write(
            WithBase::of::<E>().at(Self::PIO_PORT),
            regs::NV_PFALCON_FALCON_DMEMC::zeroed()
                .with_aincw(true)
                .with_offs(load_offsets.dst_start),
        );

Annotation

Implementation Notes