From: "Alexandre Courbot" <acourbot@nvidia.com>
To: "Alistair Popple" <apopple@nvidia.com>,
"Benno Lossin" <lossin@kernel.org>,
<rust-for-linux@vger.kernel.org>,
<dri-devel@lists.freedesktop.org>, <dakr@kernel.org>,
<acourbot@nvidia.com>
Cc: "Miguel Ojeda" <ojeda@kernel.org>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Boqun Feng" <boqun.feng@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"Trevor Gross" <tmgross@umich.edu>,
"David Airlie" <airlied@gmail.com>,
"Simona Vetter" <simona@ffwll.ch>,
"Maarten Lankhorst" <maarten.lankhorst@linux.intel.com>,
"Maxime Ripard" <mripard@kernel.org>,
"Thomas Zimmermann" <tzimmermann@suse.de>,
"John Hubbard" <jhubbard@nvidia.com>,
"Joel Fernandes" <joelagnelf@nvidia.com>,
"Timur Tabi" <ttabi@nvidia.com>,
linux-kernel@vger.kernel.org, nouveau@lists.freedesktop.org
Subject: Re: [PATCH v3 08/13] gpu: nova-core: Add bindings and accessors for GspSystemInfo
Date: Thu, 02 Oct 2025 22:49:03 +0900 [thread overview]
Message-ID: <DD7VU4239GS2.2MKVFPBFEY1R4@nvidia.com> (raw)
In-Reply-To: <20250930131648.411720-9-apopple@nvidia.com>
Hi Alistair, (+Benno as this concerns the `init!` macros)
On Tue Sep 30, 2025 at 10:16 PM JST, Alistair Popple wrote:
> Adds bindings and an in-place initialiser for the GspSystemInfo struct.
>
> Signed-off-by: Alistair Popple <apopple@nvidia.com>
>
> ---
>
> It would be good to move to using the `init!` macros at some point, but
> I couldn't figure out how to make that work to initialise an enum rather
> than a struct as is required for the transparent representation.
Indeed we have to jump through a few (minor) hoops.
First the `init!` macros do not seem to support tuple structs. They
match a `{` after the type name, which is not present in
`GspSystemInfo`. By turning it into a regular struct with a single
field, we can overcome this, and it doesn't affect the layout the
`#[repr(transparent)]` can still be used.
Then, due to a limitation with declarative macros, `init!` interprets
`::` as a separator for generic arguments, so `bindings::GspSystemInfo`
also doesn't parse. Here the trick is to use a local type alias.
After overcoming these two, I have been able to make
`GspSystemInfo::init` return an in-place initializer. It is then a
matter of changing `send_gsp_command` to accept it - please apply the
following patch on top of your series for an illustration of how it can
be done.
Note that I have added a new generic argument for the error returned by
the `Init` - this is to let us also use infallible initializers
transparently. The cool thing is that callers don't need to specify any
generic argument since they can be inferred automatically.
diff --git a/drivers/gpu/nova-core/gsp/cmdq.rs b/drivers/gpu/nova-core/gsp/cmdq.rs
index 5580eaf52f7b..0709153f9dc9 100644
--- a/drivers/gpu/nova-core/gsp/cmdq.rs
+++ b/drivers/gpu/nova-core/gsp/cmdq.rs
@@ -247,12 +247,20 @@ fn notify_gsp(bar: &Bar0) {
NV_PGSP_QUEUE_HEAD::default().set_address(0).write(bar);
}
- pub(crate) fn send_gsp_command<M: CommandToGsp>(
+ pub(crate) fn send_gsp_command<M, E>(
&mut self,
bar: &Bar0,
payload_size: usize,
- init: impl FnOnce(&mut M, SBuffer<core::array::IntoIter<&mut [u8], 2>>) -> Result,
- ) -> Result {
+ init: impl Init<M, E>,
+ init_sbuffer: impl FnOnce(SBuffer<core::array::IntoIter<&mut [u8], 2>>) -> Result,
+ ) -> Result
+ where
+ M: CommandToGsp,
+ // This allows all error types, including `Infallible`, to be used with `init`. Without
+ // this we cannot use regular stack objects as `init` since their `Init` implementation
+ // does not return any error.
+ Error: From<E>,
+ {
// TODO: a method that extracts the regions for a given command?
// ... and another that reduces the region to a given number of bytes!
let driver_area = self.gsp_mem.driver_write_area();
@@ -264,7 +272,7 @@ pub(crate) fn send_gsp_command<M: CommandToGsp>(
return Err(EAGAIN);
}
- let (msg_header, cmd, payload_1, payload_2) = {
+ let (msg_header, cmd_ptr, payload_1, payload_2) = {
#[allow(clippy::incompatible_msrv)]
let (msg_header_slice, slice_1) = driver_area
.0
@@ -272,7 +280,6 @@ pub(crate) fn send_gsp_command<M: CommandToGsp>(
.split_at_mut(size_of::<GspMsgElement>());
let msg_header = GspMsgElement::from_bytes_mut(msg_header_slice).ok_or(EINVAL)?;
let (cmd_slice, payload_1) = slice_1.split_at_mut(size_of::<M>());
- let cmd = M::from_bytes_mut(cmd_slice).ok_or(EINVAL)?;
#[allow(clippy::incompatible_msrv)]
let payload_2 = driver_area.1.as_flattened_mut();
// TODO: Replace this workaround to cut the payload size.
@@ -283,11 +290,22 @@ pub(crate) fn send_gsp_command<M: CommandToGsp>(
None => (&mut payload_1[..payload_size], payload_2),
};
- (msg_header, cmd, payload_1, payload_2)
+ (
+ msg_header,
+ cmd_slice.as_mut_ptr().cast(),
+ payload_1,
+ payload_2,
+ )
+ };
+
+ let cmd = unsafe {
+ init.__init(cmd_ptr)?;
+ // Convert the pointer backto a reference for checksum.
+ &mut *cmd_ptr
};
let sbuffer = SBuffer::new_writer([&mut payload_1[..], &mut payload_2[..]]);
- init(cmd, sbuffer)?;
+ init_sbuffer(sbuffer)?;
*msg_header =
GspMsgElement::new(self.seq, size_of::<M>() + payload_size, M::FUNCTION as u32);
diff --git a/drivers/gpu/nova-core/gsp/commands.rs b/drivers/gpu/nova-core/gsp/commands.rs
index 69df8d4be353..6f1be9078853 100644
--- a/drivers/gpu/nova-core/gsp/commands.rs
+++ b/drivers/gpu/nova-core/gsp/commands.rs
@@ -79,10 +79,12 @@ pub(crate) fn build_registry(cmdq: &mut Cmdq, bar: &Bar0) -> Result {
],
};
- cmdq.send_gsp_command::<PackedRegistryTable>(bar, registry.size(), |table, sbuffer| {
- *table = PackedRegistryTable::new(GSP_REGISTRY_NUM_ENTRIES as u32, registry.size() as u32);
- registry.write_payload(sbuffer)
- })
+ cmdq.send_gsp_command(
+ bar,
+ registry.size(),
+ PackedRegistryTable::new(GSP_REGISTRY_NUM_ENTRIES as u32, registry.size() as u32),
+ |sbuffer| registry.write_payload(sbuffer),
+ )
}
impl CommandToGsp for GspSystemInfo {
@@ -95,7 +97,7 @@ pub(crate) fn set_system_info(
bar: &Bar0,
) -> Result {
build_assert!(size_of::<GspSystemInfo>() < GSP_PAGE_SIZE);
- cmdq.send_gsp_command::<GspSystemInfo>(bar, 0, |info, _| GspSystemInfo::init(info, dev))?;
+ cmdq.send_gsp_command(bar, 0, GspSystemInfo::init(dev), |_| Ok(()))?;
Ok(())
}
diff --git a/drivers/gpu/nova-core/gsp/fw/commands.rs b/drivers/gpu/nova-core/gsp/fw/commands.rs
index 83c2b017c4cb..e69be2f422f2 100644
--- a/drivers/gpu/nova-core/gsp/fw/commands.rs
+++ b/drivers/gpu/nova-core/gsp/fw/commands.rs
@@ -4,31 +4,50 @@
use kernel::transmute::{AsBytes, FromBytes};
use kernel::{device, pci};
+// Ideally we would derive this for all our bindings, using the same technique as
+// https://lore.kernel.org/rust-for-linux/20250814093046.2071971-3-lossin@kernel.org/
+unsafe impl Zeroable for bindings::GspSystemInfo {}
+
#[repr(transparent)]
-pub(crate) struct GspSystemInfo(bindings::GspSystemInfo);
+pub(crate) struct GspSystemInfo {
+ // `try_init!` doesn't seem to work with tuple structs. Work around this by declaring a regular
+ // field, which comes down to exactly the same.
+ inner: bindings::GspSystemInfo,
+}
impl GspSystemInfo {
- pub(crate) fn init(&mut self, dev: &pci::Device<device::Bound>) -> Result {
- self.0.gpuPhysAddr = dev.resource_start(0)?;
- self.0.gpuPhysFbAddr = dev.resource_start(1)?;
- self.0.gpuPhysInstAddr = dev.resource_start(3)?;
- self.0.nvDomainBusDeviceFunc = u64::from(dev.dev_id());
+ #[allow(non_snake_case)]
+ pub(crate) fn init<'a>(dev: &'a pci::Device<device::Bound>) -> impl Init<Self, Error> + 'a {
+ // `try_init!` interprets `::` as a separator for generics, use a type alias to remove
+ // them.
+ type InnerGspSystemInfo = bindings::GspSystemInfo;
- // Using TASK_SIZE in r535_gsp_rpc_set_system_info() seems wrong because
- // TASK_SIZE is per-task. That's probably a design issue in GSP-RM though.
- self.0.maxUserVa = (1 << 47) - 4096;
- self.0.pciConfigMirrorBase = 0x088000;
- self.0.pciConfigMirrorSize = 0x001000;
+ // Initializer for the bindings type.
+ let init_inner = try_init!(InnerGspSystemInfo {
+ gpuPhysAddr: dev.resource_start(0)?,
+ gpuPhysFbAddr: dev.resource_start(1)?,
+ gpuPhysInstAddr: dev.resource_start(3)?,
+ nvDomainBusDeviceFunc: u64::from(dev.dev_id()),
- self.0.PCIDeviceID =
- (u32::from(dev.device_id()) << 16) | u32::from(dev.vendor_id().as_raw());
- self.0.PCISubDeviceID =
- (u32::from(dev.subsystem_device_id()) << 16) | u32::from(dev.subsystem_vendor_id());
- self.0.PCIRevisionID = u32::from(dev.revision_id());
- self.0.bIsPrimary = 0;
- self.0.bPreserveVideoMemoryAllocations = 0;
+ // Using TASK_SIZE in r535_gsp_rpc_set_system_info() seems wrong because
+ // TASK_SIZE is per-task. That's probably a design issue in GSP-RM though.
+ maxUserVa: (1 << 47) - 4096,
+ pciConfigMirrorBase: 0x088000,
+ pciConfigMirrorSize: 0x001000,
- Ok(())
+ PCIDeviceID: (u32::from(dev.device_id()) << 16) | u32::from(dev.vendor_id().as_raw()),
+ PCISubDeviceID: (u32::from(dev.subsystem_device_id()) << 16)
+ | u32::from(dev.subsystem_vendor_id()),
+ PCIRevisionID: u32::from(dev.revision_id()),
+ bIsPrimary: 0,
+ bPreserveVideoMemoryAllocations: 0,
+ ..Zeroable::init_zeroed()
+ });
+
+ // Final initializer for our type.
+ try_init!(GspSystemInfo {
+ inner <- init_inner,
+ })
}
}
next prev parent reply other threads:[~2025-10-02 13:49 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-30 13:16 [PATCH v3 00/13] gpu: nova-core: Boot GSP to RISC-V active Alistair Popple
2025-09-30 13:16 ` [PATCH v3 01/13] gpu: nova-core: Set correct DMA mask Alistair Popple
2025-09-30 13:29 ` Danilo Krummrich
2025-10-01 1:42 ` Alistair Popple
2025-10-01 1:53 ` John Hubbard
2025-09-30 13:16 ` [PATCH v3 02/13] gpu: nova-core: Create initial Gsp Alistair Popple
2025-09-30 13:16 ` [PATCH v3 03/13] gpu: nova-core: gsp: Create wpr metadata Alistair Popple
2025-09-30 13:16 ` [PATCH v3 04/13] gpu: nova-core: Add a slice-buffer (sbuffer) datastructure Alistair Popple
2025-09-30 13:16 ` [PATCH v3 05/13] gpu: nova-core: Add GSP command queue bindings Alistair Popple
2025-09-30 13:33 ` Danilo Krummrich
2025-09-30 13:16 ` [PATCH v3 06/13] gpu: nova-core: gsp: Add GSP command queue handling Alistair Popple
2025-09-30 13:16 ` [PATCH v3 07/13] gpu: nova-core: gsp: Create rmargs Alistair Popple
2025-09-30 13:16 ` [PATCH v3 08/13] gpu: nova-core: Add bindings and accessors for GspSystemInfo Alistair Popple
2025-10-02 13:49 ` Alexandre Courbot [this message]
2025-10-02 23:38 ` Alistair Popple
2025-10-03 0:56 ` Alexandre Courbot
2025-10-03 16:34 ` Benno Lossin
2025-10-03 17:25 ` Janne Grunau
2025-10-03 17:59 ` Benno Lossin
2025-09-30 13:16 ` [PATCH v3 09/13] gpu: nova-core: Add bindings for the GSP RM registry tables Alistair Popple
2025-09-30 13:16 ` [PATCH v3 10/13] gpu: nova-core: gsp: Create RM registry and sysinfo commands Alistair Popple
2025-10-01 16:46 ` Timur Tabi
2025-09-30 13:16 ` [PATCH v3 11/13] nova-core: falcon: Add support to check if RISC-V is active Alistair Popple
2025-09-30 17:17 ` Timur Tabi
2025-09-30 13:16 ` [PATCH v3 12/13] nova-core: falcon: Add support to write firmware version Alistair Popple
2025-09-30 13:16 ` [PATCH v3 13/13] nova-core: gsp: Boot GSP Alistair Popple
2025-09-30 17:28 ` Timur Tabi
2025-09-30 13:26 ` [PATCH v3 00/13] gpu: nova-core: Boot GSP to RISC-V active Danilo Krummrich
2025-10-01 2:02 ` Alistair Popple
2025-10-01 2:02 ` John Hubbard
2025-10-01 5:54 ` Alistair Popple
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=DD7VU4239GS2.2MKVFPBFEY1R4@nvidia.com \
--to=acourbot@nvidia.com \
--cc=a.hindborg@kernel.org \
--cc=airlied@gmail.com \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=apopple@nvidia.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=dakr@kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=gary@garyguo.net \
--cc=jhubbard@nvidia.com \
--cc=joelagnelf@nvidia.com \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=maarten.lankhorst@linux.intel.com \
--cc=mripard@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=ttabi@nvidia.com \
--cc=tzimmermann@suse.de \
/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