Re: [PATCH 15/27] gpu: nova-core: add GMC send path
Zhi Wang <[email protected]>
| Newsgroups | dev.linux.lists.nova-gpu,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <20260820141227.1376e13b@inno-dell> |
On Tue, 18 Aug 2026 20:52:08 -0700 John Hubbard <[email protected]> wrote: Looking good to me. Reviewed-by: Zhi Wang <[email protected]> > The r000 GSP-RM boot protocol requires the driver to send GSP_INIT as > a GMC command. GMC and RPC commands share the command queue and > sequence counter. GMC queue elements carry a GMC API header and no > checksum. > > Add the GMC send path needed for GSP_INIT. > > Assisted-by: Cursor:claude-opus-5 > Signed-off-by: John Hubbard <[email protected]> > --- > drivers/gpu/nova-core/gsp/cmdq.rs | 59 > +++++++++++++++++++++++++++++++ drivers/gpu/nova-core/gsp/fw.rs | > 1 - 2 files changed, 59 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/nova-core/gsp/cmdq.rs > b/drivers/gpu/nova-core/gsp/cmdq.rs index 0dab3d279426..88b143c6a7b7 > 100644 --- a/drivers/gpu/nova-core/gsp/cmdq.rs > +++ b/drivers/gpu/nova-core/gsp/cmdq.rs > @@ -52,6 +52,7 @@ > driver::Bar0, > gsp::{ > fw::{ > + GspGmcMsgElement, > GspMsgElement, > MsgFunction, > MsgqRxHeader, > @@ -963,6 +964,64 @@ fn send_command<M>(&mut self, bar: Bar0<'_>, > command: M) -> Result<u32> Ok(rpc_seq) > } > > + /// Sends a GMC API command to the GSP. > + /// > + /// `command_id` is the GMC command identifier (from > `GMCAPI_COMMANDS`). > + /// `payload` is the command-specific data following the > [`super::fw::GmcApiHeader`]. > + /// `max_response_size` is the maximum expected response payload > size. > + /// > + /// The command carries the next RPC sequence number, which the > GSP echoes in its response. > + /// The number is consumed whether or not the send succeeds. > + /// > + /// # Errors > + /// > + /// - `EMSGSIZE` if the command exceeds the maximum queue > element size. > + /// - `ETIMEDOUT` if space does not become available within the > timeout. > + /// - `EIO` if the command header is not properly aligned. > + #[expect(dead_code)] > + fn send_gmc( > + &mut self, > + bar: Bar0<'_>, > + command_id: u32, > + payload: &[u8], > + max_response_size: u32, > + ) -> Result { > + let rpc_seq = self.rpc_seq; > + self.rpc_seq = self.rpc_seq.wrapping_add(1); > + > + let dst = self > + .gsp_mem > + .allocate_command::<GspGmcMsgElement>(payload.len(), > Self::ALLOCATE_TIMEOUT)?; + > + let msg_element = GspGmcMsgElement::init( > + command_id, > + u64::from(rpc_seq), > + payload.len(), > + max_response_size, > + ); > + // SAFETY: `dst.header` points to a valid, writable > `GspGmcMsgElement` region. > + unsafe { > + msg_element.__init(core::ptr::from_mut(dst.header))?; > + } > + > + SBufferIter::new_writer([&mut dst.contents.0[..], &mut > dst.contents.1[..]]) > + .write_all(payload)?; > + > + dev_dbg!( > + &self.dev, > + "GSP GMC: send: seq# {}, command_id=0x{:x}, > length=0x{:x}\n", > + rpc_seq, > + command_id, > + dst.header.length(), > + ); > + > + let elem_count = dst.header.element_count(); > + self.gsp_mem.advance_cpu_write_ptr(elem_count); > + Cmdq::notify_gsp(bar); > + > + Ok(()) > + } > + > /// Wait for a message to become available on the message queue. > /// > /// This works purely at the transport layer and does not > interpret or validate the message diff --git > a/drivers/gpu/nova-core/gsp/fw.rs b/drivers/gpu/nova-core/gsp/fw.rs > index 050a6af8c0c7..56f255a3d49c 100644 --- > a/drivers/gpu/nova-core/gsp/fw.rs +++ > b/drivers/gpu/nova-core/gsp/fw.rs @@ -1016,7 +1016,6 @@ pub(crate) > struct GspGmcMsgElement { == > core::mem::offset_of!(r000_00::GSP_MSG_QUEUE_ELEMENT, nvdmHeader) ); > > -#[expect(dead_code)] > impl GspGmcMsgElement { > /// Creates a new GMC message element. > ///