Re: [PATCH 17/27] gpu: nova-core: gsp: add GMC dispatch on receive

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

> The r000 boot path delivers the load-and-execute steps as GMC events
> keyed by command id, where the RPC path keys on a function code, so
> the boot loop needs its own dispatch.
snip

> +    fn receive_gmc_and_dispatch<R>(
> +        &mut self,
> +        timeout: Delta,
> +        handler: impl FnOnce(u32, &[u8], &[u8]) -> Option<R>,
> +    ) -> Result<Option<R>> {
> +        let message = self.wait_for_gmc_msg(timeout)?;
> +        let header = message.header;
> +        let length = header.length();
> +
> +        // The RPC and GMC elements share every field through
> `nvdm_header`, so `gmc` holds an
> +        // RPC header rather than a GMC one unless the NVDM type
> says otherwise.
> +        let result = if header.is_gmc_api() {
> +            let command_id = header.gmc.command_id();
> +

IMO, should we check header.gmc.size == payload_length()? as now we
know it is a GMC message now. Not sure if gmc.size < payload_length()
is a valid use case.

> +            dev_dbg!(
> +                &self.dev,
> +                "GSP GMC: event: seq# {}, command_id=0x{:x},
> length=0x{:x}\n",
> +                header.gmc.sequence,
> +                command_id,
> +                length,
> +            );
> +
> +            handler(command_id, message.contents.0,
> message.contents.1)
> +        } else {
> +            dev_warn!(&self.dev, "GSP GMC: dropping non-GMC queue
> element\n");
> +            None
> +        };
> +
> +        self.gsp_mem
> +
> .advance_cpu_read_ptr(u32::try_from(length.div_ceil(GSP_PAGE_SIZE))?);
> +
> +        Ok(result)
> +    }
>  }
> diff --git a/drivers/gpu/nova-core/gsp/fw.rs
> b/drivers/gpu/nova-core/gsp/fw.rs index 9e6b5ec6aadb..83f7d2042aa1
> 100644 --- a/drivers/gpu/nova-core/gsp/fw.rs
> +++ b/drivers/gpu/nova-core/gsp/fw.rs
> @@ -975,8 +975,19 @@ pub(crate) struct GmcApiHeader {
>      reserved: [u32; 5],
>  }
>  
> +/// Command identifier bits of [`GmcApiHeader::command`], matching
> Open RM's +/// `GMCAPI_HEADER_COMMAND_ID_MASK`. The remaining byte
> carries flags. +const GMCAPI_COMMAND_ID_MASK: u32 = 0x00ff_ffff;
> +
>  static_assert!(size_of::<GmcApiHeader>() == 40);
>  
> +impl GmcApiHeader {
> +    /// Returns the command identifier, without the flag byte.
> +    pub(crate) fn command_id(&self) -> u32 {
> +        self.command & GMCAPI_COMMAND_ID_MASK
> +    }
> +}
> +
>  // SAFETY: All fields are integer types with no uninitialized
> padding bytes. unsafe impl AsBytes for GmcApiHeader {}
>  
> @@ -1070,6 +1081,15 @@ pub(crate) fn has_valid_magic(&self) -> bool {
>          self.mctp_magic == MCTP_MAGIC
>      }
>  
> +    /// Returns `true` if the NVDM header routes this element to the
> GSP's GMC dispatch.
> +    ///
> +    /// A [`GspMsgElement`] and a [`GspGmcMsgElement`] share every
> field through `nvdm_header`,
> +    /// so the NVDM type is what distinguishes the two on the queue,
> and `gmc` holds an RPC
> +    /// header rather than a GMC one when this returns `false`.
> +    pub(crate) fn is_gmc_api(&self) -> bool {
> +        self.nvdm_header.validate(NvdmType::GmcApi)
> +    }
> +
>      /// Returns the number of elements (i.e. memory pages) used by
> this message. pub(crate) fn element_count(&self) -> u32 {
>          self.mctp_payload_size
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.