Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Joel Fernandes and committed by
Alexandre Courbot
2367ce2e 6ddfc892

+107 -15
+1 -4
drivers/gpu/nova-core/gsp/fw.rs
··· 389 389 #[derive(Copy, Clone)] 390 390 pub(crate) struct RegWritePayload(r570_144::GSP_SEQ_BUF_PAYLOAD_REG_WRITE); 391 391 392 - #[expect(unused)] 393 392 impl RegWritePayload { 394 393 /// Returns the register address. 395 394 pub(crate) fn addr(&self) -> u32 { ··· 412 413 #[derive(Copy, Clone)] 413 414 pub(crate) struct RegModifyPayload(r570_144::GSP_SEQ_BUF_PAYLOAD_REG_MODIFY); 414 415 415 - #[expect(unused)] 416 416 impl RegModifyPayload { 417 417 /// Returns the register address. 418 418 pub(crate) fn addr(&self) -> u32 { ··· 440 442 #[derive(Copy, Clone)] 441 443 pub(crate) struct RegPollPayload(r570_144::GSP_SEQ_BUF_PAYLOAD_REG_POLL); 442 444 443 - #[expect(unused)] 444 445 impl RegPollPayload { 445 446 /// Returns the register address. 446 447 pub(crate) fn addr(&self) -> u32 { ··· 492 495 #[derive(Copy, Clone)] 493 496 pub(crate) struct RegStorePayload(r570_144::GSP_SEQ_BUF_PAYLOAD_REG_STORE); 494 497 495 - #[expect(unused)] 496 498 impl RegStorePayload { 497 499 /// Returns the register address. 498 500 pub(crate) fn addr(&self) -> u32 { ··· 499 503 } 500 504 501 505 /// Returns the storage index. 506 + #[allow(unused)] 502 507 pub(crate) fn index(&self) -> u32 { 503 508 self.0.index 504 509 }
+106 -11
drivers/gpu/nova-core/gsp/sequencer.rs
··· 4 4 5 5 use core::{ 6 6 array, 7 - mem::size_of, // 7 + mem::{ 8 + size_of, 9 + size_of_val, // 10 + }, 8 11 }; 9 12 10 13 use kernel::{ 11 14 device, 15 + io::poll::read_poll_timeout, 12 16 prelude::*, 13 17 time::Delta, 14 18 transmute::FromBytes, ··· 33 29 }, 34 30 fw, 35 31 }, 32 + num::FromSafeCast, 36 33 sbuffer::SBufferIter, 37 34 }; 38 35 ··· 66 61 67 62 /// GSP Sequencer Command types with payload data. 68 63 /// Commands have an opcode and an opcode-dependent struct. 69 - #[allow(dead_code)] 70 - pub(crate) enum GspSeqCmd {} 64 + #[allow(clippy::enum_variant_names)] 65 + pub(crate) enum GspSeqCmd { 66 + RegWrite(fw::RegWritePayload), 67 + RegModify(fw::RegModifyPayload), 68 + RegPoll(fw::RegPollPayload), 69 + RegStore(fw::RegStorePayload), 70 + } 71 71 72 72 impl GspSeqCmd { 73 73 /// Creates a new `GspSeqCmd` from raw data returning the command and its size in bytes. 74 - pub(crate) fn new(data: &[u8], _dev: &device::Device) -> Result<(Self, usize)> { 75 - let _fw_cmd = fw::SequencerBufferCmd::from_bytes(data).ok_or(EINVAL)?; 76 - let _opcode_size = core::mem::size_of::<u32>(); 74 + pub(crate) fn new(data: &[u8], dev: &device::Device) -> Result<(Self, usize)> { 75 + let fw_cmd = fw::SequencerBufferCmd::from_bytes(data).ok_or(EINVAL)?; 76 + let opcode_size = core::mem::size_of::<u32>(); 77 77 78 - // NOTE: At this commit, NO opcodes exist yet, so just return error. 79 - // Later commits will add match arms here. 80 - Err(EINVAL) 78 + let (cmd, size) = match fw_cmd.opcode()? { 79 + fw::SeqBufOpcode::RegWrite => { 80 + let payload = fw_cmd.reg_write_payload()?; 81 + let size = opcode_size + size_of_val(&payload); 82 + (GspSeqCmd::RegWrite(payload), size) 83 + } 84 + fw::SeqBufOpcode::RegModify => { 85 + let payload = fw_cmd.reg_modify_payload()?; 86 + let size = opcode_size + size_of_val(&payload); 87 + (GspSeqCmd::RegModify(payload), size) 88 + } 89 + fw::SeqBufOpcode::RegPoll => { 90 + let payload = fw_cmd.reg_poll_payload()?; 91 + let size = opcode_size + size_of_val(&payload); 92 + (GspSeqCmd::RegPoll(payload), size) 93 + } 94 + fw::SeqBufOpcode::RegStore => { 95 + let payload = fw_cmd.reg_store_payload()?; 96 + let size = opcode_size + size_of_val(&payload); 97 + (GspSeqCmd::RegStore(payload), size) 98 + } 99 + _ => return Err(EINVAL), 100 + }; 101 + 102 + if data.len() < size { 103 + dev_err!(dev, "Data is not enough for command"); 104 + return Err(EINVAL); 105 + } 106 + 107 + Ok((cmd, size)) 81 108 } 82 109 } 83 110 ··· 137 100 fn run(&self, sequencer: &GspSequencer<'_>) -> Result; 138 101 } 139 102 103 + impl GspSeqCmdRunner for fw::RegWritePayload { 104 + fn run(&self, sequencer: &GspSequencer<'_>) -> Result { 105 + let addr = usize::from_safe_cast(self.addr()); 106 + 107 + sequencer.bar.try_write32(self.val(), addr) 108 + } 109 + } 110 + 111 + impl GspSeqCmdRunner for fw::RegModifyPayload { 112 + fn run(&self, sequencer: &GspSequencer<'_>) -> Result { 113 + let addr = usize::from_safe_cast(self.addr()); 114 + 115 + sequencer.bar.try_read32(addr).and_then(|val| { 116 + sequencer 117 + .bar 118 + .try_write32((val & !self.mask()) | self.val(), addr) 119 + }) 120 + } 121 + } 122 + 123 + impl GspSeqCmdRunner for fw::RegPollPayload { 124 + fn run(&self, sequencer: &GspSequencer<'_>) -> Result { 125 + let addr = usize::from_safe_cast(self.addr()); 126 + 127 + // Default timeout to 4 seconds. 128 + let timeout_us = if self.timeout() == 0 { 129 + 4_000_000 130 + } else { 131 + i64::from(self.timeout()) 132 + }; 133 + 134 + // First read. 135 + sequencer.bar.try_read32(addr)?; 136 + 137 + // Poll the requested register with requested timeout. 138 + read_poll_timeout( 139 + || sequencer.bar.try_read32(addr), 140 + |current| (current & self.mask()) == self.val(), 141 + Delta::ZERO, 142 + Delta::from_micros(timeout_us), 143 + ) 144 + .map(|_| ()) 145 + } 146 + } 147 + 148 + impl GspSeqCmdRunner for fw::RegStorePayload { 149 + fn run(&self, sequencer: &GspSequencer<'_>) -> Result { 150 + let addr = usize::from_safe_cast(self.addr()); 151 + 152 + sequencer.bar.try_read32(addr).map(|_| ()) 153 + } 154 + } 155 + 140 156 impl GspSeqCmdRunner for GspSeqCmd { 141 - fn run(&self, _seq: &GspSequencer<'_>) -> Result { 142 - Ok(()) 157 + fn run(&self, seq: &GspSequencer<'_>) -> Result { 158 + match self { 159 + GspSeqCmd::RegWrite(cmd) => cmd.run(seq), 160 + GspSeqCmd::RegModify(cmd) => cmd.run(seq), 161 + GspSeqCmd::RegPoll(cmd) => cmd.run(seq), 162 + GspSeqCmd::RegStore(cmd) => cmd.run(seq), 163 + } 143 164 } 144 165 } 145 166