diff options
| author | Vishwaroop A <va@nvidia.com> | 2026-08-13 20:00:25 +0000 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2026-09-09 12:48:27 +0100 |
| commit | e329b94b1e47d1a73706bd09380bf0989fbcd4a8 (patch) | |
| tree | aef9f16062b4bdb63098d933f024e9d48cbeedfa /tools/perf/scripts/python | |
| parent | df2908090cda368b01ff43709f51890076c56157 (diff) | |
spi: tegra210-quad: Convert to hard IRQ with high-priority workqueue
Threaded IRQ handlers can be delayed by the scheduler on heavily loaded
systems, causing wait_for_completion_timeout() to expire before the
handler runs and producing false transfer timeouts. On GB200 with TPM
hwrng traffic running alongside a NCCL multicast workload this shows up
as a WARN in tegra_qspi_transfer_one_message() even though the hardware
has already signalled QSPI_RDY.
irq_thread() runs SCHED_FIFO but set_cpus_allowed_ptr()s to the IRQ
affinity mask (typically a single CPU). When that CPU is saturated by
non-preemptible kernel work on the same interrupt line (softirqs,
spinlock contention, network RX processing), the FIFO priority alone
does not help - there is nothing at lower priority to preempt. The
bottom half sits on the runqueue for milliseconds and occasionally
seconds.
Convert to a hard IRQ handler that schedules work on a WQ_HIGHPRI |
WQ_UNBOUND workqueue:
- The hard IRQ handler runs outside process-scheduler control - it
can still be delayed by higher-priority IRQ handling or local
IRQ-disabled / non-preemptible sections, but not by CFS or
RT-userspace backpressure. tegra_qspi_isr() captures FIFO / trans
status and masks the controller IRQ synchronously with the
hardware event, so the subsequent timeout classification (added
in the following patch) always sees the true state.
- The workqueue worker runs SCHED_NORMAL with HIGHPRI_NICE_LEVEL
(nice -20). A real-time SCHED_FIFO userspace task will preempt it
where it would not have preempted the old irq_thread; that is a
real trade-off. In exchange, WQ_UNBOUND lets the worker migrate
off the interrupt-taking CPU that the threaded IRQ could not
leave, which is the actual failure mode observed in the field.
The following patch (small-PIO fastpath) further removes the
worker from the latency-sensitive TPM path entirely.
The work handler only touches QSPI MMIO when curr_xfer is non-NULL.
curr_xfer is cleared only after the transfer thread has processed the
completion, and while it is set the transfer thread is blocked in
wait_for_completion_timeout() with the SPI core's runtime PM reference
held, so the clocks are guaranteed on.
The ISR returns IRQ_HANDLED unconditionally. Tegra QSPI has a
dedicated, non-shared GIC SPI line on every SoC that uses this driver,
so any spurious / late IRQ (for example after the timeout path has
cleared curr_xfer) must still be acked and re-masked here; otherwise
the level-triggered line could stay asserted and trip the kernel
spurious-IRQ detector into disabling the line ("nobody cared, try to
disable"). The lock-free curr_xfer NULL check lets the ISR bail
without touching FIFO / status when there is no transfer to drive
forward.
handle_dma_based_xfer() snapshots curr_xfer under the spinlock at
function entry and bails immediately when the timeout path has already
cleared it. This avoids waiting up to QSPI_DMA_TIMEOUT on a DMA
completion that belongs to a transfer the synchronous path has already
torn down, and keeps the subsequent dma_unmap / FIFO-drain operations
consistent with the transfer that actually started.
Resources are allocated and torn down manually so that remove() can
stop the controller, free the IRQ (preventing new work from being
queued), then destroy the workqueue (which drains any already-queued
work while the clocks are still on) before runtime PM is disabled.
Signed-off-by: Vishwaroop A <va@nvidia.com>
Link: https://patch.msgid.link/20260813200027.2711863-2-va@nvidia.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'tools/perf/scripts/python')
0 files changed, 0 insertions, 0 deletions
