mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 00:22:00 +02:00
gpu: nova-core: sequencer: Add register opcodes
These opcodes are used for register write, modify, poll and store (save) sequencer operations. Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com> [acourbot@nvidia.com: apply Lyude's suggested fixes.] Message-ID: <20251114195552.739371-9-joelagnelf@nvidia.com>
This commit is contained in:
parent
6ddfc892a5
commit
2367ce2e9e
|
|
@ -389,7 +389,6 @@ fn from(value: SeqBufOpcode) -> Self {
|
|||
#[derive(Copy, Clone)]
|
||||
pub(crate) struct RegWritePayload(r570_144::GSP_SEQ_BUF_PAYLOAD_REG_WRITE);
|
||||
|
||||
#[expect(unused)]
|
||||
impl RegWritePayload {
|
||||
/// Returns the register address.
|
||||
pub(crate) fn addr(&self) -> u32 {
|
||||
|
|
@ -413,7 +412,6 @@ unsafe impl AsBytes for RegWritePayload {}
|
|||
#[derive(Copy, Clone)]
|
||||
pub(crate) struct RegModifyPayload(r570_144::GSP_SEQ_BUF_PAYLOAD_REG_MODIFY);
|
||||
|
||||
#[expect(unused)]
|
||||
impl RegModifyPayload {
|
||||
/// Returns the register address.
|
||||
pub(crate) fn addr(&self) -> u32 {
|
||||
|
|
@ -442,7 +440,6 @@ unsafe impl AsBytes for RegModifyPayload {}
|
|||
#[derive(Copy, Clone)]
|
||||
pub(crate) struct RegPollPayload(r570_144::GSP_SEQ_BUF_PAYLOAD_REG_POLL);
|
||||
|
||||
#[expect(unused)]
|
||||
impl RegPollPayload {
|
||||
/// Returns the register address.
|
||||
pub(crate) fn addr(&self) -> u32 {
|
||||
|
|
@ -495,7 +492,6 @@ unsafe impl AsBytes for DelayUsPayload {}
|
|||
#[derive(Copy, Clone)]
|
||||
pub(crate) struct RegStorePayload(r570_144::GSP_SEQ_BUF_PAYLOAD_REG_STORE);
|
||||
|
||||
#[expect(unused)]
|
||||
impl RegStorePayload {
|
||||
/// Returns the register address.
|
||||
pub(crate) fn addr(&self) -> u32 {
|
||||
|
|
@ -503,6 +499,7 @@ pub(crate) fn addr(&self) -> u32 {
|
|||
}
|
||||
|
||||
/// Returns the storage index.
|
||||
#[allow(unused)]
|
||||
pub(crate) fn index(&self) -> u32 {
|
||||
self.0.index
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,11 +4,15 @@
|
|||
|
||||
use core::{
|
||||
array,
|
||||
mem::size_of, //
|
||||
mem::{
|
||||
size_of,
|
||||
size_of_val, //
|
||||
},
|
||||
};
|
||||
|
||||
use kernel::{
|
||||
device,
|
||||
io::poll::read_poll_timeout,
|
||||
prelude::*,
|
||||
time::Delta,
|
||||
transmute::FromBytes,
|
||||
|
|
@ -29,6 +33,7 @@
|
|||
},
|
||||
fw,
|
||||
},
|
||||
num::FromSafeCast,
|
||||
sbuffer::SBufferIter,
|
||||
};
|
||||
|
||||
|
|
@ -61,18 +66,50 @@ fn read(
|
|||
|
||||
/// GSP Sequencer Command types with payload data.
|
||||
/// Commands have an opcode and an opcode-dependent struct.
|
||||
#[allow(dead_code)]
|
||||
pub(crate) enum GspSeqCmd {}
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
pub(crate) enum GspSeqCmd {
|
||||
RegWrite(fw::RegWritePayload),
|
||||
RegModify(fw::RegModifyPayload),
|
||||
RegPoll(fw::RegPollPayload),
|
||||
RegStore(fw::RegStorePayload),
|
||||
}
|
||||
|
||||
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>();
|
||||
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>();
|
||||
|
||||
// NOTE: At this commit, NO opcodes exist yet, so just return error.
|
||||
// Later commits will add match arms here.
|
||||
Err(EINVAL)
|
||||
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::RegStore => {
|
||||
let payload = fw_cmd.reg_store_payload()?;
|
||||
let size = opcode_size + size_of_val(&payload);
|
||||
(GspSeqCmd::RegStore(payload), size)
|
||||
}
|
||||
_ => return Err(EINVAL),
|
||||
};
|
||||
|
||||
if data.len() < size {
|
||||
dev_err!(dev, "Data is not enough for command");
|
||||
return Err(EINVAL);
|
||||
}
|
||||
|
||||
Ok((cmd, size))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -100,9 +137,67 @@ pub(crate) trait GspSeqCmdRunner {
|
|||
fn run(&self, sequencer: &GspSequencer<'_>) -> Result;
|
||||
}
|
||||
|
||||
impl GspSeqCmdRunner for fw::RegWritePayload {
|
||||
fn run(&self, sequencer: &GspSequencer<'_>) -> Result {
|
||||
let addr = usize::from_safe_cast(self.addr());
|
||||
|
||||
sequencer.bar.try_write32(self.val(), addr)
|
||||
}
|
||||
}
|
||||
|
||||
impl GspSeqCmdRunner for fw::RegModifyPayload {
|
||||
fn run(&self, sequencer: &GspSequencer<'_>) -> Result {
|
||||
let addr = usize::from_safe_cast(self.addr());
|
||||
|
||||
sequencer.bar.try_read32(addr).and_then(|val| {
|
||||
sequencer
|
||||
.bar
|
||||
.try_write32((val & !self.mask()) | self.val(), addr)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl GspSeqCmdRunner for fw::RegPollPayload {
|
||||
fn run(&self, sequencer: &GspSequencer<'_>) -> Result {
|
||||
let addr = usize::from_safe_cast(self.addr());
|
||||
|
||||
// Default timeout to 4 seconds.
|
||||
let timeout_us = if self.timeout() == 0 {
|
||||
4_000_000
|
||||
} else {
|
||||
i64::from(self.timeout())
|
||||
};
|
||||
|
||||
// First read.
|
||||
sequencer.bar.try_read32(addr)?;
|
||||
|
||||
// Poll the requested register with requested timeout.
|
||||
read_poll_timeout(
|
||||
|| sequencer.bar.try_read32(addr),
|
||||
|current| (current & self.mask()) == self.val(),
|
||||
Delta::ZERO,
|
||||
Delta::from_micros(timeout_us),
|
||||
)
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
impl GspSeqCmdRunner for fw::RegStorePayload {
|
||||
fn run(&self, sequencer: &GspSequencer<'_>) -> Result {
|
||||
let addr = usize::from_safe_cast(self.addr());
|
||||
|
||||
sequencer.bar.try_read32(addr).map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
impl GspSeqCmdRunner for GspSeqCmd {
|
||||
fn run(&self, _seq: &GspSequencer<'_>) -> Result {
|
||||
Ok(())
|
||||
fn run(&self, seq: &GspSequencer<'_>) -> Result {
|
||||
match self {
|
||||
GspSeqCmd::RegWrite(cmd) => cmd.run(seq),
|
||||
GspSeqCmd::RegModify(cmd) => cmd.run(seq),
|
||||
GspSeqCmd::RegPoll(cmd) => cmd.run(seq),
|
||||
GspSeqCmd::RegStore(cmd) => cmd.run(seq),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user