mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: John Hubbard <jhubbard@nvidia.com>
To: Danilo Krummrich <dakr@kernel.org>,
	Alexandre Courbot <acourbot@nvidia.com>
Cc: "Timur Tabi" <ttabi@nvidia.com>,
	"Alistair Popple" <apopple@nvidia.com>,
	"Eliot Courtney" <ecourtney@nvidia.com>,
	"Zhi Wang" <zhiw@nvidia.com>, "David Airlie" <airlied@gmail.com>,
	"Simona Vetter" <simona@ffwll.ch>,
	"Bjorn Helgaas" <bhelgaas@google.com>,
	"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>,
	"Benno Lossin" <lossin@kernel.org>,
	"Andreas Hindborg" <a.hindborg@kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Trevor Gross" <tmgross@umich.edu>,
	nova-gpu@lists.linux.dev, LKML <linux-kernel@vger.kernel.org>,
	"John Hubbard" <jhubbard@nvidia.com>
Subject: [PATCH v3 22/33] gpu: nova-core: gsp: send GSP_INIT and decode its reply
Date: Thu, 17 Sep 2026 18:07:08 -0700	[thread overview]
Message-ID: <20260918010719.1176945-23-jhubbard@nvidia.com> (raw)
In-Reply-To: <20260918010719.1176945-1-jhubbard@nvidia.com>

GSP-RM answers GSP_INIT only once it has finished starting. To finish
starting, GSP-RM first raises the load-and-execute events and waits for
the driver to service them. So the code that waits for the reply has to
service those events while waiting.

Add the GSP_INIT sender and the wait for its reply. The wait passes each
event that arrives before the reply to a handler that the caller
supplies, and it keeps one deadline from the send however many events
arrive, as the RPC reply wait does. Decode the reply into the static
configuration type that the boot sequence already returns, so that the
rest of the driver reads the same configuration whichever firmware
produced it.

Assisted-by: LLM
Reviewed-by: Timur Tabi <ttabi@nvidia.com>
Reviewed-by: Zhi Wang <zhiw@nvidia.com>
Signed-off-by: John Hubbard <jhubbard@nvidia.com>
---
 drivers/gpu/nova-core/gsp/cmdq.rs        | 108 +++++++++++++++++++----
 drivers/gpu/nova-core/gsp/commands.rs    |  99 ++++++++++++++++++++-
 drivers/gpu/nova-core/gsp/fw.rs          |   7 +-
 drivers/gpu/nova-core/gsp/fw/commands.rs |  55 ++++++++++--
 4 files changed, 241 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/nova-core/gsp/cmdq.rs b/drivers/gpu/nova-core/gsp/cmdq.rs
index b202bd8185ba..f64a97736ed7 100644
--- a/drivers/gpu/nova-core/gsp/cmdq.rs
+++ b/drivers/gpu/nova-core/gsp/cmdq.rs
@@ -625,19 +625,38 @@ pub(crate) fn send_command_no_wait<M>(&self, command: M) -> Result
         self.inner.lock().send_command(command)
     }
 
-    /// Receives one GMC event and passes its command id and payload slices to `handler`.
+    /// Waits for the response to the GMC request with command id `command_id`, and passes every
+    /// other GMC element that arrives first to `on_other`.
     ///
-    /// This method may sleep while waiting. The queue mutex stays locked across the wait and the
-    /// `handler` call, so `handler` must not call back into this [`Cmdq`].
+    /// This method may sleep while waiting. The queue mutex stays locked across the whole wait and
+    /// across the `on_other` and `decode` calls, so neither may call back into this [`Cmdq`].
     ///
-    /// See [`CmdqInner::receive_gmc_and_dispatch`] for the return value and the errors.
-    #[expect(dead_code)]
-    pub(crate) fn receive_gmc_and_dispatch<R>(
+    /// See [`CmdqInner::await_gmc_response`] for the return value and the errors.
+    pub(crate) fn await_gmc_response<R>(
         &self,
-        timeout: Delta,
-        handler: impl FnOnce(u32, &[u8], &[u8]) -> Result<Option<R>>,
-    ) -> Result<Option<R>> {
-        self.inner.lock().receive_gmc_and_dispatch(timeout, handler)
+        command_id: u32,
+        on_other: impl FnMut(&GspGmcMsgElement, &[u8], &[u8]) -> Result,
+        decode: impl FnMut(&[u8], &[u8]) -> Result<R>,
+    ) -> Result<R> {
+        self.inner
+            .lock()
+            .await_gmc_response(command_id, on_other, decode)
+    }
+
+    /// Sends a GMC API request to the GSP without waiting for the response.
+    ///
+    /// # Errors
+    ///
+    /// Errors from [`DmaGspMem::allocate_command`] are propagated as-is.
+    pub(crate) fn send_gmc_no_wait(
+        &self,
+        command_id: u32,
+        payload: &[u8],
+        max_response_size: u32,
+    ) -> Result {
+        self.inner
+            .lock()
+            .send_gmc(command_id, payload, max_response_size)
     }
 
     /// Waits for an unsolicited GSP event of type `M`. Events that arrive before it are logged and
@@ -812,7 +831,6 @@ fn poison(&self, reason: fmt::Arguments<'_>) -> Error {
     /// # Errors
     ///
     /// Errors from [`DmaGspMem::allocate_command`] are propagated as-is.
-    #[expect(dead_code)]
     fn send_gmc(&mut self, command_id: u32, payload: &[u8], max_response_size: u32) -> Result {
         let seq = self.seq;
         self.seq = self.seq.wrapping_add(1);
@@ -1204,8 +1222,9 @@ fn consume_element<R>(
 
     /// Receives the next queue element and, if it is a GMC element, passes it to `handler`.
     ///
-    /// `handler` receives the command id and the payload that follows the GMC API header, as two
-    /// slices because the ring may wrap, and returns `None` for an element that it declines.
+    /// `handler` receives the headers that open the element and the payload that follows the GMC
+    /// API header, as two slices because the ring may wrap, and returns `None` for an element that
+    /// it declines.
     ///
     /// Returns `Ok(None)` when `handler` declines the element or when the element is not a GMC
     /// element.
@@ -1220,7 +1239,7 @@ fn consume_element<R>(
     fn receive_gmc_and_dispatch<R>(
         &mut self,
         timeout: Delta,
-        handler: impl FnOnce(u32, &[u8], &[u8]) -> Result<Option<R>>,
+        handler: impl FnOnce(&GspGmcMsgElement, &[u8], &[u8]) -> Result<Option<R>>,
     ) -> Result<Option<R>> {
         self.consume_element(timeout, |this, element| match element {
             QueueElement::Other(_) => {
@@ -1230,18 +1249,73 @@ fn receive_gmc_and_dispatch<R>(
             }
             QueueElement::Gmc(message) => {
                 let header = message.header;
-                let command_id = header.gmc.command_id();
 
                 dev_dbg!(
                     &this.dev,
                     "GSP GMC: event: seq# {}, command_id=0x{:x}, length=0x{:x}\n",
                     header.gmc.sequence,
-                    command_id,
+                    header.gmc.command_id(),
                     header.length(),
                 );
 
-                handler(command_id, message.contents.0, message.contents.1)
+                handler(header, message.contents.0, message.contents.1)
             }
         })
     }
+
+    /// Waits for the response to the GMC request with command id `command_id`, up to
+    /// [`Cmdq::RECEIVE_TIMEOUT`] from the call.
+    ///
+    /// The response's payload is passed to `decode`, as two slices because the ring may wrap.
+    /// Every other GMC element that arrives first is passed to `on_other` with the headers that
+    /// open it and its payload slices, and any other element is logged. Neither kind of element
+    /// extends the deadline.
+    ///
+    /// # Errors
+    ///
+    /// - `ETIMEDOUT` if the response does not arrive before the deadline, however many other
+    ///   elements arrive while waiting.
+    /// - `EIO` if the queue is poisoned or an element fails framing validation (see
+    ///   [`Self::wait_for_element`]), or if the response carries a failure status.
+    ///
+    /// Errors from `on_other` and `decode` are propagated as-is.
+    fn await_gmc_response<R>(
+        &mut self,
+        command_id: u32,
+        mut on_other: impl FnMut(&GspGmcMsgElement, &[u8], &[u8]) -> Result,
+        mut decode: impl FnMut(&[u8], &[u8]) -> Result<R>,
+    ) -> Result<R> {
+        let dev = self.dev;
+        let deadline = Instant::<Monotonic>::now() + Cmdq::RECEIVE_TIMEOUT;
+        loop {
+            let remaining = deadline - Instant::<Monotonic>::now();
+            if remaining.is_negative() {
+                break Err(ETIMEDOUT);
+            }
+
+            let response =
+                self.receive_gmc_and_dispatch(remaining, |header, payload_0, payload_1| {
+                    if header.gmc.command_id() != command_id {
+                        return on_other(header, payload_0, payload_1).map(|()| None);
+                    }
+
+                    let status = header.gmc.status();
+                    if status != 0 {
+                        dev_err!(
+                            dev,
+                            "GSP GMC: command 0x{:x} failed, status={:#x}\n",
+                            command_id,
+                            status
+                        );
+                        return Err(EIO);
+                    }
+
+                    decode(payload_0, payload_1).map(Some)
+                })?;
+
+            if let Some(response) = response {
+                break Ok(response);
+            }
+        }
+    }
 }
diff --git a/drivers/gpu/nova-core/gsp/commands.rs b/drivers/gpu/nova-core/gsp/commands.rs
index 2c7965174445..74ae92428cad 100644
--- a/drivers/gpu/nova-core/gsp/commands.rs
+++ b/drivers/gpu/nova-core/gsp/commands.rs
@@ -30,13 +30,21 @@
         },
         fw::{
             self,
-            commands::GspInitRequest,
-            MsgFunction, //
+            commands::{
+                GspInitRequest,
+                GspInitResponse,
+                GspInitResponseSchema, //
+            },
+            GspGmcMsgElement,
+            MsgFunction,
+            GMCAPI_CMD_GSP_INIT, //
         },
         nvkv::{
+            Decoder,
             Encodable,
             EncodedStream,
-            Encoder, //
+            Encoder,
+            UnknownKeyPolicy, //
         },
     },
     sbuffer::SBufferIter,
@@ -287,6 +295,91 @@ pub(crate) fn build_gsp_init_payload(
     Ok(encoder.finish())
 }
 
+/// Largest `GSP_INIT` response that the driver accepts.
+const GSP_INIT_MAX_RESPONSE_SIZE: u32 = 48 * 1024;
+
+/// Sends `GSP_INIT` and returns the static GPU configuration that its reply carries.
+///
+/// Every GMC (GPU Management Controller) element that arrives before the reply is passed to
+/// `on_unsolicited_element` with the headers that open it and its payload, as two slices because
+/// the ring may wrap. The load-and-execute events that GSP-RM raises while it starts arrive this
+/// way.
+///
+/// `payload` is the stream from [`build_gsp_init_payload`].
+///
+/// # Errors
+///
+/// - `EIO` if GSP-RM reports a failure status.
+/// - `ETIMEDOUT` if the reply does not arrive within [`Cmdq::RECEIVE_TIMEOUT`] of the send,
+///   however many events arrive while waiting.
+///
+/// Errors from `on_unsolicited_element` and from decoding the reply are propagated as-is.
+#[expect(dead_code)]
+pub(crate) fn gsp_init(
+    cmdq: &Cmdq<'_>,
+    payload: &[u64],
+    on_unsolicited_element: impl FnMut(&GspGmcMsgElement, &[u8], &[u8]) -> Result,
+) -> Result<GspStaticInfo> {
+    // Qualified because `zerocopy::IntoBytes` also gives `[T]` an `as_bytes`.
+    let payload = AsBytes::as_bytes(payload);
+
+    cmdq.send_gmc_no_wait(GMCAPI_CMD_GSP_INIT, payload, GSP_INIT_MAX_RESPONSE_SIZE)?;
+
+    cmdq.await_gmc_response(
+        GMCAPI_CMD_GSP_INIT,
+        on_unsolicited_element,
+        decode_gsp_init_reply,
+    )
+}
+
+/// Decodes the `GSP_INIT` reply from its payload, which the ring may have split in two, into the
+/// static configuration type that the boot sequence returns.
+///
+/// # Errors
+///
+/// - `EINVAL` if the payload is not a whole number of NVKV words, if the stream is malformed or
+///   omits a required key, or if GSP-RM reported no framebuffer region.
+/// - `ENOMEM` if the words or the decoded regions cannot be allocated.
+fn decode_gsp_init_reply(payload_0: &[u8], payload_1: &[u8]) -> Result<GspStaticInfo> {
+    const WORD_SIZE: usize = size_of::<u64>();
+
+    let len = payload_0.len() + payload_1.len();
+    if len % WORD_SIZE != 0 {
+        return Err(EINVAL);
+    }
+
+    let mut words = KVVec::with_capacity(len / WORD_SIZE, GFP_KERNEL)?;
+    let mut bytes = SBufferIter::new_reader([payload_0, payload_1]);
+    for _ in 0..len / WORD_SIZE {
+        let mut word = [0u8; WORD_SIZE];
+        bytes.read_exact(&mut word)?;
+        words.push(u64::from_le_bytes(word), GFP_KERNEL)?;
+    }
+
+    let decoder = Decoder::new(&words, UnknownKeyPolicy::Ignore);
+    let mut schema = GspInitResponseSchema::default();
+    let decoded = KBox::try_init(decoder.decode(&mut schema)?, GFP_KERNEL)?;
+
+    let mut gpu_name = [0u8; GspInitResponse::MAX_GPU_NAME_LEN];
+    let name = decoded.gpu_name();
+    gpu_name
+        .get_mut(..name.len())
+        .ok_or(EINVAL)?
+        .copy_from_slice(name);
+
+    let mut usable_fb_regions = KVec::new();
+    for region in decoded.usable_fb_regions() {
+        usable_fb_regions.push(region, GFP_KERNEL)?;
+    }
+
+    Ok(GspStaticInfo {
+        gpu_name,
+        bar1_pde_base: decoded.bar1_pde_base(),
+        usable_fb_regions,
+        total_fb_end: decoded.total_fb_end().ok_or(EINVAL)?,
+    })
+}
+
 pub(crate) use fw::commands::PowerStateLevel;
 
 /// The `UnloadingGuestDriver` command, used to shut down the GSP.
diff --git a/drivers/gpu/nova-core/gsp/fw.rs b/drivers/gpu/nova-core/gsp/fw.rs
index e86283f67358..cc0bc8f8ae87 100644
--- a/drivers/gpu/nova-core/gsp/fw.rs
+++ b/drivers/gpu/nova-core/gsp/fw.rs
@@ -1048,13 +1048,17 @@ pub(crate) struct GmcApiHeader {
     /// Sequence number that GSP-RM copies from a request into its response.
     pub(crate) sequence: u64,
     /// In a request, the largest response that the sender accepts. In a response, the `NV_STATUS`.
-    pub(crate) max_resp_or_status: u32,
+    max_resp_or_status: u32,
     reserved: [u32; 5],
 }
 
 /// Bits of [`GmcApiHeader::command`] that hold the command id. The high byte holds flags.
 const GMCAPI_COMMAND_ID_MASK: u32 = 0x00ff_ffff;
 
+/// GMC request that carries the system information and registry keys to GSP-RM. GSP-RM answers
+/// it with the static GPU configuration once it has finished starting.
+pub(crate) const GMCAPI_CMD_GSP_INIT: u32 = r000_00::GMCAPI_COMMANDS_GMCAPI_CMD_GSP_INIT;
+
 /// GMC event that requests the driver to run the generic falcon bootloader on the descriptor that
 /// the event carries.
 pub(crate) const GMCAPI_CMD_EXEC_GENERIC_BOOTLOADER: u32 =
@@ -1097,7 +1101,6 @@ pub(crate) fn command_id(&self) -> u32 {
     ///
     /// The value is meaningful only on a response, which GSP-RM marks with a flag in the command
     /// word. In a request, the same word holds the largest response that the sender accepts.
-    #[expect(dead_code)]
     pub(crate) fn status(&self) -> u32 {
         self.max_resp_or_status
     }
diff --git a/drivers/gpu/nova-core/gsp/fw/commands.rs b/drivers/gpu/nova-core/gsp/fw/commands.rs
index 4fdd6ff23dc1..748639942fe1 100644
--- a/drivers/gpu/nova-core/gsp/fw/commands.rs
+++ b/drivers/gpu/nova-core/gsp/fw/commands.rs
@@ -455,10 +455,7 @@ pub(crate) fn new(
 // Should decode with UnknownKeyPolicy::Ignore.
 nvkv_decode! {
     /// Schema for the `GSP_INIT` response.
-    // TODO: expect() doesn't work here due to Self:: reference, fixed in 1.97.0
-    // https://github.com/rust-lang/rust/pull/154377
-    #[cfg_attr(not(CONFIG_KUNIT), allow(dead_code))]
-    struct GspInitResponseSchema => GspInitResponse {
+    pub(crate) struct GspInitResponseSchema => GspInitResponse {
         gpu_name:
             Array<u8, { GspInitResponse::MAX_GPU_NAME_LEN }, { Self::GPU_NAME_STRING_KEY }>,
         fb_regions: Accumulated<FbRegionSchema>,
@@ -475,15 +472,61 @@ impl GspInitResponseSchema {
 }
 
 /// Payload of the `GSP_INIT` response.
-struct GspInitResponse {
+pub(crate) struct GspInitResponse {
     gpu_name: ArrayVec<u8, { Self::MAX_GPU_NAME_LEN }>,
     fb_regions: KVVec<FbRegion>,
     bar1_pde_base: u64,
+    #[cfg_attr(not(CONFIG_KUNIT = "y"), expect(dead_code))]
     vmmu_segment_size: u64,
 }
 
 impl GspInitResponse {
-    const MAX_GPU_NAME_LEN: usize = 64;
+    pub(crate) const MAX_GPU_NAME_LEN: usize = 64;
+
+    /// Tag of a general-purpose region. Any other tag marks a region that GSP-RM reserves for the
+    /// use that the tag names.
+    const FB_REGION_TAG_NONE: u32 = 0;
+
+    /// Returns the GPU name, which GSP-RM sends with its NUL terminator.
+    pub(crate) fn gpu_name(&self) -> &[u8] {
+        self.gpu_name.as_slice()
+    }
+
+    /// Returns an iterator over the FB regions from which the driver may allocate: the
+    /// general-purpose regions that are not protected and that support both compression and
+    /// isochronous access.
+    pub(crate) fn usable_fb_regions(&self) -> impl Iterator<Item = Range<u64>> + '_ {
+        self.fb_regions.iter().filter_map(|region| {
+            if region.limit >= region.base
+                && region.tag == Self::FB_REGION_TAG_NONE
+                && !region.flags.protected()
+                && region.flags.support_compressed()
+                && region.flags.support_iso()
+            {
+                region.limit.checked_add(1).map(|end| region.base..end)
+            } else {
+                None
+            }
+        })
+    }
+
+    /// Returns the exclusive end of the FB physical address space, which spans every region
+    /// including the ones that [`Self::usable_fb_regions`] leaves out.
+    ///
+    /// Returns `None` if no region that GSP-RM reported has a limit at or above its base.
+    pub(crate) fn total_fb_end(&self) -> Option<u64> {
+        self.fb_regions
+            .iter()
+            .filter(|region| region.limit >= region.base)
+            .map(|region| region.limit)
+            .max()?
+            .checked_add(1)
+    }
+
+    /// Returns the BAR1 page directory entry base address.
+    pub(crate) fn bar1_pde_base(&self) -> u64 {
+        self.bar1_pde_base
+    }
 }
 
 nvkv_decode! {
-- 
2.55.0


  parent reply	other threads:[~2026-09-18  1:08 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-18  1:06 [PATCH v3 00/33] gpu: nova-core: boot on the r000 GSP firmware John Hubbard
2026-09-18  1:06 ` [PATCH v3 01/33] rust: pci: add domain_nr() accessor John Hubbard
2026-09-18  1:06 ` [PATCH v3 02/33] gpu: nova-core: set MCTP transport header version to 1 John Hubbard
2026-09-18  1:06 ` [PATCH v3 03/33] gpu: nova-core: gsp: give the command queue its own BAR0 mapping John Hubbard
2026-09-18  1:06 ` [PATCH v3 04/33] gpu: nova-core: firmware: add r000 bindings John Hubbard
2026-09-18  1:06 ` [PATCH v3 05/33] gpu: nova-core: regs: add msgq v2 BAR0 register declarations John Hubbard
2026-09-18  1:06 ` [PATCH v3 06/33] gpu: nova-core: gsp: ring the GSP doorbell from the queue memory John Hubbard
2026-09-18  1:06 ` [PATCH v3 07/33] gpu: nova-core: gsp: make command allocation generic over the header John Hubbard
2026-09-18  1:06 ` [PATCH v3 08/33] gpu: nova-core: gsp: compute the queue regions from a count and a slot John Hubbard
2026-09-18  1:06 ` [PATCH v3 09/33] gpu: nova-core: add GMC API message types John Hubbard
2026-09-18  1:06 ` [PATCH v3 10/33] gpu: nova-core: add GMC send path John Hubbard
2026-09-18  1:06 ` [PATCH v3 11/33] gpu: nova-core: add GMC transport receive path John Hubbard
2026-09-18  1:06 ` [PATCH v3 12/33] gpu: nova-core: gsp: add GMC dispatch on receive John Hubbard
2026-09-18  1:06 ` [PATCH v3 13/33] gpu: nova-core: separate the generic falcon bootloader from FWSEC John Hubbard
2026-09-18  1:07 ` [PATCH v3 14/33] gpu: nova-core: add the falcon DMA and suspend helpers for r000 boot John Hubbard
2026-09-18  1:07 ` [PATCH v3 15/33] gpu: nova-core: add the r000 load-and-execute HS binary handler John Hubbard
2026-09-18  1:07 ` [PATCH v3 16/33] gpu: nova-core: move the bootloader DMEM descriptor out of FWSEC John Hubbard
2026-09-18  1:07 ` [PATCH v3 17/33] gpu: nova-core: add the r000 load-and-execute bootloader handler John Hubbard
2026-09-18  3:32   ` Timur Tabi
2026-09-18  1:07 ` [PATCH v3 18/33] gpu: nova-core: gsp: add the GMC boot event dispatcher John Hubbard
2026-09-18  1:07 ` [PATCH v3 19/33] gpu: nova-core: gsp: rename the static configuration type John Hubbard
2026-09-18  1:07 ` [PATCH v3 20/33] gpu: nova-core: gsp: return the static GPU configuration from boot John Hubbard
2026-09-18  1:07 ` [PATCH v3 21/33] gpu: nova-core: gsp: add the GSP_INIT request builder John Hubbard
2026-09-18  1:07 ` John Hubbard [this message]
2026-09-18  1:07 ` [PATCH v3 23/33] gpu: nova-core: add LIBOS3 log buffers and state monitor buffer John Hubbard
2026-09-18  1:07 ` [PATCH v3 24/33] gpu: nova-core: add the ucodes firmware loader John Hubbard
2026-09-18  1:07 ` [PATCH v3 25/33] gpu: nova-core: gsp: let the GSP HAL load the generic bootloader John Hubbard
2026-09-18  1:07 ` [PATCH v3 26/33] gpu: nova-core: gsp: add the GSP_SUSPEND request John Hubbard
2026-09-18  1:07 ` [PATCH v3 27/33] gpu: nova-core: switch to the r000 GSP firmware John Hubbard
2026-09-18  1:07 ` [PATCH v3 28/33] gpu: nova-core: gsp: make the GSP_INIT reply the static configuration John Hubbard
2026-09-18  1:07 ` [PATCH v3 29/33] gpu: nova-core: firmware: delete the r570 bindings John Hubbard
2026-09-18  1:07 ` [PATCH v3 30/33] gpu: nova-core: match GSP RPC replies by sequence, not just function John Hubbard
2026-09-18  1:07 ` [PATCH v3 31/33] gpu: nova-core: gsp: split the reply match out of the RPC receive path John Hubbard
2026-09-18  1:07 ` [PATCH v3 32/33] gpu: nova-core: gsp: decode queue elements by their NVDM type John Hubbard
2026-09-18  1:07 ` [PATCH v3 33/33] gpu: nova-core: gsp: match a GMC response by flag, id and sequence John Hubbard

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=20260918010719.1176945-23-jhubbard@nvidia.com \
    --to=jhubbard@nvidia.com \
    --cc=a.hindborg@kernel.org \
    --cc=acourbot@nvidia.com \
    --cc=airlied@gmail.com \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=apopple@nvidia.com \
    --cc=bhelgaas@google.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=dakr@kernel.org \
    --cc=ecourtney@nvidia.com \
    --cc=gary@garyguo.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=nova-gpu@lists.linux.dev \
    --cc=ojeda@kernel.org \
    --cc=simona@ffwll.ch \
    --cc=tmgross@umich.edu \
    --cc=ttabi@nvidia.com \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®