From: Eliot Courtney <ecourtney@nvidia.com>
To: Danilo Krummrich <dakr@kernel.org>,
Alice Ryhl <aliceryhl@google.com>,
Alexandre Courbot <acourbot@nvidia.com>,
David Airlie <airlied@gmail.com>,
Simona Vetter <simona@ffwll.ch>,
Benno Lossin <lossin@kernel.org>, Gary Guo <gary@garyguo.net>
Cc: nouveau@lists.freedesktop.org, dri-devel@lists.freedesktop.org,
linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org,
Eliot Courtney <ecourtney@nvidia.com>
Subject: [PATCH v2 2/4] gpu: nova-core: gsp: add sync and async command queue API to `Cmdq`
Date: Thu, 26 Feb 2026 23:50:24 +0900 [thread overview]
Message-ID: <20260226-cmdq-locking-v2-2-c7e16a6d5885@nvidia.com> (raw)
In-Reply-To: <20260226-cmdq-locking-v2-0-c7e16a6d5885@nvidia.com>
Add sync and async command queue API and the type infrastructure to know
what reply is expected from each `CommandToGsp`.
Use a marker type `NoReply` which does not implement `MessageFromGsp` to
mark async commands which don't expect a response.
This prepares for adding locking to the queue.
Signed-off-by: Eliot Courtney <ecourtney@nvidia.com>
---
drivers/gpu/nova-core/gsp/boot.rs | 5 ++--
drivers/gpu/nova-core/gsp/cmdq.rs | 54 ++++++++++++++++++++++++++++++++++-
drivers/gpu/nova-core/gsp/commands.rs | 19 ++++++------
3 files changed, 65 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/nova-core/gsp/boot.rs b/drivers/gpu/nova-core/gsp/boot.rs
index c56029f444cb..55899eba75db 100644
--- a/drivers/gpu/nova-core/gsp/boot.rs
+++ b/drivers/gpu/nova-core/gsp/boot.rs
@@ -160,8 +160,9 @@ pub(crate) fn boot(
dma_write!(wpr_meta[0] = GspFwWprMeta::new(&gsp_fw, &fb_layout))?;
self.cmdq
- .send_command(bar, commands::SetSystemInfo::new(pdev))?;
- self.cmdq.send_command(bar, commands::SetRegistry::new())?;
+ .send_async_command(bar, commands::SetSystemInfo::new(pdev))?;
+ self.cmdq
+ .send_async_command(bar, commands::SetRegistry::new())?;
gsp_falcon.reset(bar)?;
let libos_handle = self.libos.dma_handle();
diff --git a/drivers/gpu/nova-core/gsp/cmdq.rs b/drivers/gpu/nova-core/gsp/cmdq.rs
index a3e039117120..daf3e1d153d4 100644
--- a/drivers/gpu/nova-core/gsp/cmdq.rs
+++ b/drivers/gpu/nova-core/gsp/cmdq.rs
@@ -48,6 +48,10 @@
sbuffer::SBufferIter, //
};
+/// Marker type representing the absence of a reply for a command. This does not implement
+/// `MessageFromGsp`.
+pub(crate) struct NoReply;
+
/// Trait implemented by types representing a command to send to the GSP.
///
/// The main purpose of this trait is to provide [`Cmdq::send_command`] with the information it
@@ -66,6 +70,9 @@ pub(crate) trait CommandToGsp {
/// Type generated by [`CommandToGsp::init`], to be written into the command queue buffer.
type Command: FromBytes + AsBytes;
+ /// Type of the reply expected from the GSP, or [`NoReply`] for async commands.
+ type Reply;
+
/// Error type returned by [`CommandToGsp::init`].
type InitError;
@@ -604,7 +611,7 @@ fn send_single_command<M>(&mut self, bar: &Bar0, command: M) -> Result
/// written to by its [`CommandToGsp::init_variable_payload`] method.
///
/// Error codes returned by the command initializers are propagated as-is.
- pub(crate) fn send_command<M>(&mut self, bar: &Bar0, command: M) -> Result
+ fn send_command<M>(&mut self, bar: &Bar0, command: M) -> Result
where
M: CommandToGsp,
Error: From<M::InitError>,
@@ -626,6 +633,51 @@ pub(crate) fn send_command<M>(&mut self, bar: &Bar0, command: M) -> Result
Ok(())
}
+ /// Sends `command` to the GSP and waits for the reply.
+ ///
+ /// # Errors
+ ///
+ /// - `ETIMEDOUT` if space does not become available to send the command, or if the reply is
+ /// not received 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 and reply initializers are propagated as-is.
+ pub(crate) fn send_sync_command<M>(&mut self, bar: &Bar0, command: M) -> Result<M::Reply>
+ where
+ M: CommandToGsp,
+ M::Reply: MessageFromGsp,
+ Error: From<M::InitError>,
+ Error: From<<M::Reply as MessageFromGsp>::InitError>,
+ {
+ self.send_command(bar, command)?;
+
+ loop {
+ match self.receive_msg::<M::Reply>(Delta::from_secs(10)) {
+ Ok(reply) => break Ok(reply),
+ Err(ERANGE) => continue,
+ Err(e) => break Err(e),
+ }
+ }
+ }
+
+ /// Sends `command` to the GSP without waiting for a reply.
+ ///
+ /// # Errors
+ ///
+ /// - `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.
+ pub(crate) fn send_async_command<M>(&mut self, bar: &Bar0, command: M) -> Result
+ where
+ M: CommandToGsp<Reply = NoReply>,
+ Error: From<M::InitError>,
+ {
+ self.send_command(bar, command)
+ }
+
/// 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/commands.rs b/drivers/gpu/nova-core/gsp/commands.rs
index 74f875755e53..47ca31611927 100644
--- a/drivers/gpu/nova-core/gsp/commands.rs
+++ b/drivers/gpu/nova-core/gsp/commands.rs
@@ -26,7 +26,8 @@
command_size,
Cmdq,
CommandToGsp,
- MessageFromGsp, //
+ MessageFromGsp,
+ NoReply, //
},
fw::{
commands::*,
@@ -53,6 +54,7 @@ pub(crate) fn new(pdev: &'a pci::Device<device::Bound>) -> Self {
impl<'a> CommandToGsp for SetSystemInfo<'a> {
const FUNCTION: MsgFunction = MsgFunction::GspSetSystemInfo;
type Command = GspSetSystemInfo;
+ type Reply = NoReply;
type InitError = Error;
fn init(&self) -> impl Init<Self::Command, Self::InitError> {
@@ -104,6 +106,7 @@ pub(crate) fn new() -> Self {
impl CommandToGsp for SetRegistry {
const FUNCTION: MsgFunction = MsgFunction::SetRegistry;
type Command = PackedRegistryTable;
+ type Reply = NoReply;
type InitError = Infallible;
fn init(&self) -> impl Init<Self::Command, Self::InitError> {
@@ -183,6 +186,7 @@ pub(crate) fn wait_gsp_init_done(cmdq: &mut Cmdq) -> Result {
impl CommandToGsp for GetGspStaticInfo {
const FUNCTION: MsgFunction = MsgFunction::GetGspStaticInfo;
type Command = GspStaticConfigInfo;
+ type Reply = GetGspStaticInfoReply;
type InitError = Infallible;
fn init(&self) -> impl Init<Self::Command, Self::InitError> {
@@ -236,15 +240,7 @@ pub(crate) fn gpu_name(&self) -> core::result::Result<&str, GpuNameError> {
/// Send the [`GetGspInfo`] command and awaits for its reply.
pub(crate) fn get_gsp_info(cmdq: &mut Cmdq, bar: &Bar0) -> Result<GetGspStaticInfoReply> {
- cmdq.send_command(bar, GetGspStaticInfo)?;
-
- loop {
- match cmdq.receive_msg::<GetGspStaticInfoReply>(Delta::from_secs(5)) {
- Ok(info) => return Ok(info),
- Err(ERANGE) => continue,
- Err(e) => return Err(e),
- }
- }
+ cmdq.send_sync_command(bar, GetGspStaticInfo)
}
/// The `ContinuationRecord` command.
@@ -262,6 +258,7 @@ pub(crate) fn new(data: &'a [u8]) -> Self {
impl<'a> CommandToGsp for ContinuationRecord<'a> {
const FUNCTION: MsgFunction = MsgFunction::ContinuationRecord;
type Command = ();
+ type Reply = NoReply;
type InitError = Infallible;
fn init(&self) -> impl Init<Self::Command, Self::InitError> {
@@ -356,6 +353,7 @@ pub(crate) enum SplitCommand<'a, C: CommandToGsp> {
impl<'a, C: CommandToGsp> CommandToGsp for SplitCommand<'a, C> {
const FUNCTION: MsgFunction = C::FUNCTION;
type Command = C::Command;
+ type Reply = C::Reply;
type InitError = C::InitError;
fn init(&self) -> impl Init<Self::Command, Self::InitError> {
@@ -412,6 +410,7 @@ fn new(len: usize) -> Result<Self> {
impl CommandToGsp for TestPayload {
const FUNCTION: MsgFunction = MsgFunction::Nop;
type Command = ();
+ type Reply = NoReply;
type InitError = Infallible;
fn init(&self) -> impl Init<Self::Command, Self::InitError> {
--
2.53.0
next prev parent reply other threads:[~2026-02-26 14:54 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-26 14:50 [PATCH v2 0/4] gpu: nova-core: gsp: add locking to Cmdq Eliot Courtney
2026-02-26 14:50 ` [PATCH v2 1/4] gpu: nova-core: gsp: fix stale doc comments on command queue methods Eliot Courtney
2026-02-26 14:50 ` Eliot Courtney [this message]
2026-02-28 6:11 ` [PATCH v2 2/4] gpu: nova-core: gsp: add sync and async command queue API to `Cmdq` John Hubbard
2026-03-02 2:22 ` Eliot Courtney
2026-03-02 2:44 ` John Hubbard
2026-03-02 3:03 ` Alexandre Courbot
2026-03-02 3:08 ` John Hubbard
2026-03-02 4:42 ` Eliot Courtney
2026-03-02 5:31 ` Alexandre Courbot
2026-03-02 17:26 ` Gary Guo
2026-03-02 12:28 ` Danilo Krummrich
2026-03-02 18:03 ` John Hubbard
2026-03-03 2:46 ` Eliot Courtney
2026-02-26 14:50 ` [PATCH v2 3/4] gpu: nova-core: gsp: make `Cmdq` a pinned type Eliot Courtney
2026-03-02 17:33 ` Gary Guo
2026-03-03 3:42 ` Eliot Courtney
2026-02-26 14:50 ` [PATCH v2 4/4] gpu: nova-core: gsp: add mutex locking to Cmdq Eliot Courtney
2026-03-02 17:36 ` Gary Guo
2026-03-03 3:47 ` Eliot Courtney
2026-03-03 7:58 ` Alexandre Courbot
2026-02-26 18:48 ` [PATCH v2 0/4] gpu: nova-core: gsp: add " Zhi Wang
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=20260226-cmdq-locking-v2-2-c7e16a6d5885@nvidia.com \
--to=ecourtney@nvidia.com \
--cc=acourbot@nvidia.com \
--cc=airlied@gmail.com \
--cc=aliceryhl@google.com \
--cc=dakr@kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=gary@garyguo.net \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=nouveau@lists.freedesktop.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=simona@ffwll.ch \
/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