From: "Eliot Courtney" <ecourtney@nvidia.com>
To: "Alexandre Courbot" <acourbot@nvidia.com>,
"John Hubbard" <jhubbard@nvidia.com>,
"Danilo Krummrich" <dakr@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"David Airlie" <airlied@gmail.com>,
"Simona Vetter" <simona@ffwll.ch>,
"Benno Lossin" <lossin@kernel.org>, "Gary Guo" <gary@garyguo.net>
Cc: "Alistair Popple" <apopple@nvidia.com>,
"Timur Tabi" <ttabi@nvidia.com>,
"Eliot Courtney" <ecourtney@nvidia.com>,
"Zhi Wang" <zhiw@nvidia.com>, <nova-gpu@lists.linux.dev>,
<dri-devel@lists.freedesktop.org>, <linux-kernel@vger.kernel.org>,
<rust-for-linux@vger.kernel.org>,
"dri-devel" <dri-devel-bounces@lists.freedesktop.org>
Subject: Re: [PATCH v2 4/9] gpu: nova-core: gsp: cmdq: split the transport part of the send path
Date: Mon, 28 Sep 2026 14:16:43 +0900 [thread overview]
Message-ID: <DLQP0I37RZTD.4C52AA74ID18@nvidia.com> (raw)
In-Reply-To: <20260927-cmdq-rpc-v2-4-c3f66ae73be4@nvidia.com>
On Sun Sep 27, 2026 at 10:46 PM JST, Alexandre Courbot wrote:
> Move the transport part of `send_single_command` into
> `send_command_element`, which allocates the queue slots, writes the
> element header, calls a closure to fill the remainder of the command,
> then computes the checksum, advances the write pointer and rings the
> doorbell.
>
> The RPC part of `send_single_command` (writing the RPC header and the
> command payload) is passed as a closure, unchanged apart from its
> indentation. This sets things up for moving the RPC code into its own
> sub-module, leaving the transport agnostic of the message type.
>
> No functional change intended.
>
> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
> ---
> drivers/gpu/nova-core/gsp/cmdq.rs | 118 ++++++++++++++++++++++++--------------
> 1 file changed, 74 insertions(+), 44 deletions(-)
>
> diff --git a/drivers/gpu/nova-core/gsp/cmdq.rs b/drivers/gpu/nova-core/gsp/cmdq.rs
> index 07e8e32c3d57..b6d50b0bd039 100644
> --- a/drivers/gpu/nova-core/gsp/cmdq.rs
> +++ b/drivers/gpu/nova-core/gsp/cmdq.rs
> @@ -638,65 +638,35 @@ impl CmdqInner<'_> {
> /// Timeout for waiting for space on the command queue.
> const ALLOCATE_TIMEOUT: Delta = Delta::from_secs(1);
>
> - /// Sends `command` to the GSP, without splitting it.
> + /// Allocates enough send slots to store a command of `sizes_in_bytes` length, initialize them
> + /// using `command_init`, and send the command to the GSP.
> ///
> /// # Errors
> ///
> /// - `EMSGSIZE` if the command exceeds the maximum queue element size.
> /// - `ETIMEDOUT` if space does not become available within the timeout.
> - /// - `EIO` if the variable payload requested by the command has not been entirely
> - /// written to by its [`CommandToGsp::init_variable_payload`] method.
> ///
> - /// Error codes returned by the command initializers are propagated as-is.
> - fn send_single_command<M>(&mut self, command: M) -> Result
> - where
> - M: CommandToGsp,
> - // This allows all error types, including `Infallible`, to be used for `M::InitError`.
> - Error: From<M::InitError>,
> - {
> - let size_in_bytes = command.size();
> - let dst = self
> + /// Error codes returned by `command_init` are returned as-is.
> + fn send_command_element(
> + &mut self,
> + size_in_bytes: usize,
> + command_init: impl FnOnce(&mut GspCommand<'_>) -> Result,
> + ) -> Result {
> + let mut dst = self
> .gsp_mem
> .allocate_command(size_in_bytes, Self::ALLOCATE_TIMEOUT)?;
>
> + let seq = self.seq;
nit: this local reads noisily to me
> +
> // Fill the header.
> - let msg_element_init = GspMsgElement::init(self.seq, size_in_bytes);
> + let msg_element_init = GspMsgElement::init(seq, size_in_bytes);
> // SAFETY: `msg_header` is a valid reference, and not touched if the initializer fails.
> unsafe {
> pin_init::raw_try_init(core::ptr::from_mut(dst.header), msg_element_init)?;
> }
>
> - // Extract area for the command itself. The GSP message header and the command header
> - // together are guaranteed to fit entirely into a single page, so it's ok to only look
> - // at `dst.contents.0` here.
> - let (cmd, payload_1) = M::Command::from_bytes_mut_prefix(dst.contents.0).ok_or(EIO)?;
> - let rpc_header_init = RpcMessageHeader::init(size_in_bytes, M::FUNCTION);
> - // SAFETY: `rpc_header_mut()` and `cmd` are valid references, and not touched if the
> - // initializer fails.
> - unsafe {
> - pin_init::raw_try_init(
> - core::ptr::from_mut(dst.header.rpc_header_mut()),
> - rpc_header_init,
> - )?;
> - pin_init::raw_try_init(core::ptr::from_mut(cmd), command.init())?;
> - }
> -
> - // Fill the variable-length payload, which may be empty.
> - let mut sbuffer = SBufferIter::new_writer([&mut payload_1[..], &mut dst.contents.1[..]]);
> - command.init_variable_payload(&mut sbuffer)?;
> -
> - if !sbuffer.is_empty() {
> - return Err(EIO);
> - }
> - drop(sbuffer);
> -
> - dev_dbg!(
> - &self.dev,
> - "GSP RPC: send: seq# {}, function={:?}, length=0x{:x}\n",
> - self.seq,
> - M::FUNCTION,
> - size_in_bytes,
> - );
> + // Initialize the message payload.
> + command_init(&mut dst)?;
>
> // Compute checksum now that the whole message is ready.
> dst.header
> @@ -715,6 +685,66 @@ fn send_single_command<M>(&mut self, command: M) -> Result
> Ok(())
> }
>
> + /// Sends `command` to the GSP, without splitting it.
> + ///
> + /// # Errors
> + ///
> + /// - `EMSGSIZE` if the command exceeds the maximum queue element size.
> + /// - `ETIMEDOUT` if space does not become available within the timeout.
> + /// - `EIO` if the variable payload requested by the command has not been entirely
> + /// written to by its [`CommandToGsp::init_variable_payload`] method.
> + ///
> + /// Error codes returned by the command initializers are propagated as-is.
> + fn send_single_command<M>(&mut self, command: M) -> Result
> + where
> + M: CommandToGsp,
> + // This allows all error types, including `Infallible`, to be used for `M::InitError`.
> + Error: From<M::InitError>,
> + {
> + let dev = self.dev;
> + let seq = self.seq;
> + let size_in_bytes = command.size();
I suspect if we pass dev and seq into the closure below, we can
further split the RPC layer from the transport layer. That means the
patches after this won't have to impl on CmdqInner for e.g.
`send_single_command` and instead we can just define a trait that writes
in the message layer data (so send_single_command could e.g. instead
take an impl RpcCommandWriter or whatever, and we can impl
RpcCommandWriter for anything that impls CommandToGsp, inserting the
message layer protocol stuff in there).
next prev parent reply other threads:[~2026-09-28 5:16 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-27 13:46 [PATCH v2 0/9] gpu: nova-core: gsp: prepare the command queue for r000 dual-message types Alexandre Courbot
2026-09-27 13:46 ` [PATCH v2 1/9] gpu: nova-core: gsp: cmdq: validate checksum earlier on receive Alexandre Courbot
2026-09-28 4:25 ` Eliot Courtney
2026-09-28 6:24 ` Alexandre Courbot
2026-09-27 13:46 ` [PATCH v2 2/9] gpu: nova-core: gsp: introduce and use proper RpcMessageHeader type Alexandre Courbot
2026-09-28 4:43 ` Eliot Courtney
2026-09-28 6:22 ` Alexandre Courbot
2026-09-27 13:46 ` [PATCH v2 3/9] gpu: nova-core: gsp: cmdq: group the RPC-specific part of send_single_command Alexandre Courbot
2026-09-28 4:52 ` Eliot Courtney
2026-09-27 13:46 ` [PATCH v2 4/9] gpu: nova-core: gsp: cmdq: split the transport part of the send path Alexandre Courbot
2026-09-28 5:16 ` Eliot Courtney [this message]
2026-09-28 6:19 ` Alexandre Courbot
2026-09-28 6:40 ` Eliot Courtney
2026-09-28 11:35 ` Alexandre Courbot
2026-09-27 13:46 ` [PATCH v2 5/9] gpu: nova-core: gsp: cmdq: move the RPC send code into a sub-module Alexandre Courbot
2026-09-27 13:46 ` [PATCH v2 6/9] gpu: nova-core: gsp: cmdq: split the transport part of the receive path Alexandre Courbot
2026-09-28 3:19 ` Alexandre Courbot
2026-09-27 13:46 ` [PATCH v2 7/9] gpu: nova-core: gsp: cmdq: move the RPC receive code into a sub-module Alexandre Courbot
2026-09-27 13:46 ` [PATCH v2 8/9] gpu: nova-core: gsp: move the RPC commands " Alexandre Courbot
2026-09-28 5:25 ` Eliot Courtney
2026-09-28 9:20 ` Zhi Wang
2026-09-28 11:40 ` Alexandre Courbot
2026-09-28 15:11 ` Zhi Wang
2026-09-27 13:46 ` [PATCH v2 9/9] gpu: nova-core: gsp: add `rpc` to RPC message send/receive methods Alexandre Courbot
2026-09-28 5:32 ` Eliot Courtney
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=DLQP0I37RZTD.4C52AA74ID18@nvidia.com \
--to=ecourtney@nvidia.com \
--cc=acourbot@nvidia.com \
--cc=airlied@gmail.com \
--cc=aliceryhl@google.com \
--cc=apopple@nvidia.com \
--cc=dakr@kernel.org \
--cc=dri-devel-bounces@lists.freedesktop.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=gary@garyguo.net \
--cc=jhubbard@nvidia.com \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=nova-gpu@lists.linux.dev \
--cc=rust-for-linux@vger.kernel.org \
--cc=simona@ffwll.ch \
--cc=ttabi@nvidia.com \
--cc=zhiw@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®