Skip to content

Bound the GPFIFO-space wait in nvWriteGpEntry()#1192

Open
Lumzdas wants to merge 2 commits into
NVIDIA:mainfrom
Lumzdas:bound-gpfifo-wait
Open

Bound the GPFIFO-space wait in nvWriteGpEntry()#1192
Lumzdas wants to merge 2 commits into
NVIDIA:mainfrom
Lumzdas:bound-gpfifo-wait

Conversation

@Lumzdas

@Lumzdas Lumzdas commented Jun 11, 2026

Copy link
Copy Markdown

Bound the GPFIFO and pushbuffer waits in nvidia-push

Problem

nvWriteGpEntry() waits for a free GPFIFO entry with no timeout. __nvPushMakeRoom() waits for pushbuffer space with no timeout. Both loops exit only when the GPU makes progress or a channel error is flagged. If a channel stalls without a flagged error, the loop spins forever in kernel context. When the spinning code holds the nvkms lock, every later modeset blocks in D state and the desktop is unusable until reboot.

I hit this reproducibly with DIFR prefetch after resume from suspend. Same trace as #1167 and #1177.

Environment: RTX 5090, driver 595.71.05 open modules, NVreg_PreserveVideoMemoryAllocations enabled, kernel 7.0.3, KDE Plasma on Wayland, S3 suspend.

The nvidia-modeset kthread spins on one core:

RIP: 0010:nvWriteGpEntry+0x90/0x370 [nvidia_modeset]
Call Trace:
 nvPushKickoff+0x24/0x40 [nvidia_modeset]
 PrefetchHelperSurfaceEvo+0x5aa/0x610 [nvidia_modeset]
 nvDIFRPrefetchSurfaces+0xed/0x240 [nvidia_modeset]
 DifrPrefetchEventDeferredWork+0x16/0x30 [nvidia_modeset]

and the compositor blocks on the nvkms lock held by that thread:

task:kwin_wayland state:D
 down+0x45/0x50
 nvkms_ioctl_from_kapi_try_pmlock+0x36/0x80 [nvidia_modeset]
 ApplyModeSetConfig+0xc7a/0xe00 [nvidia_modeset]
 nv_drm_atomic_check+0x220/0x270 [nvidia_drm]

Fix

Commit 1 bounds nvWriteGpEntry() the same way IdleChannel() already does: poll nvPushImportGetMilliSeconds(), honor the channel noTimeout flag, log an error and return FALSE after NV_PUSH_NOTIFIER_SHORT_TIMEOUT. Kickoff() already handles the FALSE return.

Commit 2 bounds __nvPushMakeRoom() with the same timeout. This function returns void and callers write methods unconditionally after it returns, so on timeout it wraps the write pointer back to the buffer base and marks the whole buffer free. Each method write is asserted smaller than the buffer, so the writes stay in bounds, and they land only in the channel's own pushbuffer. The following kickoff then fails and the caller gives up. Commit 2 is needed because with only commit 1 applied the same stall spins in __nvPushMakeRoom() instead, one call earlier on the same DIFR path. Observed on my machine.

DIFR prefetch already has a failure path for a kickoff that never completes: the semaphore wait in PrefetchSingleSurface() times out and reports NV2080_CTRL_LPWR_DIFR_PREFETCH_FAIL_CE_HW_ERROR. That path was unreachable only because the waits above it could spin first.

Channels created with noTimeout = TRUE keep the old behavior.

Results

Both commits, rebased onto 595.71.05, have been running on my machine since June 25. The stall occurred six times since then, mostly within seconds of resume. Each time the desktop kept working and the driver logged:

nvidia-modeset: ERROR: GPU:0: Timed out waiting for a free GPFIFO entry.
nvidia-modeset: ERROR: GPU:0: Timed out waiting for room in the pushbuffer.

@CLAassistant

CLAassistant commented Jun 11, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@Lumzdas Lumzdas force-pushed the bound-gpfifo-wait branch from cf7592c to 2fc027e Compare June 11, 2026 11:12
With nvWriteGpEntry() bounded, the same stalled-channel scenario spins
in __nvPushMakeRoom() instead, one call earlier on the same path. Bound
it with the same NV_PUSH_NOTIFIER_SHORT_TIMEOUT / noTimeout logic. Since
this function returns void and callers write methods unconditionally
after it returns, on timeout wrap the write pointer back to the buffer
base and mark the whole buffer free so the writes stay in bounds; the
following kickoff then fails and the caller gives up.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants