* [PATCH 0/2] drm/nouveau: nv04 FIFO cleanup + recovery for Tesla
@ 2026-05-13 17:50 Marek Czernohous
2026-05-13 17:50 ` [PATCH 1/2] drm/nouveau/fifo/nv04: filter benign CACHE_ERROR from Mesa NV50 bind probe Marek Czernohous
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: Marek Czernohous @ 2026-05-13 17:50 UTC (permalink / raw)
To: nouveau
Cc: Lyude Paul, Danilo Krummrich, dri-devel, linux-kernel, Marek Czernohous
Hi all,
Two-patch series for the legacy nv04_fifo path covering Tesla
(MCP77/MCP79 and G80-GT218). Daily-driven on the reference NVAC
hardware (Apple Mac mini Late 2009, GeForce 9400M) since 2026-05-05.
Patch 1 demotes a benign CACHE_ERROR that fires once per Mesa session
start on Tesla GPUs. The Mesa NV50 userspace driver issues a method-
0x0060 / data-0xbeef02xx binding probe that recovers cleanly via
nv04_fifo_swmthd(), but currently logs at error level on every X or
Wayland session, dominating dmesg noise on this hardware class. This
clears the channel for patch 2 to identify real faults from noise.
Patch 2 adds a two-tier fault-recovery path for Tesla FIFO faults:
Tier 1 (per fault). Look up the channel via nvkm_chan_get_chid,
call nvkm_chan_error(chan, true), fire tracepoint
nouveau:fifo_chan_killed. Idempotent through the existing
chan->errored short-circuit.
Tier 2 (sliding window). When the per-fifo fault count in a
configurable window reaches the threshold, schedule a worker that
calls drm_dev_wedged_event(drm, DRM_WEDGE_RECOVERY_REBIND, NULL)
and fires tracepoint nouveau:fifo_dev_wedged. Worker context is
needed because kobject_uevent_env may sleep.
Motivation: Fermi+ gets channel-kill and device-wedge automatically
through nvkm_runl_rc; Tesla was feature-frozen before the DRM wedge
uAPI existed. Three observable consequences on the reference
hardware:
1. Silent state corruption (channel produces wrong output after a
fault, no notice to userspace).
2. Observability gap (no counters, tracepoints, or wedge event,
only dmesg).
3. Repeated-fault loop (the log-and-reset cycle repeats forever on
a persistently faulting channel instead of killing it).
Validation. A debugfs fault-injector (kept on a separate
DO-NOT-MERGE branch, not part of this submission) was used to drive
both Tier-1 and Tier-2 paths through their full state space. Phases
1-5 of the test plan were exercised that way. Phase 6 (no manual
injection, real workload soak) ran 2026-05-05 through 2026-05-13:
one organic DRM_WEDGE_RECOVERY_REBIND event was captured on
2026-05-05 09:08; the rest of the soak was fault-free.
Companion userland tool nouveau-pstate-daemon v0.2.0 [1] subscribes
to the WEDGED=rebind uevent in log-only mode and was used to confirm
end-to-end propagation through udev.
Module parameters:
nouveau.fifo_wedge_count (uint, 0..32, default 10)
nouveau.fifo_wedge_window_ms (uint, 100..600000, default 60000)
Setting fifo_wedge_count=0 disables Tier-2 entirely while keeping
Tier-1 channel-kill active.
A note on MAINTAINERS. The series adds a new file
drivers/gpu/drm/nouveau/nvkm/engine/fifo/recover.c. The change is
covered by the existing nouveau MAINTAINERS section
(drivers/gpu/drm/nouveau/), so no MAINTAINERS update is included.
checkpatch.pl flags this as a hint; it is not load-bearing.
This is a follow-up to the April 9 NVAC stability series [2], which
is still awaiting review. The two patches here are independent of
that series and apply against current Linus master.
[1] https://github.com/hibbes/nouveau-pstate-daemon (v0.2.0)
[2] https://lore.kernel.org/dri-devel/20260409-nouveau-nvac-stability-series
Marek Czernohous (2):
drm/nouveau/fifo/nv04: filter benign CACHE_ERROR from Mesa NV50 bind
probe
drm/nouveau/fifo: add recovery path for Tesla cache_error/dma_pusher
.../drm/nouveau/include/nvkm/engine/fifo.h | 12 ++
.../include/trace/events/nouveau_fifo.h | 58 +++++++++
drivers/gpu/drm/nouveau/nouveau_drm.c | 29 +++++
.../gpu/drm/nouveau/nvkm/engine/fifo/Kbuild | 1 +
.../gpu/drm/nouveau/nvkm/engine/fifo/base.c | 3 +
.../gpu/drm/nouveau/nvkm/engine/fifo/nv04.c | 29 ++++-
.../gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 10 ++
.../drm/nouveau/nvkm/engine/fifo/recover.c | 121 ++++++++++++++++++
8 files changed, 257 insertions(+), 6 deletions(-)
create mode 100644 drivers/gpu/drm/nouveau/include/trace/events/nouveau_fifo.h
create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/recover.c
base-commit: 1f63dd8ca0dc05a8272bb8155f643c691d29bb11
--
2.53.0
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH 1/2] drm/nouveau/fifo/nv04: filter benign CACHE_ERROR from Mesa NV50 bind probe 2026-05-13 17:50 [PATCH 0/2] drm/nouveau: nv04 FIFO cleanup + recovery for Tesla Marek Czernohous @ 2026-05-13 17:50 ` Marek Czernohous 2026-05-13 17:50 ` [PATCH 2/2] drm/nouveau/fifo: add recovery path for Tesla cache_error/dma_pusher Marek Czernohous ` (2 subsequent siblings) 3 siblings, 0 replies; 6+ messages in thread From: Marek Czernohous @ 2026-05-13 17:50 UTC (permalink / raw) To: nouveau Cc: Lyude Paul, Danilo Krummrich, dri-devel, linux-kernel, Marek Czernohous The Mesa userspace driver issues a method-0x0060 / data-0xbeef02xx binding probe on Tesla GPUs that ends up triggering CACHE_ERROR in the PFIFO interrupt handler. The probe is harmless and recovers cleanly, but it floods dmesg at error level on every X/Wayland session start. Filter that specific pattern down to debug level so dmesg stays clean while real CACHE_ERROR conditions are still logged at error level. Tested on Apple Mac Mini (MCP79, NVAC 0xac080b1) and a G94: dmesg has no CACHE_ERROR spam during normal operation, the previously visible beef02xx pattern now only appears at debug level. Signed-off-by: Marek Czernohous <marek@czernohous.de> --- .../gpu/drm/nouveau/nvkm/engine/fifo/nv04.c | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c index c4b8e567d86f..fa13cd55b593 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c @@ -327,12 +327,25 @@ nv04_fifo_intr_cache_error(struct nvkm_fifo *fifo, u32 chid, u32 get) if (!(pull0 & 0x00000100) || !nv04_fifo_swmthd(device, chid, mthd, data)) { - chan = nvkm_chan_get_chid(&fifo->engine, chid, &flags); - nvkm_error(subdev, "CACHE_ERROR - " - "ch %d [%s] subc %d mthd %04x data %08x\n", - chid, chan ? chan->name : "unknown", - (mthd >> 13) & 7, mthd & 0x1ffc, data); - nvkm_chan_put(&chan, flags); + /* + * Filter benign Mesa NV50 bind probe: mthd 0x0060 with + * data 0xbeef02xx is a harmless userspace probe on Tesla + * GPUs and does not indicate an actual error condition. + * Demote to debug to keep dmesg clean while still catching + * real CACHE_ERROR events. + */ + if ((mthd & 0x1ffc) == 0x0060 && + (data & 0xffffff00) == 0xbeef0200) { + nvkm_debug(subdev, "CACHE_ERROR - ch %d subc %d mthd %04x data %08x (benign, skipped)\n", + chid, (mthd >> 13) & 7, mthd & 0x1ffc, data); + } else { + chan = nvkm_chan_get_chid(&fifo->engine, chid, &flags); + nvkm_error(subdev, "CACHE_ERROR - " + "ch %d [%s] subc %d mthd %04x data %08x\n", + chid, chan ? chan->name : "unknown", + (mthd >> 13) & 7, mthd & 0x1ffc, data); + nvkm_chan_put(&chan, flags); + } } nvkm_wr32(device, NV04_PFIFO_CACHE1_DMA_PUSH, 0); -- 2.53.0 ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/2] drm/nouveau/fifo: add recovery path for Tesla cache_error/dma_pusher 2026-05-13 17:50 [PATCH 0/2] drm/nouveau: nv04 FIFO cleanup + recovery for Tesla Marek Czernohous 2026-05-13 17:50 ` [PATCH 1/2] drm/nouveau/fifo/nv04: filter benign CACHE_ERROR from Mesa NV50 bind probe Marek Czernohous @ 2026-05-13 17:50 ` Marek Czernohous 2026-05-19 22:01 ` [PATCH 0/2] drm/nouveau: nv04 FIFO cleanup + recovery for Tesla lyude 2026-07-25 18:59 ` Marek Czernohous 3 siblings, 0 replies; 6+ messages in thread From: Marek Czernohous @ 2026-05-13 17:50 UTC (permalink / raw) To: nouveau Cc: Lyude Paul, Danilo Krummrich, dri-devel, linux-kernel, Marek Czernohous On Tesla / NV50 family chipsets (nv50, g84, g94, g98, mcp77, mcp79), FIFO fault handling in nv04_fifo_intr_cache_error and nv04_fifo_intr_dma_pusher logs the fault and resets hardware registers but leaves the offending channel running. Compared to Fermi+ which calls nvkm_chan_error from nvkm_runl_rc, Tesla has no escalation: silent state corruption is possible, no telemetry beyond dmesg, and repeated faults on the same channel keep firing forever. Add a shared recovery helper nv04_fifo_recover() that both intr handlers call after the existing logging+reset sequence. It implements two tiers: Tier-1 (per-fault): nvkm_chan_get_chid + nvkm_chan_error(chan, true). The atomic chan->errored short-circuit means re-faults on the same channel are no-op; other channels are unaffected. Tier-2 (sliding-window): per-fifo lock-protected ring of fault timestamps. When the count within fifo_wedge_window_ms reaches fifo_wedge_count, schedule a workqueue job that emits a drm_dev_wedged_event with DRM_WEDGE_RECOVERY_REBIND. The drm_dev_wedged_event call cannot run from IRQ context because kobject_uevent_env may sleep; the workqueue indirection handles this. Tracepoints (nouveau:fifo_chan_killed, nouveau:fifo_dev_wedged) provide zero-overhead telemetry consumable via perf or bpftrace. Module parameters fifo_wedge_count (default 10, range 0..32, 0=Tier-2 disabled) and fifo_wedge_window_ms (default 60000, range 100..600000) allow tuning without rebuild. Validated on Apple Mac mini Late 2009 (NVAC, MCP79). Signed-off-by: Marek Czernohous <marek@czernohous.de> --- .../drm/nouveau/include/nvkm/engine/fifo.h | 12 ++ .../include/trace/events/nouveau_fifo.h | 58 +++++++++ drivers/gpu/drm/nouveau/nouveau_drm.c | 29 +++++ .../gpu/drm/nouveau/nvkm/engine/fifo/Kbuild | 1 + .../gpu/drm/nouveau/nvkm/engine/fifo/base.c | 3 + .../gpu/drm/nouveau/nvkm/engine/fifo/nv04.c | 4 + .../gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 10 ++ .../drm/nouveau/nvkm/engine/fifo/recover.c | 121 ++++++++++++++++++ 8 files changed, 238 insertions(+) create mode 100644 drivers/gpu/drm/nouveau/include/trace/events/nouveau_fifo.h create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/fifo/recover.c diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index 96c16cfccf16..7c27b4c8a212 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -55,6 +55,17 @@ void nvkm_chan_put(struct nvkm_chan **, unsigned long irqflags); struct nvkm_chan *nvkm_uchan_chan(struct nvkm_object *); +#define NVKM_FIFO_WEDGE_RING_MAX 32 + +struct nvkm_fifo_wedge { + spinlock_t lock; + u32 count; /* aktuelle Fenster-Tiefe */ + ktime_t ts[NVKM_FIFO_WEDGE_RING_MAX]; /* Ring von Timestamps */ + u32 head; /* Ring-Head */ + struct work_struct work; /* schedules drm_dev_wedged_event */ + atomic_t wedged; /* Tier-2 already fired? */ +}; + struct nvkm_fifo { const struct nvkm_fifo_func *func; struct nvkm_engine engine; @@ -86,6 +97,7 @@ struct nvkm_fifo { spinlock_t lock; struct mutex mutex; + struct nvkm_fifo_wedge wedge; }; void nvkm_fifo_fault(struct nvkm_fifo *, struct nvkm_fault_data *); diff --git a/drivers/gpu/drm/nouveau/include/trace/events/nouveau_fifo.h b/drivers/gpu/drm/nouveau/include/trace/events/nouveau_fifo.h new file mode 100644 index 000000000000..46d043a82850 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/trace/events/nouveau_fifo.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: MIT */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM nouveau + +#if !defined(_TRACE_NOUVEAU_FIFO_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_NOUVEAU_FIFO_H + +#include <linux/tracepoint.h> +#include <drm/drm_device.h> + +TRACE_EVENT(nouveau_fifo_chan_killed, + TP_PROTO(struct drm_device *dev, u32 chid, u32 fault_type, u64 info), + TP_ARGS(dev, chid, fault_type, info), + TP_STRUCT__entry( + __string(devname, dev_name(dev->dev)) + __field(u32, chid) + __field(u32, fault_type) + __field(u64, info) + ), + TP_fast_assign( + __assign_str(devname); + __entry->chid = chid; + __entry->fault_type = fault_type; + __entry->info = info; + ), + TP_printk("dev=%s chid=%u fault=%s info=0x%llx", + __get_str(devname), + __entry->chid, + __entry->fault_type == 0 ? "CACHE_ERROR" : "DMA_PUSHER", + __entry->info) +); + +TRACE_EVENT(nouveau_fifo_dev_wedged, + TP_PROTO(struct drm_device *dev, u32 fault_count, u32 window_ms), + TP_ARGS(dev, fault_count, window_ms), + TP_STRUCT__entry( + __string(devname, dev_name(dev->dev)) + __field(u32, fault_count) + __field(u32, window_ms) + ), + TP_fast_assign( + __assign_str(devname); + __entry->fault_count = fault_count; + __entry->window_ms = window_ms; + ), + TP_printk("dev=%s wedged after %u faults in %u ms", + __get_str(devname), + __entry->fault_count, + __entry->window_ms) +); + +#endif /* _TRACE_NOUVEAU_FIFO_H */ + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH ../../drivers/gpu/drm/nouveau/include/trace/events +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE nouveau_fifo +#include <trace/define_trace.h> diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 517ff2c31dce..c62b7fc3a1d3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -22,6 +22,8 @@ * Authors: Ben Skeggs */ +#define CREATE_TRACE_POINTS + #include <linux/aperture.h> #include <linux/delay.h> #include <linux/module.h> @@ -74,6 +76,9 @@ #include "nouveau_uvmm.h" #include "nouveau_sched.h" +#include <engine/fifo.h> +#include <trace/events/nouveau_fifo.h> + DECLARE_DYNDBG_CLASSMAP(drm_debug_classes, DD_CLASS_TYPE_DISJOINT_BITS, 0, "DRM_UT_CORE", "DRM_UT_DRIVER", @@ -111,6 +116,18 @@ MODULE_PARM_DESC(runpm, "disable (0), force enable (1), optimus only default (-1 static int nouveau_runtime_pm = -1; module_param_named(runpm, nouveau_runtime_pm, int, 0400); +MODULE_PARM_DESC(fifo_wedge_count, + "FIFO faults within window before drm_dev_wedged_event " + "(0=disable Tier-2, max 32, default 10)"); +unsigned int nouveau_fifo_wedge_count = 10; +module_param_named(fifo_wedge_count, nouveau_fifo_wedge_count, uint, 0400); + +MODULE_PARM_DESC(fifo_wedge_window_ms, + "Sliding-window width in milliseconds for fifo_wedge_count " + "(default 60000)"); +unsigned int nouveau_fifo_wedge_window_ms = 60000; +module_param_named(fifo_wedge_window_ms, nouveau_fifo_wedge_window_ms, uint, 0400); + static struct drm_driver driver_stub; static struct drm_driver driver_pci; static struct drm_driver driver_platform; @@ -1495,6 +1512,18 @@ nouveau_drm_init(void) if (!nouveau_modeset) return 0; + if (nouveau_fifo_wedge_count > NVKM_FIFO_WEDGE_RING_MAX) { + pr_warn("nouveau: fifo_wedge_count=%u exceeds max %u; clamping\n", + nouveau_fifo_wedge_count, NVKM_FIFO_WEDGE_RING_MAX); + nouveau_fifo_wedge_count = NVKM_FIFO_WEDGE_RING_MAX; + } + if (nouveau_fifo_wedge_window_ms < 100 || + nouveau_fifo_wedge_window_ms > 600000) { + pr_warn("nouveau: fifo_wedge_window_ms=%u out of range; resetting to 60000\n", + nouveau_fifo_wedge_window_ms); + nouveau_fifo_wedge_window_ms = 60000; + } + nouveau_module_debugfs_init(); #ifdef CONFIG_NOUVEAU_PLATFORM_DRIVER diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild index 376e9c3bcb1a..1ff29753731d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild @@ -5,6 +5,7 @@ nvkm-y += nvkm/engine/fifo/chan.o nvkm-y += nvkm/engine/fifo/chid.o nvkm-y += nvkm/engine/fifo/runl.o nvkm-y += nvkm/engine/fifo/runq.o +nvkm-y += nvkm/engine/fifo/recover.o nvkm-y += nvkm/engine/fifo/nv04.o nvkm-y += nvkm/engine/fifo/nv10.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index 9dd924694306..a61183fa38af 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -337,6 +337,8 @@ nvkm_fifo_dtor(struct nvkm_engine *engine) struct nvkm_runl *runl, *runt; struct nvkm_runq *runq, *rtmp; + nv04_fifo_wedge_fini(fifo); + if (fifo->userd.bar1) nvkm_vmm_put(nvkm_bar_bar1_vmm(engine->subdev.device), &fifo->userd.bar1); nvkm_memory_unref(&fifo->userd.mem); @@ -390,6 +392,7 @@ nvkm_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device, fifo->timeout.chan_msec = 10000; spin_lock_init(&fifo->lock); mutex_init(&fifo->mutex); + nv04_fifo_wedge_init(fifo); return nvkm_engine_ctor(&nvkm_fifo, device, type, inst, true, &fifo->engine); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c index fa13cd55b593..cb81941ecccd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c @@ -345,6 +345,8 @@ nv04_fifo_intr_cache_error(struct nvkm_fifo *fifo, u32 chid, u32 get) chid, chan ? chan->name : "unknown", (mthd >> 13) & 7, mthd & 0x1ffc, data); nvkm_chan_put(&chan, flags); + nv04_fifo_recover(fifo, chid, NV04_FAULT_CACHE_ERROR, + ((u64)mthd << 32) | data); } } @@ -410,6 +412,8 @@ nv04_fifo_intr_dma_pusher(struct nvkm_fifo *fifo, u32 chid) } nvkm_chan_put(&chan, flags); + nv04_fifo_recover(fifo, chid, NV04_FAULT_DMA_PUSHER, state); + nvkm_wr32(device, 0x003228, 0x00000000); nvkm_wr32(device, 0x003220, 0x00000001); nvkm_wr32(device, 0x002100, NV_PFIFO_INTR_DMA_PUSHER); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h index fff1428ef267..bf551906dcd4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h @@ -83,6 +83,16 @@ void nv04_chan_start(struct nvkm_chan *); void nv04_chan_stop(struct nvkm_chan *); void nv04_eobj_ramht_del(struct nvkm_chan *, int); +/* Recovery helper for Tesla cache_error/dma_pusher (recover.c). */ +#define NV04_FAULT_CACHE_ERROR 0 +#define NV04_FAULT_DMA_PUSHER 1 + +void nv04_fifo_recover(struct nvkm_fifo *fifo, u32 chid, u32 fault_type, u64 info); +void nv04_fifo_wedge_init(struct nvkm_fifo *fifo); +void nv04_fifo_wedge_fini(struct nvkm_fifo *fifo); +extern unsigned int nouveau_fifo_wedge_count; +extern unsigned int nouveau_fifo_wedge_window_ms; + int nv10_fifo_chid_nr(struct nvkm_fifo *); int nv50_fifo_chid_nr(struct nvkm_fifo *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/recover.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/recover.c new file mode 100644 index 000000000000..14c0eebf7040 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/recover.c @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: MIT +/* + * nv04_fifo_recover - shared recovery helper for Tesla cache_error and + * dma_pusher fault paths. + * + * Tier-1: kill the offending channel via nvkm_chan_error. + * Tier-2: after a configurable burst of faults within a sliding time + * window, request a device-wide drm_dev_wedged_event so userspace + * can rebind the driver. + */ + +#include "priv.h" +#include "chan.h" + +#include <core/device.h> +#include <subdev/timer.h> + +#include <linux/workqueue.h> +#include <linux/jiffies.h> +#include <linux/ktime.h> +#include <drm/drm_drv.h> +#include <drm/drm_device.h> + +#include "nouveau_drv.h" +#include <trace/events/nouveau_fifo.h> + +static struct drm_device * +nv04_fifo_drm_device(struct nvkm_fifo *fifo) +{ + struct nvkm_device *device = fifo->engine.subdev.device; + struct nouveau_drm *drm = dev_get_drvdata(device->dev); + + return (drm && drm->dev) ? drm->dev : NULL; +} + +void +nv04_fifo_recover(struct nvkm_fifo *fifo, u32 chid, u32 fault_type, u64 info) +{ + struct drm_device *drm_dev = nv04_fifo_drm_device(fifo); + struct nvkm_chan *chan; + unsigned long flags; + ktime_t now, cutoff; + u32 i, count; + + if (drm_dev) + trace_nouveau_fifo_chan_killed(drm_dev, chid, fault_type, info); + + chan = nvkm_chan_get_chid(&fifo->engine, chid, &flags); + if (chan) { + nvkm_chan_error(chan, true); + nvkm_chan_put(&chan, flags); + } + + if (nouveau_fifo_wedge_count == 0) + return; + + now = ktime_get(); + cutoff = ktime_sub_ms(now, nouveau_fifo_wedge_window_ms); + + spin_lock_irqsave(&fifo->wedge.lock, flags); + + /* Insert current first, then purge expired and count survivors. */ + fifo->wedge.ts[fifo->wedge.head] = now; + fifo->wedge.head = (fifo->wedge.head + 1) % NVKM_FIFO_WEDGE_RING_MAX; + + count = 0; + for (i = 0; i < NVKM_FIFO_WEDGE_RING_MAX; i++) { + if (!ktime_to_ns(fifo->wedge.ts[i])) + continue; + if (ktime_before(fifo->wedge.ts[i], cutoff)) + fifo->wedge.ts[i] = 0; + else + count++; + } + fifo->wedge.count = count; + + if (count >= nouveau_fifo_wedge_count) + schedule_work(&fifo->wedge.work); + + spin_unlock_irqrestore(&fifo->wedge.lock, flags); +} + +static void +nv04_fifo_wedge_work(struct work_struct *work) +{ + struct nvkm_fifo_wedge *w = container_of(work, struct nvkm_fifo_wedge, work); + struct nvkm_fifo *fifo = container_of(w, struct nvkm_fifo, wedge); + struct drm_device *drm_dev = nv04_fifo_drm_device(fifo); + u32 fault_count; + + if (atomic_xchg(&w->wedged, 1) != 0) + return; /* already wedged this cycle */ + + if (!drm_dev) + return; + + fault_count = w->count; + + dev_info(drm_dev->dev, + "nouveau: fifo wedged after %u faults in %u ms\n", + fault_count, nouveau_fifo_wedge_window_ms); + + trace_nouveau_fifo_dev_wedged(drm_dev, fault_count, + nouveau_fifo_wedge_window_ms); + + drm_dev_wedged_event(drm_dev, DRM_WEDGE_RECOVERY_REBIND, NULL); +} + +void +nv04_fifo_wedge_init(struct nvkm_fifo *fifo) +{ + spin_lock_init(&fifo->wedge.lock); + INIT_WORK(&fifo->wedge.work, nv04_fifo_wedge_work); + atomic_set(&fifo->wedge.wedged, 0); +} + +void +nv04_fifo_wedge_fini(struct nvkm_fifo *fifo) +{ + cancel_work_sync(&fifo->wedge.work); +} -- 2.53.0 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 0/2] drm/nouveau: nv04 FIFO cleanup + recovery for Tesla 2026-05-13 17:50 [PATCH 0/2] drm/nouveau: nv04 FIFO cleanup + recovery for Tesla Marek Czernohous 2026-05-13 17:50 ` [PATCH 1/2] drm/nouveau/fifo/nv04: filter benign CACHE_ERROR from Mesa NV50 bind probe Marek Czernohous 2026-05-13 17:50 ` [PATCH 2/2] drm/nouveau/fifo: add recovery path for Tesla cache_error/dma_pusher Marek Czernohous @ 2026-05-19 22:01 ` lyude 2026-05-20 4:27 ` Marek Czernohous 2026-07-25 18:59 ` Marek Czernohous 3 siblings, 1 reply; 6+ messages in thread From: lyude @ 2026-05-19 22:01 UTC (permalink / raw) To: Marek Czernohous, nouveau Cc: Danilo Krummrich, dri-devel, linux-kernel, Marek Czernohous Hey! I truly apologize for asking, and thank you tremendously in advance if the answer is no. But I had to check since I haven't seen you around before, and these are unusually long commit messages: These patches were written by a person correct? If not, you need to follow the coding assistants guidelines here: https://docs.kernel.org/process/coding-assistants.html On Wed, 2026-05-13 at 19:50 +0200, Marek Czernohous wrote: > Hi all, > > Two-patch series for the legacy nv04_fifo path covering Tesla > (MCP77/MCP79 and G80-GT218). Daily-driven on the reference NVAC > hardware (Apple Mac mini Late 2009, GeForce 9400M) since 2026-05-05. > > Patch 1 demotes a benign CACHE_ERROR that fires once per Mesa session > start on Tesla GPUs. The Mesa NV50 userspace driver issues a method- > 0x0060 / data-0xbeef02xx binding probe that recovers cleanly via > nv04_fifo_swmthd(), but currently logs at error level on every X or > Wayland session, dominating dmesg noise on this hardware class. This > clears the channel for patch 2 to identify real faults from noise. > > Patch 2 adds a two-tier fault-recovery path for Tesla FIFO faults: > > Tier 1 (per fault). Look up the channel via nvkm_chan_get_chid, > call nvkm_chan_error(chan, true), fire tracepoint > nouveau:fifo_chan_killed. Idempotent through the existing > chan->errored short-circuit. > > Tier 2 (sliding window). When the per-fifo fault count in a > configurable window reaches the threshold, schedule a worker that > calls drm_dev_wedged_event(drm, DRM_WEDGE_RECOVERY_REBIND, NULL) > and fires tracepoint nouveau:fifo_dev_wedged. Worker context is > needed because kobject_uevent_env may sleep. > > Motivation: Fermi+ gets channel-kill and device-wedge automatically > through nvkm_runl_rc; Tesla was feature-frozen before the DRM wedge > uAPI existed. Three observable consequences on the reference > hardware: > > 1. Silent state corruption (channel produces wrong output after a > fault, no notice to userspace). > 2. Observability gap (no counters, tracepoints, or wedge event, > only dmesg). > 3. Repeated-fault loop (the log-and-reset cycle repeats forever on > a persistently faulting channel instead of killing it). > > Validation. A debugfs fault-injector (kept on a separate > DO-NOT-MERGE branch, not part of this submission) was used to drive > both Tier-1 and Tier-2 paths through their full state space. Phases > 1-5 of the test plan were exercised that way. Phase 6 (no manual > injection, real workload soak) ran 2026-05-05 through 2026-05-13: > one organic DRM_WEDGE_RECOVERY_REBIND event was captured on > 2026-05-05 09:08; the rest of the soak was fault-free. > > Companion userland tool nouveau-pstate-daemon v0.2.0 [1] subscribes > to the WEDGED=rebind uevent in log-only mode and was used to confirm > end-to-end propagation through udev. > > Module parameters: > > nouveau.fifo_wedge_count (uint, 0..32, default 10) > nouveau.fifo_wedge_window_ms (uint, 100..600000, default 60000) > > Setting fifo_wedge_count=0 disables Tier-2 entirely while keeping > Tier-1 channel-kill active. > > A note on MAINTAINERS. The series adds a new file > drivers/gpu/drm/nouveau/nvkm/engine/fifo/recover.c. The change is > covered by the existing nouveau MAINTAINERS section > (drivers/gpu/drm/nouveau/), so no MAINTAINERS update is included. > checkpatch.pl flags this as a hint; it is not load-bearing. > > This is a follow-up to the April 9 NVAC stability series [2], which > is still awaiting review. The two patches here are independent of > that series and apply against current Linus master. > > [1] https://github.com/hibbes/nouveau-pstate-daemon (v0.2.0) > [2] > https://lore.kernel.org/dri-devel/20260409-nouveau-nvac-stability-series > > Marek Czernohous (2): > drm/nouveau/fifo/nv04: filter benign CACHE_ERROR from Mesa NV50 > bind > probe > drm/nouveau/fifo: add recovery path for Tesla > cache_error/dma_pusher > > .../drm/nouveau/include/nvkm/engine/fifo.h | 12 ++ > .../include/trace/events/nouveau_fifo.h | 58 +++++++++ > drivers/gpu/drm/nouveau/nouveau_drm.c | 29 +++++ > .../gpu/drm/nouveau/nvkm/engine/fifo/Kbuild | 1 + > .../gpu/drm/nouveau/nvkm/engine/fifo/base.c | 3 + > .../gpu/drm/nouveau/nvkm/engine/fifo/nv04.c | 29 ++++- > .../gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 10 ++ > .../drm/nouveau/nvkm/engine/fifo/recover.c | 121 > ++++++++++++++++++ > 8 files changed, 257 insertions(+), 6 deletions(-) > create mode 100644 > drivers/gpu/drm/nouveau/include/trace/events/nouveau_fifo.h > create mode 100644 > drivers/gpu/drm/nouveau/nvkm/engine/fifo/recover.c > > > base-commit: 1f63dd8ca0dc05a8272bb8155f643c691d29bb11 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 0/2] drm/nouveau: nv04 FIFO cleanup + recovery for Tesla 2026-05-19 22:01 ` [PATCH 0/2] drm/nouveau: nv04 FIFO cleanup + recovery for Tesla lyude @ 2026-05-20 4:27 ` Marek Czernohous 0 siblings, 0 replies; 6+ messages in thread From: Marek Czernohous @ 2026-05-20 4:27 UTC (permalink / raw) To: lyude, Marek Czernohous, nouveau Cc: Danilo Krummrich, dri-devel, linux-kernel Hi Lyude, No need to apologise, it is a completely fair question and I should have got ahead of it. To answer directly: these patches were not written by a person alone. I used Anthropic's Claude (Opus 4.7) while developing the series, to help investigate the nv04_fifo fault behaviour and to draft both the code and the commit messages. I reviewed every change myself, the series was soak-tested on the reference hardware as described in the cover letter, and I take full responsibility for it under my Signed-off-by. I missed Documentation/process/coding-assistants.rst when I prepared the series, apologies for that. The fix is to add this trailer to both patches: Assisted-by: Claude:claude-opus-4-7 I can send a v2 with that trailer right away, or fold it into the next revision together with any review feedback you have, whichever keeps things tidiest for you. For full disclosure: my earlier April series (NVAC stability, ref [2] in the cover letter) was likewise developed with Claude's assistance. It is still awaiting review, and I will make sure the trailer is in place when I revise it. Thanks for the careful review, Marek Am 20.05.26 um 00:01 schrieb lyude@redhat.com: > Hey! I truly apologize for asking, and thank you tremendously in > advance if the answer is no. But I had to check since I haven't seen > you around before, and these are unusually long commit messages: > > These patches were written by a person correct? If not, you need to > follow the coding assistants guidelines here: > > https://docs.kernel.org/process/coding-assistants.html > > On Wed, 2026-05-13 at 19:50 +0200, Marek Czernohous wrote: >> Hi all, >> >> Two-patch series for the legacy nv04_fifo path covering Tesla >> (MCP77/MCP79 and G80-GT218). Daily-driven on the reference NVAC >> hardware (Apple Mac mini Late 2009, GeForce 9400M) since 2026-05-05. >> >> Patch 1 demotes a benign CACHE_ERROR that fires once per Mesa session >> start on Tesla GPUs. The Mesa NV50 userspace driver issues a method- >> 0x0060 / data-0xbeef02xx binding probe that recovers cleanly via >> nv04_fifo_swmthd(), but currently logs at error level on every X or >> Wayland session, dominating dmesg noise on this hardware class. This >> clears the channel for patch 2 to identify real faults from noise. >> >> Patch 2 adds a two-tier fault-recovery path for Tesla FIFO faults: >> >> Tier 1 (per fault). Look up the channel via nvkm_chan_get_chid, >> call nvkm_chan_error(chan, true), fire tracepoint >> nouveau:fifo_chan_killed. Idempotent through the existing >> chan->errored short-circuit. >> >> Tier 2 (sliding window). When the per-fifo fault count in a >> configurable window reaches the threshold, schedule a worker that >> calls drm_dev_wedged_event(drm, DRM_WEDGE_RECOVERY_REBIND, NULL) >> and fires tracepoint nouveau:fifo_dev_wedged. Worker context is >> needed because kobject_uevent_env may sleep. >> >> Motivation: Fermi+ gets channel-kill and device-wedge automatically >> through nvkm_runl_rc; Tesla was feature-frozen before the DRM wedge >> uAPI existed. Three observable consequences on the reference >> hardware: >> >> 1. Silent state corruption (channel produces wrong output after a >> fault, no notice to userspace). >> 2. Observability gap (no counters, tracepoints, or wedge event, >> only dmesg). >> 3. Repeated-fault loop (the log-and-reset cycle repeats forever on >> a persistently faulting channel instead of killing it). >> >> Validation. A debugfs fault-injector (kept on a separate >> DO-NOT-MERGE branch, not part of this submission) was used to drive >> both Tier-1 and Tier-2 paths through their full state space. Phases >> 1-5 of the test plan were exercised that way. Phase 6 (no manual >> injection, real workload soak) ran 2026-05-05 through 2026-05-13: >> one organic DRM_WEDGE_RECOVERY_REBIND event was captured on >> 2026-05-05 09:08; the rest of the soak was fault-free. >> >> Companion userland tool nouveau-pstate-daemon v0.2.0 [1] subscribes >> to the WEDGED=rebind uevent in log-only mode and was used to confirm >> end-to-end propagation through udev. >> >> Module parameters: >> >> nouveau.fifo_wedge_count (uint, 0..32, default 10) >> nouveau.fifo_wedge_window_ms (uint, 100..600000, default 60000) >> >> Setting fifo_wedge_count=0 disables Tier-2 entirely while keeping >> Tier-1 channel-kill active. >> >> A note on MAINTAINERS. The series adds a new file >> drivers/gpu/drm/nouveau/nvkm/engine/fifo/recover.c. The change is >> covered by the existing nouveau MAINTAINERS section >> (drivers/gpu/drm/nouveau/), so no MAINTAINERS update is included. >> checkpatch.pl flags this as a hint; it is not load-bearing. >> >> This is a follow-up to the April 9 NVAC stability series [2], which >> is still awaiting review. The two patches here are independent of >> that series and apply against current Linus master. >> >> [1] https://github.com/hibbes/nouveau-pstate-daemon (v0.2.0) >> [2] >> https://lore.kernel.org/dri-devel/20260409-nouveau-nvac-stability-series >> >> Marek Czernohous (2): >> drm/nouveau/fifo/nv04: filter benign CACHE_ERROR from Mesa NV50 >> bind >> probe >> drm/nouveau/fifo: add recovery path for Tesla >> cache_error/dma_pusher >> >> .../drm/nouveau/include/nvkm/engine/fifo.h | 12 ++ >> .../include/trace/events/nouveau_fifo.h | 58 +++++++++ >> drivers/gpu/drm/nouveau/nouveau_drm.c | 29 +++++ >> .../gpu/drm/nouveau/nvkm/engine/fifo/Kbuild | 1 + >> .../gpu/drm/nouveau/nvkm/engine/fifo/base.c | 3 + >> .../gpu/drm/nouveau/nvkm/engine/fifo/nv04.c | 29 ++++- >> .../gpu/drm/nouveau/nvkm/engine/fifo/priv.h | 10 ++ >> .../drm/nouveau/nvkm/engine/fifo/recover.c | 121 >> ++++++++++++++++++ >> 8 files changed, 257 insertions(+), 6 deletions(-) >> create mode 100644 >> drivers/gpu/drm/nouveau/include/trace/events/nouveau_fifo.h >> create mode 100644 >> drivers/gpu/drm/nouveau/nvkm/engine/fifo/recover.c >> >> >> base-commit: 1f63dd8ca0dc05a8272bb8155f643c691d29bb11 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 0/2] drm/nouveau: nv04 FIFO cleanup + recovery for Tesla 2026-05-13 17:50 [PATCH 0/2] drm/nouveau: nv04 FIFO cleanup + recovery for Tesla Marek Czernohous ` (2 preceding siblings ...) 2026-05-19 22:01 ` [PATCH 0/2] drm/nouveau: nv04 FIFO cleanup + recovery for Tesla lyude @ 2026-07-25 18:59 ` Marek Czernohous 3 siblings, 0 replies; 6+ messages in thread From: Marek Czernohous @ 2026-07-25 18:59 UTC (permalink / raw) To: nouveau; +Cc: Lyude Paul, Danilo Krummrich, dri-devel, linux-kernel Please do not apply this series. Since sending it I have been running it on the reference machine and found three defects in it, one of which is a guaranteed crash on exactly the hardware it targets. 1) Patch 2/2 calls nvkm_chan_error(chan, true). nv50 and g84 channels have no .preempt callback and the call site in nvkm_chan_error() is not guarded, so this dereferences a NULL function pointer under chan->lock in interrupt context. It fired here on 2026-06-02 on the first CACHE_ERROR after a VRAM stress test: fifo: CACHE_ERROR - ch 2 [labwc[3950]] subc 3 mthd 0f00 data 0000007b nv04_fifo_intr_cache_error+0x111 -> nv04_fifo_recover+0x80 -> nvkm_chan_error+0x99 RIP: 0010:0x0 The oops escalated to a panic and the watchdog reset the machine. 2) Killing the channel on the first fault is wrong. There is a single PFIFO cache puller and on a fault it names the channel that is resident, not necessarily the one that caused it, as nv04_fifo_pause() already documents. Here this killed the Wayland compositor twice for faults it did not cause. 3) On Tesla a killed channel is not survivable at all. The channel-killed event is only subscribed for FERMI_CHANNEL_GPFIFO and newer, so nouveau_fence_context_kill() never runs and the pending fences of the killed channel are never signalled. The display commit tail and the TTM delayed-delete workers then wait forever, uninterruptibly. The series as posted therefore trades a recoverable fault for an unrecoverable hang. v2 fixes all three and adds a prerequisite patch for the event subscription. It is written and rebased, but I am not sending it yet: the new escalation logic has only hours of runtime here and no fault has hit it so far. I would rather restore the debugfs fault injector I used for the original validation and demonstrate the corrected paths with injected faults than post a second series that is short on evidence. That is what I am doing next. Lyude: v2 will carry the Assisted-by trailers, as offered in my reply to your question in May. Sorry for the noise, and thanks for not having applied it yet. Marek ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-07-25 18:59 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-05-13 17:50 [PATCH 0/2] drm/nouveau: nv04 FIFO cleanup + recovery for Tesla Marek Czernohous 2026-05-13 17:50 ` [PATCH 1/2] drm/nouveau/fifo/nv04: filter benign CACHE_ERROR from Mesa NV50 bind probe Marek Czernohous 2026-05-13 17:50 ` [PATCH 2/2] drm/nouveau/fifo: add recovery path for Tesla cache_error/dma_pusher Marek Czernohous 2026-05-19 22:01 ` [PATCH 0/2] drm/nouveau: nv04 FIFO cleanup + recovery for Tesla lyude 2026-05-20 4:27 ` Marek Czernohous 2026-07-25 18:59 ` Marek Czernohous
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®