From: John Hubbard <jhubbard@nvidia.com>
To: Danilo Krummrich <dakr@kernel.org>,
Joel Fernandes <joel@joelfernandes.org>,
Alexandre Courbot <acourbot@nvidia.com>
Cc: "Timur Tabi" <ttabi@nvidia.com>,
"Alistair Popple" <apopple@nvidia.com>,
"Eliot Courtney" <ecourtney@nvidia.com>,
"Shashank Sharma" <shashanks@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>,
"Will Pierce" <wpierce@nvidia.com>,
"Joel Fernandes" <joelagnelf@nvidia.com>
Subject: [PATCH 09/17] gpu: nova-core: add an interrupt delivery self-test
Date: Fri, 7 Aug 2026 20:11:11 -0700 [thread overview]
Message-ID: <20260808031120.363869-10-jhubbard@nvidia.com> (raw)
In-Reply-To: <20260808031120.363869-1-jhubbard@nvidia.com>
A GPU interrupt can be lost in the MSI or MSI-X allocation, in the GIN
tree's enable bits, or in the rearm. Every one of those failures looks
the same to the driver: no interrupt arrives, and nothing in the symptom
says which one broke.
Add an optional probe-time self-test that injects the CPU doorbell
through the GIN software trigger. One injection would pass even with a
broken rearm, because the first message-signaled interrupt arrives
whether the driver rearms or not. The test injects twice, and waits for
the first handler to rearm before it injects again.
Run it before GSP boot on a quiesced tree, and fail probe unless exactly
two deliveries arrive, each delivery finds only the doorbell pending,
and the leaf ends clear. Under MSI-X the injected subtree has its own
table entry, so the delivery exercises that entry too.
Assisted-by: Cursor:claude-opus-5
Reviewed-by: Will Pierce <wpierce@nvidia.com>
Co-developed-by: Joel Fernandes <joelagnelf@nvidia.com>
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
Signed-off-by: John Hubbard <jhubbard@nvidia.com>
---
drivers/gpu/nova-core/Kconfig | 15 +
drivers/gpu/nova-core/gpu.rs | 8 +
drivers/gpu/nova-core/irq.rs | 2 +
drivers/gpu/nova-core/irq/doorbell_test.rs | 324 ++++++++++++++++++++
drivers/gpu/nova-core/irq/interrupt_tree.rs | 13 +
drivers/gpu/nova-core/nova_core.rs | 2 +-
6 files changed, 363 insertions(+), 1 deletion(-)
create mode 100644 drivers/gpu/nova-core/irq/doorbell_test.rs
diff --git a/drivers/gpu/nova-core/Kconfig b/drivers/gpu/nova-core/Kconfig
index f918f69e0599..7198fae6b6f4 100644
--- a/drivers/gpu/nova-core/Kconfig
+++ b/drivers/gpu/nova-core/Kconfig
@@ -15,3 +15,18 @@ config NOVA_CORE
This driver is work in progress and may not be functional.
If M is selected, the module will be called nova-core.
+
+config NOVA_CORE_IRQ_SELFTEST
+ bool "Nova Core interrupt delivery self-test"
+ depends on NOVA_CORE
+ help
+ Run an interrupt delivery self-test during nova-core probe. It
+ injects a known vector through the GPU interrupt controller's
+ software trigger and confirms the interrupt reaches the driver's
+ handler, validating the PCI interrupt path from the GPU to the CPU
+ with no dependency on GSP firmware. The result is printed to dmesg.
+
+ If the test fails, the PCI probe fails and the driver does not load.
+
+ This is intended for driver bring-up and for debugging PCI, MSI, or
+ passthrough setups. If unsure, say N.
diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs
index 42a4cd7971fa..d5df0ebf67ae 100644
--- a/drivers/gpu/nova-core/gpu.rs
+++ b/drivers/gpu/nova-core/gpu.rs
@@ -347,6 +347,14 @@ pub(crate) fn new(
.inspect_err(|_| dev_err!(dev, "GFW boot did not complete\n"))?;
},
+ // Validate the MSI interrupt path before booting GSP, when the self-test is
+ // enabled. This runs on a quiesced interrupt tree with no GSP state present, so it
+ // never observes or clears GSP or PRIV_RING interrupts.
+ _: {
+ #[cfg(CONFIG_NOVA_CORE_IRQ_SELFTEST)]
+ crate::irq::doorbell_test::run_selftest(pdev, bar, spec.chipset)?;
+ },
+
// Initialize this early because `gsp_resources` depends on it.
sysmem_flush: SysmemFlush::register(dev, bar, spec.chipset)?,
diff --git a/drivers/gpu/nova-core/irq.rs b/drivers/gpu/nova-core/irq.rs
index 2f0e2644b9bd..5b449759b333 100644
--- a/drivers/gpu/nova-core/irq.rs
+++ b/drivers/gpu/nova-core/irq.rs
@@ -8,6 +8,8 @@
//!
//! See `Documentation/gpu/nova/core/interrupts.rst`.
+#[cfg(CONFIG_NOVA_CORE_IRQ_SELFTEST)]
+pub(crate) mod doorbell_test;
mod hal;
mod interrupt_tree;
diff --git a/drivers/gpu/nova-core/irq/doorbell_test.rs b/drivers/gpu/nova-core/irq/doorbell_test.rs
new file mode 100644
index 000000000000..fae770339fd7
--- /dev/null
+++ b/drivers/gpu/nova-core/irq/doorbell_test.rs
@@ -0,0 +1,324 @@
+// SPDX-License-Identifier: GPL-2.0
+// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+//! Interrupt delivery self-test, driven through the CPU doorbell vector.
+//!
+//! Exercises the whole PCI interrupt path (GPU to PCIe to CPU to handler) with no GSP dependency:
+//! it injects a known vector through the GIN software trigger and confirms the handler runs. Two
+//! interrupts are triggered one at a time, which also covers the rearm that every delivery after
+//! the first depends on. Gated behind `CONFIG_NOVA_CORE_IRQ_SELFTEST` and run before GSP boot, so
+//! it never observes or clears GSP interrupt state.
+//!
+//! See `Documentation/gpu/nova/core/interrupts.rst`.
+
+use core::pin::Pin;
+
+use kernel::{
+ device::Bound,
+ irq,
+ pci,
+ prelude::*,
+ sync::{
+ atomic::{
+ Atomic,
+ Relaxed, //
+ },
+ Completion, //
+ },
+ time, //
+};
+
+use super::interrupt_tree::{
+ vector_leaf_bit,
+ vector_subtree_mask,
+ LeafIndex,
+ Tree, //
+};
+use crate::{
+ driver::Bar0,
+ gpu::Chipset, //
+};
+
+/// Fixed vector for the CPU doorbell.
+///
+/// The resource manager pins the CPU doorbell to this vector on every supported chip, so nova-core
+/// uses the constant directly instead of discovering it at runtime.
+const DOORBELL_VECTOR: u32 = 129;
+
+/// Leaf and bit index of the doorbell vector within the interrupt tree.
+const DOORBELL_LOC: (usize, u32) = vector_leaf_bit(DOORBELL_VECTOR);
+
+/// Leaf holding the doorbell vector.
+const DOORBELL_LEAF: usize = DOORBELL_LOC.0;
+
+/// Bit of the doorbell vector within its leaf.
+const DOORBELL_BIT: u32 = 1 << DOORBELL_LOC.1;
+
+/// Subtree carrying the doorbell vector, and the only subtree this test services.
+///
+/// Derived from the vector so that changing `DOORBELL_VECTOR` moves the allocation, the subtree it
+/// enables, and the handler together.
+const DOORBELL_SUBTREE: u32 = vector_subtree_mask(DOORBELL_VECTOR);
+
+/// Index of the subtree carrying the doorbell vector. Under MSI-X this is also the index of the
+/// table entry that subtree raises.
+const DOORBELL_SUBTREE_INDEX: u32 = DOORBELL_SUBTREE.trailing_zeros();
+
+/// Time allowed for each of the two deliveries to arrive.
+const DELIVERY_TIMEOUT_MS: time::Msecs = 1000;
+
+/// Interrupt handler installed by the self-test.
+///
+/// Services the doorbell the way a notification source is serviced: it clears its own leaf bit and
+/// rearms PCI interrupt delivery, leaving the rest of the tree untouched. It records the leaf's
+/// pending bits seen on each of the first two deliveries and signals the matching completion.
+#[pin_data]
+struct DoorbellTestHandler<'a> {
+ /// Borrowed BAR0, for register access from interrupt context.
+ bar: Bar0<'a>,
+ tree: Tree,
+ /// Signalled by the first delivery.
+ #[pin]
+ first: Completion,
+ /// Signalled by the second delivery.
+ #[pin]
+ second: Completion,
+ /// Count of deliveries this handler has serviced.
+ irq_count: Atomic<u32>,
+ /// Doorbell leaf's pending bits observed on the first delivery.
+ first_pending: Atomic<u32>,
+ /// Doorbell leaf's pending bits observed on the second delivery.
+ second_pending: Atomic<u32>,
+}
+
+impl irq::Handler for DoorbellTestHandler<'_> {
+ fn handle(&self) -> irq::IrqReturn {
+ let bar = self.bar;
+
+ // Clear only this handler's own bit and leave `TOP_EN` alone. A full walk disables and
+ // enables the tree, which produces a delivery edge by itself and would hide a missing PCI
+ // interrupt rearm.
+ let leaf = self
+ .tree
+ .leaf(LeafIndex::new::<DOORBELL_LEAF>())
+ .read_pending(bar);
+ let pending = leaf.pending_bits();
+ if pending & DOORBELL_BIT == 0 {
+ self.tree.rearm_pci_irq(bar, DOORBELL_SUBTREE);
+ return irq::IrqReturn::None;
+ }
+ leaf.clear_vectors(bar, DOORBELL_BIT);
+
+ let count = self.irq_count.fetch_add(1, Relaxed);
+
+ // Rearm before signalling, so delivery is possible again by the time the waiting thread
+ // triggers the next vector.
+ self.tree.rearm_pci_irq(bar, DOORBELL_SUBTREE);
+
+ match count {
+ 0 => {
+ self.first_pending.store(pending, Relaxed);
+ self.first.complete_all();
+ }
+ 1 => {
+ self.second_pending.store(pending, Relaxed);
+ self.second.complete_all();
+ }
+ _ => (),
+ }
+
+ irq::IrqReturn::Handled
+ }
+}
+
+/// Teardown guard for the self-test.
+///
+/// Owns the IRQ registration so that every exit path, including an early error, tears down the
+/// interrupt in this order: disabling the leaf stops new deliveries, dropping the registration
+/// runs `free_irq()`, which waits for a handler still in flight, and only then are the tree's
+/// subtrees disabled, so a late handler cannot rearm them.
+struct SelftestGuard<'a, 'r> {
+ bar: Bar0<'a>,
+ tree: Tree,
+ doorbell: LeafIndex,
+ reg: Option<Pin<KBox<irq::Registration<'r, DoorbellTestHandler<'a>>>>>,
+}
+
+impl<'a, 'r> SelftestGuard<'a, 'r> {
+ /// Returns the registered handler.
+ fn handler(&self) -> &DoorbellTestHandler<'a> {
+ // `reg` is `Some` for the whole lifetime of the guard. Only `drop` clears it.
+ self.reg.as_ref().unwrap().handler()
+ }
+
+ /// Disables the doorbell source and waits for a handler already running on another CPU.
+ ///
+ /// On return no further delivery can reach the handler, so its counters and the doorbell
+ /// leaf hold their final values.
+ fn quiesce_source(&self) {
+ self.tree
+ .leaf(self.doorbell)
+ .disable(self.bar, DOORBELL_BIT);
+ // `reg` is `Some` for the whole lifetime of the guard. Only `drop` clears it.
+ self.reg.as_ref().unwrap().synchronize();
+ }
+}
+
+impl Drop for SelftestGuard<'_, '_> {
+ fn drop(&mut self) {
+ self.tree
+ .leaf(self.doorbell)
+ .disable(self.bar, DOORBELL_BIT);
+ self.reg = None;
+ self.tree.top().disable(self.bar);
+ }
+}
+
+/// Runs the interrupt delivery self-test.
+///
+/// Quiesces the interrupt tree, registers a temporary handler, and injects the doorbell vector
+/// through the GIN software trigger twice, one delivery at a time. This validates the PCI
+/// interrupt path from GIN to the ISR without GSP firmware, including the rearm without which only
+/// the first interrupt would arrive. The handler, its IRQ registration, and all tree state are
+/// torn down before this returns.
+///
+/// # Errors
+///
+/// `EIO` if the doorbell is already pending before the test, if the delivery count is not two, if
+/// the doorbell bit is still set once the source is stopped, or if either delivery found a pending
+/// bit other than the doorbell. `ETIMEDOUT` if either delivery does not arrive within the timeout.
+pub(crate) fn run_selftest<'a>(
+ pdev: &'a pci::Device<Bound>,
+ bar: Bar0<'a>,
+ chipset: Chipset,
+) -> Result {
+ // The allocated interrupt type decides how the handler rearms delivery, so the vectors are
+ // allocated before the tree is built.
+ let vectors = super::alloc_vectors(pdev, DOORBELL_SUBTREE)?;
+ let vector = vectors.vector_for(DOORBELL_SUBTREE)?;
+ let irq_type = vectors.irq_type();
+ let tree = Tree::new(chipset, irq_type, DOORBELL_SUBTREE);
+ let doorbell = LeafIndex::new::<DOORBELL_LEAF>();
+
+ // Under MSI-X the subtree index is also the table entry the delivery arrives on, so a pass
+ // shows that the per-subtree routing works. Under MSI every subtree shares one entry.
+ dev_info!(
+ pdev.as_ref(),
+ "interrupt self-test: starting on vector {}, subtree {}, with {:?}\n",
+ DOORBELL_VECTOR,
+ DOORBELL_SUBTREE_INDEX,
+ irq_type,
+ );
+
+ // No delivery may reach the CPU before a handler is registered. `drain` enables the top level
+ // as the last step of its cycle, so disable it again afterward.
+ tree.leaf(doorbell).disable(bar, DOORBELL_BIT);
+ tree.drain(bar);
+ tree.top().disable(bar);
+
+ // A delivery can be credited to the trigger below only if the vector starts out clear, so
+ // refuse to run otherwise.
+ let pre_pending = tree.leaf(doorbell).read_pending(bar).pending_bits();
+ if pre_pending & DOORBELL_BIT != 0 {
+ dev_warn!(
+ pdev.as_ref(),
+ "interrupt self-test: failed, vector {} already pending (leaf[{}] pending {:#x})\n",
+ DOORBELL_VECTOR,
+ DOORBELL_LEAF,
+ pre_pending,
+ );
+ return Err(EIO);
+ }
+
+ // `try_pin_init!` moves its captures, so the handler takes a clone and `tree` stays available
+ // for the guard below.
+ let handler_tree = tree.clone();
+ let handler_init = try_pin_init!(DoorbellTestHandler {
+ bar,
+ tree: handler_tree,
+ first <- Completion::new(),
+ second <- Completion::new(),
+ irq_count: Atomic::new(0),
+ first_pending: Atomic::new(0),
+ second_pending: Atomic::new(0),
+ }? Error);
+
+ // Register the handler before allowing any source to fire.
+ let reg = KBox::pin_init(
+ // SAFETY: the registration is owned by `guard` below and dropped before this function
+ // returns, so its `Drop` (which calls `free_irq()`) always runs and the registration is
+ // never leaked or `mem::forget`-ed.
+ unsafe { pdev.request_irq(vector, irq::Flags::TRIGGER_NONE, c"nova-core", handler_init) },
+ GFP_KERNEL,
+ )?;
+
+ // From here every exit must tear down the source, the registration, and the tree, so hand the
+ // registration to a guard that does so on drop.
+ let guard = SelftestGuard {
+ bar,
+ tree: tree.clone(),
+ doorbell,
+ reg: Some(reg),
+ };
+ let handler = guard.handler();
+
+ // The handler is registered, so the source can be enabled.
+ handler.tree.leaf(doorbell).enable(bar, DOORBELL_BIT);
+ handler.tree.top().enable(bar);
+
+ handler.tree.trigger(bar, DOORBELL_VECTOR)?;
+ let mut completed = handler
+ .first
+ .wait_for_completion_timeout(time::msecs_to_jiffies(DELIVERY_TIMEOUT_MS))
+ .is_some();
+
+ // Trigger the second interrupt only once the first handler has cleared its leaf bit and
+ // rearmed, so the two cannot coalesce into one delivery and a handler that never rearms
+ // cannot pass.
+ if completed {
+ handler.tree.trigger(bar, DOORBELL_VECTOR)?;
+ completed = handler
+ .second
+ .wait_for_completion_timeout(time::msecs_to_jiffies(DELIVERY_TIMEOUT_MS))
+ .is_some();
+ }
+
+ // Stop the source and wait out any handler still running, so the values read below are the
+ // final ones.
+ guard.quiesce_source();
+
+ let count = handler.irq_count.load(Relaxed);
+ let first_pending = handler.first_pending.load(Relaxed);
+ let second_pending = handler.second_pending.load(Relaxed);
+ let residual = tree.leaf(doorbell).read_pending(bar).pending_bits();
+
+ // The self-test runs before GSP boot on a leaf that `drain` has just cleared, and nothing
+ // triggers the vector after the second delivery, so each delivery must find the doorbell bit
+ // and nothing else, and the leaf must end clear.
+ if completed
+ && count == 2
+ && first_pending == DOORBELL_BIT
+ && second_pending == DOORBELL_BIT
+ && residual & DOORBELL_BIT == 0
+ {
+ dev_info!(
+ pdev.as_ref(),
+ "interrupt self-test: passed, subtree {}, {} deliveries\n",
+ DOORBELL_SUBTREE_INDEX,
+ count,
+ );
+ Ok(())
+ } else {
+ dev_warn!(
+ pdev.as_ref(),
+ "interrupt self-test: failed, {} of 2 deliveries, leaf[{}] pending {:#x} and {:#x}, \
+ {:#x} left set\n",
+ count,
+ DOORBELL_LEAF,
+ first_pending,
+ second_pending,
+ residual,
+ );
+ Err(if completed { EIO } else { ETIMEDOUT })
+ }
+}
diff --git a/drivers/gpu/nova-core/irq/interrupt_tree.rs b/drivers/gpu/nova-core/irq/interrupt_tree.rs
index 51add9f33c89..73f5afadea3e 100644
--- a/drivers/gpu/nova-core/irq/interrupt_tree.rs
+++ b/drivers/gpu/nova-core/irq/interrupt_tree.rs
@@ -270,4 +270,17 @@ pub(super) fn clear_pending(&self, bar: Bar0<'_>) {
}
}
}
+
+ /// Clears the vectors set in `vectors` (write-1-to-clear), leaving every other pending bit
+ /// set.
+ ///
+ /// A handler that services one vector uses this rather than [`Self::clear_pending`], which
+ /// clears every vector the leaf had pending.
+ pub(super) fn clear_vectors(&self, bar: Bar0<'_>, vectors: u32) {
+ if vectors != 0 {
+ if let Some(loc) = CPU_INTR_LEAF::try_at(self.index.get()) {
+ bar.write(loc, vectors.into());
+ }
+ }
+ }
}
diff --git a/drivers/gpu/nova-core/nova_core.rs b/drivers/gpu/nova-core/nova_core.rs
index dfd11dfe562c..65ce547bd44e 100644
--- a/drivers/gpu/nova-core/nova_core.rs
+++ b/drivers/gpu/nova-core/nova_core.rs
@@ -17,7 +17,7 @@
mod fsp;
mod gpu;
mod gsp;
-#[expect(dead_code)]
+#[cfg_attr(not(CONFIG_NOVA_CORE_IRQ_SELFTEST), expect(dead_code))]
mod irq;
mod mctp;
#[macro_use]
--
2.55.0
next prev parent reply other threads:[~2026-08-08 3:11 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-08 3:11 [PATCH 00/17] nova-core: GPU interrupt support and GSP event delivery John Hubbard
2026-08-08 3:11 ` [PATCH 01/17] rust: sync: completion: add wait_for_completion_timeout() John Hubbard
[not found] ` <DKK2DM3VK6TF.3KBBWP7S4A8T1@nvidia.com>
2026-08-09 21:43 ` John Hubbard
2026-08-08 3:11 ` [PATCH 02/17] rust: pci: expose the whole interrupt vector allocation John Hubbard
2026-08-09 13:27 ` Danilo Krummrich
2026-08-08 3:11 ` [PATCH 03/17] rust: pci: expose the allocated interrupt type John Hubbard
2026-08-09 13:24 ` Danilo Krummrich
2026-08-09 21:42 ` John Hubbard
2026-08-08 3:11 ` [PATCH 04/17] gpu: nova-core: allocate PCI MSI vector during probe John Hubbard
2026-08-08 3:11 ` [PATCH 05/17] gpu: nova-core: add the GIN CPU interrupt tree and MSI EOI registers John Hubbard
2026-08-08 3:11 ` [PATCH 06/17] gpu: nova-core: add the GIN interrupt tree API John Hubbard
2026-08-08 3:11 ` [PATCH 07/17] gpu: nova-core: add the per-architecture GIN CPU interrupt HAL John Hubbard
2026-08-08 3:11 ` [PATCH 08/17] gpu: nova-core: allocate interrupt vectors for the serviced subtrees John Hubbard
2026-08-08 3:11 ` John Hubbard [this message]
2026-08-08 3:11 ` [PATCH 10/17] gpu: nova-core: dispatch GSP events instead of discarding them John Hubbard
2026-08-08 3:11 ` [PATCH 11/17] gpu: nova-core: match GSP RPC replies by sequence, not just function John Hubbard
2026-08-08 3:11 ` [PATCH 12/17] gpu: nova-core: recover the GSP receive path from corrupt framing John Hubbard
2026-08-08 3:11 ` [PATCH 13/17] gpu: nova-core: bound a GSP wait by a single deadline John Hubbard
2026-08-08 3:11 ` [PATCH 14/17] gpu: nova-core: drive GSP events with the SWGEN0 interrupt John Hubbard
2026-08-08 3:11 ` [PATCH 15/17] gpu: nova-core: retrigger the GSP falcon and clear every latched cause John Hubbard
2026-08-08 3:11 ` [PATCH 16/17] gpu: nova-core: add KUnit tests for the interrupt tree and HALs John Hubbard
2026-08-08 3:11 ` [PATCH 17/17] gpu: nova-core: document the GIN interrupt controller and GSP events 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=20260808031120.363869-10-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=joel@joelfernandes.org \
--cc=joelagnelf@nvidia.com \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=nova-gpu@lists.linux.dev \
--cc=ojeda@kernel.org \
--cc=shashanks@nvidia.com \
--cc=simona@ffwll.ch \
--cc=tmgross@umich.edu \
--cc=ttabi@nvidia.com \
--cc=wpierce@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