Skip to content

feat(nvidia): stopped every active head with the shutdown update - #515

Merged
FlareCoding merged 2 commits into
pr/nvidia-head-serial-linksfrom
pr/nvidia-shutdown-update
Oct 29, 2026
Merged

FlareCoding merged 2 commits into
pr/nvidia-head-serial-linksfrom
pr/nvidia-shutdown-update

Conversation

@FlareCoding

@FlareCoding FlareCoding commented Oct 29, 2026 •

Copy link
Copy Markdown
Owner

Summary

Before the driver lights an output of its own, the heads the boot firmware lit (a head being one of the display engine's units that each generate one monitor's timing) must be stopped, inside a mode set (the programming of heads to drive monitors) that display common (the firmware's object for the display's connectors) is told of, as NVIDIA's modesetting module does at its first mode set. So bring-up brackets the chosen output's mode set with display common's start and end and between them, when a head is active, sends one update (the core channel method applying the methods before it) that stops every active head, and once an update was sent the driver's release does not ask to keep the hardware.

Changes

  • The chosen output's mode set is bracketed: once the window owners are read, display_engine::set_up sends display common NVIDIA's DISPLAY_CHANGE (re-declared in rm.h) with the start, naming the chosen output's display id, and with the end after everything the mode set writes, whether or not a head is active, as NVIDIA's module brackets each mode set. A refused start skips the update and the end and bring-up goes on, a refused end is logged and bring-up goes on, and any other error of either fails the set-up.
  • One update stops every active head: with a head active, shut_down_heads writes into the core channel, in NVIDIA's order, every present window's owner (its head, or none) and then every present window's usage bounds at NVIDIA's default, since the update is the first since the channel's allocation, then for each active head its cursor's context DMA 0 and control disabled, its serial link's control 0 and its display id 0 (build_shutdown_methods, core_methods.cpp).
  • The update's completion is checked: shut_down_heads clears the core channel's completion notifier (the memory the display engine writes once it has taken an update), sends one UPDATE with release ELV (the bit NVIDIA's module sets in every update of a mode set) naming the notifier, waits up to 3 seconds for the notifier to read finished, then stops later updates from writing it. Bring-up logs that the core channel read the update, with the heads it stopped and the notifier's word, and each stopped head's display id and link control as the core channel's armed state reads them.
  • The notifier's wait takes a lost notification as finished: completion_notifier::wait_finished reads the notifier's status (bits 31:30 of its first word) until it reads finished. Past its deadline it takes a core channel that read every method (GET at PUT) as a lost notification, logged as a warning, as NVIDIA's module does, and otherwise fails with ERR_TIMEOUT.
  • A failed update takes the display engine down: when a write, the notifier's wait or the stop of its writes fails, take_down writes the heads' methods again (with the window mapping only if no update was kicked) and an update naming no notifier, waits up to 5 seconds for the core channel to read it, then the bracket ends and bring-up goes on. A take-down that fails is logged at error level, saying the heads may still scan out.
  • The release keeps the hardware only before an update: once an update was sent, display_engine::release releases the window and core channels without NVIDIA's PRESERVE_HW flag (release_display_channel takes whether to keep the hardware), since the update changed the boot firmware's state.
  • Departure, the link's control: each stopped head's link is written with no head, where NVIDIA's module writes the heads still attached to it. The two differ only when two active heads share a link, and the update applies the link's last write, which carries no head in both.
  • Departure, the notifier's deadline: a core channel whose GET does not read PUT 3 seconds after the kick fails the wait and takes the display engine down, where NVIDIA's module waits on. The wait spins on the calling CPU, as bring-up's other waits do, since bring-up may run on a thread that cannot sleep, where NVIDIA's module yields between reads.
  • Departure, a head showing no output: a head whose display id names none of the outputs is stopped too, where NVIDIA's module records no link for it and leaves it running.
  • Departure, the blank: a stopped head's blank writes only its cursor's first context DMA and its control. NVIDIA's module also writes the cursor's other methods, points the head's output table at its default table, which the driver does not allocate, and flips each layer to an empty image through its window's own channel, which the driver holds only for the chosen window. A head with no link drives no monitor, so the images it still names reach none.
  • Card: on the RTX 3080 booted with the boot firmware's display, run land-shutdown-update-v5-card-1, a boot of 8c897fac, an earlier version whose kernel, stripped of debug information, is byte-identical to f1405a7's, logged nvidia: display common took the start of the mode set naming display id 0x100, nvidia: the core channel read the shutdown update for 1 active head, its completion notifier reading 0x80000000 and nvidia: after the shutdown update, head 0's display id reads 0x0 and serial link 0's control 0x0 in the core channel's armed state, then the end taken and bring-up ended with the driver attached, with 0 IOMMU or PCIe faults on the host. In run land-shutdown-update-v2-diag2-card-1, a boot of 375d9f51 with a diagnostic patch that logs head 0's armed state and fails the shutdown update without sending it, so the take-down was the boot's first update, link 0's control read 0x901 (head 0 attached) before any update, so the 0 that run land-shutdown-update-v5-card-1 read after the shutdown update shows the stop, while the display id read 0 before any update too; the screen was not captured. Run land-shutdown-update-v5-vga-1 of the same kernel, booted on QEMU's VGA, logged the start and the end with no update between them, since no head is active.
  • Tests: nvidia_completion_notifier checks that a clear writes the not-begun status, that a finished status ends the wait with every other bit set, that a begun status or status 3 with GET not at PUT times out only past the deadline and that a lost notification with GET at PUT ends the wait only past it. nvidia_core_methods checks that the first update maps the present windows before stopping the heads, that a later update only stops the active heads, that heads sharing a link each set it to carry no head and that a later update with no head active gives no methods. nvidia_core_channel checks that a release without keeping the hardware asks for no flag. nvidia_display_engine checks that a set-up brackets the chosen output's mode set with no head active, that a refused start writes nothing and sends no end, that a start failing otherwise fails the set-up with its error, writing nothing and keeping the hardware at release, that a refused end is logged and a late one fails the set-up with no take-down, that one shutdown update stops one active head and two, that the mode set ends only after the notifier's wait ran for the engine's time, which a constructed engine sets to NVIDIA's 3 seconds, that a failed notifier wait takes the display engine down, that a take-down sent as the first update maps the windows and that the mode set ends after a failed take-down.

Note

Medium Risk
Changes boot-time display engine programming and firmware mode-set controls; incorrect shutdown or release could leave heads scanning stale state, though take-down and conditional PRESERVE_HW mitigate that.

Overview
Extends NVIDIA display bring-up so the driver can stop firmware-lit heads inside a proper mode set before lighting its own output, matching NVIDIA’s first modeset sequence.

Mode set bracketing: After window owners are read, display_engine::set_up sends NV0073_CTRL_CMD_SPECIFIC_DISPLAY_CHANGE start/end around the chosen output’s display id. Refused start/end are logged and bring-up continues where appropriate; other errors fail set-up.

Shutdown update: When any head is active, shut_down_heads pushes core-channel methods from build_shutdown_methods—window owner mapping and default usage bounds on the first update, then per-head cursor disable, serial link control cleared, and display id cleared—followed by an UPDATE with release ELV that names the completion notifier, waits up to 3s via new completion_notifier::clear / wait_finished (treating “GET at PUT” after timeout as a lost notification), then clears notifier binding so later updates do not rewrite it.

Failure path: Failed shutdown triggers take_down (head methods again, optional window remap if no prior kick, update without notifier, channel idle wait) before the mode set end still runs.

Release behavior: release_display_channel gains a keeps_hardware flag; channels are released with PRESERVE_HW only if no core update was kicked yet.

LICENSE-NVIDIA and unit tests cover notifier wait semantics, shutdown method ordering, display-change sequencing, and full display_engine bring-up paths.

Reviewed by Cursor Bugbot for commit f1405a7. Bugbot is set up for automated code reviews on this repo. Configure here.

@cursor

cursor Bot commented Oct 29, 2026

Copy link
Copy Markdown

Current version of PR was reviewed by /review-bugbot with additional instructions on Oct 29, 06:35. It flagged 0 findings.

Bugbot on commit 11c673c is skipped.

Display common is told the start and end of each mode set, as NVIDIA's
driver brackets every mode set. A refusal of either is logged and
leaves the set-up OK, while any other failure of either fails it.
Bring-up stops every head found active, and once an update has changed
the boot firmware's state, the display channels are released without
keeping the hardware.
@FlareCoding
FlareCoding force-pushed the pr/nvidia-shutdown-update branch from 11c673c to f1405a7 Compare October 29, 2026 07:47
@FlareCoding
FlareCoding added this pull request to stack #519 October 29, 2026 17:48
@FlareCoding
FlareCoding merged commit b35ee81 into master Oct 29, 2026
21 of 26 checks passed
@FlareCoding
FlareCoding deleted the pr/nvidia-shutdown-update branch October 29, 2026 17:49
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.

1 participant