Re: [PATCH 14/27] gpu: nova-core: add GMC API message types

Zhi Wang <[email protected]>
Newsgroups dev.linux.lists.nova-gpu,org.kernel.vger.linux-kernel
Message-ID <20260820135352.6e387428@inno-dell>
On Tue, 18 Aug 2026 20:52:07 -0700
John Hubbard <[email protected]> wrote:

snip

> +/// GMC API message header.
> +///
> +/// Matches the `GMCAPI_HEADER` struct from Open RM. The `command`
> field carries +/// flags in the high byte and a 24-bit command ID in
> the low bits. `size` is the +/// payload size for both requests and
> responses, while the union at offset 16 +/// carries the maximum
> response size for requests and the status for responses. +#[repr(C)]
> +#[derive(Zeroable)]
> +pub(crate) struct GmcApiHeader {
> +    /// GMC command identifier with flags in the high byte.
> +    pub(crate) command: u32,
> +    /// Payload size in bytes.
> +    pub(crate) size: u32,
> +    /// Sequence number for matching requests to responses.
> +    pub(crate) sequence: u64,
> +    /// Request: maximum response size. Response: `NV_STATUS` code.
> +    pub(crate) max_resp_or_status: u32,
> +    reserved: [u32; 5],
> +}
> +
> +static_assert!(size_of::<GmcApiHeader>() == 40);
> +

Should we use the GMCAPI_HEADER in the r000 bindings?

Z.

> +// SAFETY: All fields are integer types with no uninitialized
> padding bytes. +unsafe impl AsBytes for GmcApiHeader {}
> +
> +// SAFETY: All fields are integer types for which all bit patterns
> are valid. +unsafe impl FromBytes for GmcApiHeader {}
> +
> +/// Header for an unencrypted GMC API message in the GSP command
> queue. +///
> +/// The fields before `gmc` match `GSP_MSG_QUEUE_ELEMENT` through its
> +/// `noEncryption` union member. `gmc` occupies the start of that
> member's +/// flexible payload array, and the GMC command payload
> follows this structure. +#[repr(C)]
> +pub(crate) struct GspGmcMsgElement {
> +    mctp_magic: u32,
> +    mctp_payload_size: u32,
> +    mctp_header: MctpHeader,
> +    nvdm_header: NvdmHeader,
> +    nvdm_payload_size: u32,
> +    reserved: u32,
> +    pub(crate) gmc: GmcApiHeader,
> +}
> +
> +static_assert!(
> +    core::mem::offset_of!(GspGmcMsgElement, mctp_magic)
> +        == core::mem::offset_of!(r000_00::GSP_MSG_QUEUE_ELEMENT,
> mctpMagic) +);
> +static_assert!(
> +    core::mem::offset_of!(GspGmcMsgElement, mctp_payload_size)
> +        == core::mem::offset_of!(r000_00::GSP_MSG_QUEUE_ELEMENT,
> mctpPayloadSize) +);
> +static_assert!(
> +    core::mem::offset_of!(GspGmcMsgElement, mctp_header)
> +        == core::mem::offset_of!(r000_00::GSP_MSG_QUEUE_ELEMENT,
> mctpHeader) +);
> +static_assert!(
> +    core::mem::offset_of!(GspGmcMsgElement, nvdm_header)
> +        == core::mem::offset_of!(r000_00::GSP_MSG_QUEUE_ELEMENT,
> nvdmHeader) +);
> +
> +#[expect(dead_code)]
> +impl GspGmcMsgElement {
> +    /// Creates a new GMC message element.
> +    ///
> +    /// `payload_size` is the size of the command payload following
> this header.
> +    /// `command_id` is the GMC command identifier.
> +    /// `sequence` is the sequence number for request/response
> matching.
> +    /// `max_response_size` is the maximum expected response payload
> size.
> +    pub(crate) fn init(
> +        command_id: u32,
> +        sequence: u64,
> +        payload_size: usize,
> +        max_response_size: u32,
> +    ) -> impl Init<Self, Error> {
> +        try_init!(GspGmcMsgElement {
> +            mctp_magic: MCTP_MAGIC,
> +            // Despite the name, this counts the element header as
> well as the payload.
> +            mctp_payload_size: size_of::<Self>()
> +                .checked_add(payload_size)
> +                .ok_or(EOVERFLOW)?
> +                .try_into()
> +                .map_err(|_| EOVERFLOW)?,
> +            mctp_header: MctpHeader::single_packet(),
> +            nvdm_header: NvdmHeader::new(NvdmType::GmcApi),
> +            nvdm_payload_size: size_of::<GmcApiHeader>()
> +                .checked_add(payload_size)
> +                .ok_or(EOVERFLOW)?
> +                .try_into()
> +                .map_err(|_| EOVERFLOW)?,
> +            reserved: 0u32,
> +            gmc: GmcApiHeader {
> +                command: command_id,
> +                size: payload_size.try_into().map_err(|_|
> EOVERFLOW)?,
> +                sequence,
> +                max_resp_or_status: max_response_size,
> +                reserved: [0; 5],
> +            },
> +        })
> +    }
> +
> +    /// Returns the total length of the message, transport and GMC
> headers included.
> +    pub(crate) fn length(&self) -> usize {
> +        num::u32_as_usize(self.mctp_payload_size)
> +    }
> +
> +    /// Returns the number of elements (i.e. memory pages) used by
> this message.
> +    pub(crate) fn element_count(&self) -> u32 {
> +        self.mctp_payload_size
> +            .div_ceil(num::usize_into_u32::<GSP_PAGE_SIZE>())
> +    }
> +}
> +
> +// SAFETY: All fields are integer types with no uninitialized
> padding bytes. +unsafe impl AsBytes for GspGmcMsgElement {}
> +
> +// SAFETY: All fields are integer types for which all bit patterns
> are valid. +unsafe impl FromBytes for GspGmcMsgElement {}
> +
>  /// Arguments for GSP startup.
>  #[repr(transparent)]
>  #[derive(Zeroable)]
> diff --git a/drivers/gpu/nova-core/mctp.rs
> b/drivers/gpu/nova-core/mctp.rs index 03546213da28..0ae88bef2a05
> 100644 --- a/drivers/gpu/nova-core/mctp.rs
> +++ b/drivers/gpu/nova-core/mctp.rs
> @@ -28,6 +28,8 @@ pub(crate) enum NvdmType with TryFrom<Bounded<u32,
> 8>> { Cot = 0x14,
>          /// FSP command response.
>          FspResponse = 0x15,
> +        /// GMC API message (GSP command queue).
> +        GmcApi = 0x26,
>      }
>  }
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.