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>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Boqun Feng" <boqun@kernel.org>, "Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <lossin@kernel.org>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Trevor Gross" <tmgross@umich.edu>
Cc: Zhi Wang <zhiw@nvidia.com>, Alistair Popple <apopple@nvidia.com>,
Joel Fernandes <joelagnelf@nvidia.com>,
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 v5 2/9] gpu: nova-core: gsp: add mechanism to wait for space on command queue
Date: Wed, 04 Mar 2026 10:42:18 +0900 [thread overview]
Message-ID: <20260304-cmdq-continuation-v5-2-3f19d759ed93@nvidia.com> (raw)
In-Reply-To: <20260304-cmdq-continuation-v5-0-3f19d759ed93@nvidia.com>
Add a timeout to `allocate_command` which waits for space on the GSP
command queue. It uses a similar timeout to nouveau.
This lets `send_command` wait for space to free up in the command queue.
This is required to support continuation records which can fill up the
queue.
Tested-by: Zhi Wang <zhiw@nvidia.com>
Signed-off-by: Eliot Courtney <ecourtney@nvidia.com>
---
drivers/gpu/nova-core/gsp/cmdq.rs | 42 ++++++++++++++++++++++++++++-----------
1 file changed, 30 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/nova-core/gsp/cmdq.rs b/drivers/gpu/nova-core/gsp/cmdq.rs
index 87dbbd6d1be9..5cb845bae123 100644
--- a/drivers/gpu/nova-core/gsp/cmdq.rs
+++ b/drivers/gpu/nova-core/gsp/cmdq.rs
@@ -250,6 +250,19 @@ fn new(dev: &device::Device<device::Bound>) -> Result<Self> {
}
}
+ /// Returns the size of the region of the CPU message queue that the driver is currently allowed
+ /// to write to, in bytes.
+ fn driver_write_area_size(&self) -> usize {
+ let tx = self.cpu_write_ptr();
+ let rx = self.gsp_read_ptr();
+
+ // `rx` and `tx` are both in `0..MSGQ_NUM_PAGES` per the invariants of `gsp_read_ptr` and
+ // `cpu_write_ptr`. The minimum value case is where `rx == 0` and `tx == MSGQ_NUM_PAGES -
+ // 1`, which gives `0 + MSGQ_NUM_PAGES - (MSGQ_NUM_PAGES - 1) - 1 == 0`.
+ let slots = (rx + MSGQ_NUM_PAGES - tx - 1) % MSGQ_NUM_PAGES;
+ num::u32_as_usize(slots) * GSP_PAGE_SIZE
+ }
+
/// Returns the region of the GSP message queue that the driver is currently allowed to read
/// from.
///
@@ -281,15 +294,22 @@ fn new(dev: &device::Device<device::Bound>) -> Result<Self> {
}
/// Allocates a region on the command queue that is large enough to send a command of `size`
- /// bytes.
+ /// bytes, waiting for space to become available based on the provided timeout.
///
/// This returns a [`GspCommand`] ready to be written to by the caller.
///
/// # Errors
///
- /// - `EAGAIN` if the driver area is too small to hold the requested command.
+ /// - `ETIMEDOUT` if space does not become available within the timeout.
/// - `EIO` if the command header is not properly aligned.
- fn allocate_command(&mut self, size: usize) -> Result<GspCommand<'_>> {
+ fn allocate_command(&mut self, size: usize, timeout: Delta) -> Result<GspCommand<'_>> {
+ read_poll_timeout(
+ || Ok(self.driver_write_area_size()),
+ |available_bytes| *available_bytes >= size_of::<GspMsgElement>() + size,
+ Delta::ZERO,
+ timeout,
+ )?;
+
// Get the current writable area as an array of bytes.
let (slice_1, slice_2) = {
let (slice_1, slice_2) = self.driver_write_area();
@@ -298,13 +318,6 @@ fn allocate_command(&mut self, size: usize) -> Result<GspCommand<'_>> {
(slice_1.as_flattened_mut(), slice_2.as_flattened_mut())
};
- // If the GSP is still processing previous messages the shared region
- // may be full in which case we will have to retry once the GSP has
- // processed the existing commands.
- if size_of::<GspMsgElement>() + size > slice_1.len() + slice_2.len() {
- return Err(EAGAIN);
- }
-
// Extract area for the `GspMsgElement`.
let (header, slice_1) = GspMsgElement::from_bytes_mut_prefix(slice_1).ok_or(EIO)?;
@@ -462,6 +475,9 @@ impl Cmdq {
/// Number of page table entries for the GSP shared region.
pub(crate) const NUM_PTES: usize = size_of::<GspMem>() >> GSP_PAGE_SHIFT;
+ /// Timeout for waiting for space on the command queue.
+ const ALLOCATE_TIMEOUT: Delta = Delta::from_secs(1);
+
/// Creates a new command queue for `dev`.
pub(crate) fn new(dev: &device::Device<device::Bound>) -> Result<Cmdq> {
let gsp_mem = DmaGspMem::new(dev)?;
@@ -497,7 +513,7 @@ fn notify_gsp(bar: &Bar0) {
///
/// # Errors
///
- /// - `EAGAIN` if there was not enough space in the command queue to send the command.
+ /// - `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.
///
@@ -509,7 +525,9 @@ pub(crate) fn send_command<M>(&mut self, bar: &Bar0, command: M) -> Result
Error: From<M::InitError>,
{
let command_size = size_of::<M::Command>() + command.variable_payload_len();
- let dst = self.gsp_mem.allocate_command(command_size)?;
+ let dst = self
+ .gsp_mem
+ .allocate_command(command_size, Self::ALLOCATE_TIMEOUT)?;
// Extract area for the command itself.
let (cmd, payload_1) = M::Command::from_bytes_mut_prefix(dst.contents.0).ok_or(EIO)?;
--
2.53.0
WARNING: multiple messages have this Message-ID (diff)
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>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Boqun Feng" <boqun@kernel.org>, "Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <lossin@kernel.org>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Trevor Gross" <tmgross@umich.edu>
Cc: Zhi Wang <zhiw@nvidia.com>, John Hubbard <jhubbard@nvidia.com>,
Alistair Popple <apopple@nvidia.com>,
Joel Fernandes <joelagnelf@nvidia.com>,
Timur Tabi <ttabi@nvidia.com>,
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 v5 2/9] gpu: nova-core: gsp: add mechanism to wait for space on command queue
Date: Wed, 04 Mar 2026 10:42:18 +0900 [thread overview]
Message-ID: <20260304-cmdq-continuation-v5-2-3f19d759ed93@nvidia.com> (raw)
In-Reply-To: <20260304-cmdq-continuation-v5-0-3f19d759ed93@nvidia.com>
Add a timeout to `allocate_command` which waits for space on the GSP
command queue. It uses a similar timeout to nouveau.
This lets `send_command` wait for space to free up in the command queue.
This is required to support continuation records which can fill up the
queue.
Tested-by: Zhi Wang <zhiw@nvidia.com>
Signed-off-by: Eliot Courtney <ecourtney@nvidia.com>
---
drivers/gpu/nova-core/gsp/cmdq.rs | 42 ++++++++++++++++++++++++++++-----------
1 file changed, 30 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/nova-core/gsp/cmdq.rs b/drivers/gpu/nova-core/gsp/cmdq.rs
index 87dbbd6d1be9..5cb845bae123 100644
--- a/drivers/gpu/nova-core/gsp/cmdq.rs
+++ b/drivers/gpu/nova-core/gsp/cmdq.rs
@@ -250,6 +250,19 @@ fn new(dev: &device::Device<device::Bound>) -> Result<Self> {
}
}
+ /// Returns the size of the region of the CPU message queue that the driver is currently allowed
+ /// to write to, in bytes.
+ fn driver_write_area_size(&self) -> usize {
+ let tx = self.cpu_write_ptr();
+ let rx = self.gsp_read_ptr();
+
+ // `rx` and `tx` are both in `0..MSGQ_NUM_PAGES` per the invariants of `gsp_read_ptr` and
+ // `cpu_write_ptr`. The minimum value case is where `rx == 0` and `tx == MSGQ_NUM_PAGES -
+ // 1`, which gives `0 + MSGQ_NUM_PAGES - (MSGQ_NUM_PAGES - 1) - 1 == 0`.
+ let slots = (rx + MSGQ_NUM_PAGES - tx - 1) % MSGQ_NUM_PAGES;
+ num::u32_as_usize(slots) * GSP_PAGE_SIZE
+ }
+
/// Returns the region of the GSP message queue that the driver is currently allowed to read
/// from.
///
@@ -281,15 +294,22 @@ fn new(dev: &device::Device<device::Bound>) -> Result<Self> {
}
/// Allocates a region on the command queue that is large enough to send a command of `size`
- /// bytes.
+ /// bytes, waiting for space to become available based on the provided timeout.
///
/// This returns a [`GspCommand`] ready to be written to by the caller.
///
/// # Errors
///
- /// - `EAGAIN` if the driver area is too small to hold the requested command.
+ /// - `ETIMEDOUT` if space does not become available within the timeout.
/// - `EIO` if the command header is not properly aligned.
- fn allocate_command(&mut self, size: usize) -> Result<GspCommand<'_>> {
+ fn allocate_command(&mut self, size: usize, timeout: Delta) -> Result<GspCommand<'_>> {
+ read_poll_timeout(
+ || Ok(self.driver_write_area_size()),
+ |available_bytes| *available_bytes >= size_of::<GspMsgElement>() + size,
+ Delta::ZERO,
+ timeout,
+ )?;
+
// Get the current writable area as an array of bytes.
let (slice_1, slice_2) = {
let (slice_1, slice_2) = self.driver_write_area();
@@ -298,13 +318,6 @@ fn allocate_command(&mut self, size: usize) -> Result<GspCommand<'_>> {
(slice_1.as_flattened_mut(), slice_2.as_flattened_mut())
};
- // If the GSP is still processing previous messages the shared region
- // may be full in which case we will have to retry once the GSP has
- // processed the existing commands.
- if size_of::<GspMsgElement>() + size > slice_1.len() + slice_2.len() {
- return Err(EAGAIN);
- }
-
// Extract area for the `GspMsgElement`.
let (header, slice_1) = GspMsgElement::from_bytes_mut_prefix(slice_1).ok_or(EIO)?;
@@ -462,6 +475,9 @@ impl Cmdq {
/// Number of page table entries for the GSP shared region.
pub(crate) const NUM_PTES: usize = size_of::<GspMem>() >> GSP_PAGE_SHIFT;
+ /// Timeout for waiting for space on the command queue.
+ const ALLOCATE_TIMEOUT: Delta = Delta::from_secs(1);
+
/// Creates a new command queue for `dev`.
pub(crate) fn new(dev: &device::Device<device::Bound>) -> Result<Cmdq> {
let gsp_mem = DmaGspMem::new(dev)?;
@@ -497,7 +513,7 @@ fn notify_gsp(bar: &Bar0) {
///
/// # Errors
///
- /// - `EAGAIN` if there was not enough space in the command queue to send the command.
+ /// - `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.
///
@@ -509,7 +525,9 @@ pub(crate) fn send_command<M>(&mut self, bar: &Bar0, command: M) -> Result
Error: From<M::InitError>,
{
let command_size = size_of::<M::Command>() + command.variable_payload_len();
- let dst = self.gsp_mem.allocate_command(command_size)?;
+ let dst = self
+ .gsp_mem
+ .allocate_command(command_size, Self::ALLOCATE_TIMEOUT)?;
// Extract area for the command itself.
let (cmd, payload_1) = M::Command::from_bytes_mut_prefix(dst.contents.0).ok_or(EIO)?;
--
2.53.0
next prev parent reply other threads:[~2026-03-04 1:43 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-04 1:42 [PATCH v5 0/9] gpu: nova-core: gsp: add continuation record support Eliot Courtney
2026-03-04 1:42 ` Eliot Courtney
2026-03-04 1:42 ` [PATCH v5 1/9] gpu: nova-core: gsp: sort `MsgFunction` variants alphabetically Eliot Courtney
2026-03-04 1:42 ` Eliot Courtney
2026-03-04 1:42 ` Eliot Courtney [this message]
2026-03-04 1:42 ` [PATCH v5 2/9] gpu: nova-core: gsp: add mechanism to wait for space on command queue Eliot Courtney
2026-03-04 11:39 ` Danilo Krummrich
2026-03-04 11:39 ` Danilo Krummrich
2026-03-05 7:37 ` Eliot Courtney
2026-03-05 7:37 ` Eliot Courtney
2026-03-05 7:50 ` John Hubbard
2026-03-05 7:50 ` John Hubbard
2026-03-05 8:01 ` Eliot Courtney
2026-03-05 8:01 ` Eliot Courtney
2026-03-05 10:38 ` Alexandre Courbot
2026-03-05 10:38 ` Alexandre Courbot
2026-03-05 11:16 ` Danilo Krummrich
2026-03-05 11:16 ` Danilo Krummrich
2026-03-06 0:48 ` Alexandre Courbot
2026-03-06 0:48 ` Alexandre Courbot
2026-03-06 1:46 ` Gary Guo
2026-03-06 1:46 ` Gary Guo
2026-03-06 11:03 ` Danilo Krummrich
2026-03-06 11:03 ` Danilo Krummrich
2026-03-06 5:21 ` Alexandre Courbot
2026-03-06 5:21 ` Alexandre Courbot
2026-03-04 1:42 ` [PATCH v5 3/9] rust: add EMSGSIZE error code Eliot Courtney
2026-03-04 1:42 ` Eliot Courtney
2026-03-04 1:42 ` [PATCH v5 4/9] gpu: nova-core: gsp: add checking oversized commands Eliot Courtney
2026-03-04 1:42 ` Eliot Courtney
2026-03-04 1:42 ` [PATCH v5 5/9] gpu: nova-core: gsp: clarify invariant on command queue Eliot Courtney
2026-03-04 1:42 ` Eliot Courtney
2026-03-04 1:42 ` [PATCH v5 6/9] gpu: nova-core: gsp: unconditionally call variable payload handling Eliot Courtney
2026-03-04 1:42 ` Eliot Courtney
2026-03-04 1:42 ` [PATCH v5 7/9] gpu: nova-core: gsp: add `size_in_bytes` helper to `CommandToGsp` Eliot Courtney
2026-03-04 1:42 ` Eliot Courtney
2026-03-04 2:53 ` Alexandre Courbot
2026-03-04 2:53 ` Alexandre Courbot
2026-03-04 3:10 ` Eliot Courtney
2026-03-04 3:10 ` Eliot Courtney
2026-03-04 1:42 ` [PATCH v5 8/9] gpu: nova-core: gsp: support large RPCs via continuation record Eliot Courtney
2026-03-04 1:42 ` Eliot Courtney
2026-03-04 1:42 ` [PATCH v5 9/9] gpu: nova-core: gsp: add tests for continuation records Eliot Courtney
2026-03-04 1:42 ` 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=20260304-cmdq-continuation-v5-2-3f19d759ed93@nvidia.com \
--to=ecourtney@nvidia.com \
--cc=a.hindborg@kernel.org \
--cc=acourbot@nvidia.com \
--cc=airlied@gmail.com \
--cc=aliceryhl@google.com \
--cc=apopple@nvidia.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun@kernel.org \
--cc=dakr@kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=gary@garyguo.net \
--cc=joelagnelf@nvidia.com \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=nouveau@lists.freedesktop.org \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=simona@ffwll.ch \
--cc=tmgross@umich.edu \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.