drivers/gpu/nova-core/gsp/sequencer.rs

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/nova-core/gsp/sequencer.rs
Extension
.rs
Size
12716 bytes
Lines
400
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 GspSequence {
    /// Current command index for error reporting.
    cmd_index: u32,
    /// Command data buffer containing the sequence of commands.
    cmd_data: KVec<u8>,
}

impl MessageFromGsp for GspSequence {
    const FUNCTION: fw::MsgFunction = fw::MsgFunction::GspRunCpuSequencer;
    type InitError = Error;
    type Message = fw::RunCpuSequencer;

    fn read(
        msg: &Self::Message,
        sbuffer: &mut SBufferIter<array::IntoIter<&[u8], 2>>,
    ) -> Result<Self, Self::InitError> {
        let cmd_data = sbuffer.flush_into_kvec(GFP_KERNEL)?;
        Ok(GspSequence {
            cmd_index: msg.cmd_index(),
            cmd_data,
        })
    }
}

const CMD_SIZE: usize = size_of::<fw::SequencerBufferCmd>();

/// GSP Sequencer Command types with payload data.
/// Commands have an opcode and an opcode-dependent struct.
#[allow(clippy::enum_variant_names)]
#[derive(Debug)]
pub(crate) enum GspSeqCmd {
    RegWrite(fw::RegWritePayload),
    RegModify(fw::RegModifyPayload),
    RegPoll(fw::RegPollPayload),
    DelayUs(fw::DelayUsPayload),
    RegStore(fw::RegStorePayload),
    CoreReset,
    CoreStart,
    CoreWaitForHalt,
    CoreResume,
}

impl GspSeqCmd {
    /// Creates a new `GspSeqCmd` from raw data returning the command and its size in bytes.
    pub(crate) fn new(data: &[u8], dev: &device::Device) -> Result<(Self, usize)> {
        let fw_cmd = fw::SequencerBufferCmd::from_bytes(data).ok_or(EINVAL)?;
        let opcode_size = core::mem::size_of::<u32>();

        let (cmd, size) = match fw_cmd.opcode()? {
            fw::SeqBufOpcode::RegWrite => {
                let payload = fw_cmd.reg_write_payload()?;
                let size = opcode_size + size_of_val(&payload);
                (GspSeqCmd::RegWrite(payload), size)
            }
            fw::SeqBufOpcode::RegModify => {
                let payload = fw_cmd.reg_modify_payload()?;
                let size = opcode_size + size_of_val(&payload);
                (GspSeqCmd::RegModify(payload), size)
            }
            fw::SeqBufOpcode::RegPoll => {
                let payload = fw_cmd.reg_poll_payload()?;
                let size = opcode_size + size_of_val(&payload);
                (GspSeqCmd::RegPoll(payload), size)
            }
            fw::SeqBufOpcode::DelayUs => {
                let payload = fw_cmd.delay_us_payload()?;
                let size = opcode_size + size_of_val(&payload);
                (GspSeqCmd::DelayUs(payload), size)
            }
            fw::SeqBufOpcode::RegStore => {
                let payload = fw_cmd.reg_store_payload()?;
                let size = opcode_size + size_of_val(&payload);
                (GspSeqCmd::RegStore(payload), size)
            }
            fw::SeqBufOpcode::CoreReset => (GspSeqCmd::CoreReset, opcode_size),
            fw::SeqBufOpcode::CoreStart => (GspSeqCmd::CoreStart, opcode_size),
            fw::SeqBufOpcode::CoreWaitForHalt => (GspSeqCmd::CoreWaitForHalt, opcode_size),
            fw::SeqBufOpcode::CoreResume => (GspSeqCmd::CoreResume, opcode_size),
        };

        if data.len() < size {
            dev_err!(dev, "Data is not enough for command\n");
            return Err(EINVAL);
        }

        Ok((cmd, size))
    }
}

/// GSP Sequencer for executing firmware commands during boot.

Annotation

Implementation Notes