Skip to content

Commit 2367ce2

Browse files
Joel FernandesGnurou
authored andcommitted
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>
1 parent 6ddfc89 commit 2367ce2

2 files changed

Lines changed: 107 additions & 15 deletions

File tree

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,6 @@ impl From<SeqBufOpcode> for u32 {
389389
#[derive(Copy, Clone)]
390390
pub(crate) struct RegWritePayload(r570_144::GSP_SEQ_BUF_PAYLOAD_REG_WRITE);
391391

392-
#[expect(unused)]
393392
impl RegWritePayload {
394393
/// Returns the register address.
395394
pub(crate) fn addr(&self) -> u32 {
@@ -413,7 +412,6 @@ unsafe impl AsBytes for RegWritePayload {}
413412
#[derive(Copy, Clone)]
414413
pub(crate) struct RegModifyPayload(r570_144::GSP_SEQ_BUF_PAYLOAD_REG_MODIFY);
415414

416-
#[expect(unused)]
417415
impl RegModifyPayload {
418416
/// Returns the register address.
419417
pub(crate) fn addr(&self) -> u32 {
@@ -442,7 +440,6 @@ unsafe impl AsBytes for RegModifyPayload {}
442440
#[derive(Copy, Clone)]
443441
pub(crate) struct RegPollPayload(r570_144::GSP_SEQ_BUF_PAYLOAD_REG_POLL);
444442

445-
#[expect(unused)]
446443
impl RegPollPayload {
447444
/// Returns the register address.
448445
pub(crate) fn addr(&self) -> u32 {
@@ -495,14 +492,14 @@ unsafe impl AsBytes for DelayUsPayload {}
495492
#[derive(Copy, Clone)]
496493
pub(crate) struct RegStorePayload(r570_144::GSP_SEQ_BUF_PAYLOAD_REG_STORE);
497494

498-
#[expect(unused)]
499495
impl RegStorePayload {
500496
/// Returns the register address.
501497
pub(crate) fn addr(&self) -> u32 {
502498
self.0.addr
503499
}
504500

505501
/// Returns the storage index.
502+
#[allow(unused)]
506503
pub(crate) fn index(&self) -> u32 {
507504
self.0.index
508505
}

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

Lines changed: 106 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@
44
55
use core::{
66
array,
7-
mem::size_of, //
7+
mem::{
8+
size_of,
9+
size_of_val, //
10+
},
811
};
912

1013
use kernel::{
1114
device,
15+
io::poll::read_poll_timeout,
1216
prelude::*,
1317
time::Delta,
1418
transmute::FromBytes,
@@ -29,6 +33,7 @@ use crate::{
2933
},
3034
fw,
3135
},
36+
num::FromSafeCast,
3237
sbuffer::SBufferIter,
3338
};
3439

@@ -61,18 +66,50 @@ const CMD_SIZE: usize = size_of::<fw::SequencerBufferCmd>();
6166

6267
/// GSP Sequencer Command types with payload data.
6368
/// Commands have an opcode and an opcode-dependent struct.
64-
#[allow(dead_code)]
65-
pub(crate) enum GspSeqCmd {}
69+
#[allow(clippy::enum_variant_names)]
70+
pub(crate) enum GspSeqCmd {
71+
RegWrite(fw::RegWritePayload),
72+
RegModify(fw::RegModifyPayload),
73+
RegPoll(fw::RegPollPayload),
74+
RegStore(fw::RegStorePayload),
75+
}
6676

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

73-
// NOTE: At this commit, NO opcodes exist yet, so just return error.
74-
// Later commits will add match arms here.
75-
Err(EINVAL)
83+
let (cmd, size) = match fw_cmd.opcode()? {
84+
fw::SeqBufOpcode::RegWrite => {
85+
let payload = fw_cmd.reg_write_payload()?;
86+
let size = opcode_size + size_of_val(&payload);
87+
(GspSeqCmd::RegWrite(payload), size)
88+
}
89+
fw::SeqBufOpcode::RegModify => {
90+
let payload = fw_cmd.reg_modify_payload()?;
91+
let size = opcode_size + size_of_val(&payload);
92+
(GspSeqCmd::RegModify(payload), size)
93+
}
94+
fw::SeqBufOpcode::RegPoll => {
95+
let payload = fw_cmd.reg_poll_payload()?;
96+
let size = opcode_size + size_of_val(&payload);
97+
(GspSeqCmd::RegPoll(payload), size)
98+
}
99+
fw::SeqBufOpcode::RegStore => {
100+
let payload = fw_cmd.reg_store_payload()?;
101+
let size = opcode_size + size_of_val(&payload);
102+
(GspSeqCmd::RegStore(payload), size)
103+
}
104+
_ => return Err(EINVAL),
105+
};
106+
107+
if data.len() < size {
108+
dev_err!(dev, "Data is not enough for command");
109+
return Err(EINVAL);
110+
}
111+
112+
Ok((cmd, size))
76113
}
77114
}
78115

@@ -100,9 +137,67 @@ pub(crate) trait GspSeqCmdRunner {
100137
fn run(&self, sequencer: &GspSequencer<'_>) -> Result;
101138
}
102139

140+
impl GspSeqCmdRunner for fw::RegWritePayload {
141+
fn run(&self, sequencer: &GspSequencer<'_>) -> Result {
142+
let addr = usize::from_safe_cast(self.addr());
143+
144+
sequencer.bar.try_write32(self.val(), addr)
145+
}
146+
}
147+
148+
impl GspSeqCmdRunner for fw::RegModifyPayload {
149+
fn run(&self, sequencer: &GspSequencer<'_>) -> Result {
150+
let addr = usize::from_safe_cast(self.addr());
151+
152+
sequencer.bar.try_read32(addr).and_then(|val| {
153+
sequencer
154+
.bar
155+
.try_write32((val & !self.mask()) | self.val(), addr)
156+
})
157+
}
158+
}
159+
160+
impl GspSeqCmdRunner for fw::RegPollPayload {
161+
fn run(&self, sequencer: &GspSequencer<'_>) -> Result {
162+
let addr = usize::from_safe_cast(self.addr());
163+
164+
// Default timeout to 4 seconds.
165+
let timeout_us = if self.timeout() == 0 {
166+
4_000_000
167+
} else {
168+
i64::from(self.timeout())
169+
};
170+
171+
// First read.
172+
sequencer.bar.try_read32(addr)?;
173+
174+
// Poll the requested register with requested timeout.
175+
read_poll_timeout(
176+
|| sequencer.bar.try_read32(addr),
177+
|current| (current & self.mask()) == self.val(),
178+
Delta::ZERO,
179+
Delta::from_micros(timeout_us),
180+
)
181+
.map(|_| ())
182+
}
183+
}
184+
185+
impl GspSeqCmdRunner for fw::RegStorePayload {
186+
fn run(&self, sequencer: &GspSequencer<'_>) -> Result {
187+
let addr = usize::from_safe_cast(self.addr());
188+
189+
sequencer.bar.try_read32(addr).map(|_| ())
190+
}
191+
}
192+
103193
impl GspSeqCmdRunner for GspSeqCmd {
104-
fn run(&self, _seq: &GspSequencer<'_>) -> Result {
105-
Ok(())
194+
fn run(&self, seq: &GspSequencer<'_>) -> Result {
195+
match self {
196+
GspSeqCmd::RegWrite(cmd) => cmd.run(seq),
197+
GspSeqCmd::RegModify(cmd) => cmd.run(seq),
198+
GspSeqCmd::RegPoll(cmd) => cmd.run(seq),
199+
GspSeqCmd::RegStore(cmd) => cmd.run(seq),
200+
}
106201
}
107202
}
108203

0 commit comments

Comments
 (0)