ValveSoftware / ValveSoftware/SteamOS
[7.2.0-valve1] NULL dereference in dm_freesync_mccs_ddc_worker on MST HDMI hotplug
Nobody has claimed this yet.
- Dominant language
- No language data
- Stars
- 2.6k
- Forks
- 83
- Avg merge
- 4m
- Merged PRs (30d)
- 3
Description
Your system information
- Steam client version: 1778281814 (
steamdeck_publicbeta) - SteamOS version: 3.9.0, BUILD_ID
20260828.100, kernel7.2.0-valve1-1-neptune-72-gd39b4282853d - Opted into Steam client beta?: Yes
- Opted into SteamOS beta?: Yes (
previewbranch) - Have you checked for updates in Settings > System?: Yes — updated to 20260828.100 today; the issue persists on the new kernel exactly as on 6.16.12-valve
Hardware:
- Lenovo Legion Go S (
83N6), BIOSS0CN24WW - Dock: HP USB-C 100W G6, firmware
01.02.11.00(latest — updating the dock did not change the behaviour) - Display: TCL C6K, attached via the dock's MST connector
card0-DP-11
Please describe your issue in as much detail as possible:
Expected: attaching an external display through a DisplayPort MST dock brings up the display.
What happens: every HDMI hotplug/modeset through the dock queues dm_freesync_mccs_ddc_worker and oopses with a NULL pointer dereference in i2c_transfer. Because SteamOS ships kernel.panic_on_oops=1 with kernel.panic=-1, the oops becomes an immediate reboot, and the device enters a continuous reboot loop (2–4 second boots) for as long as the display is attached. Unplugging HDMI makes it boot and run normally.
Setting kernel.panic_on_oops=0 at runtime contains it: the worker dies, but the display then works perfectly — including 3840x2160@120Hz. That is also the only way the trace below could be captured, since with the default sysctls the journal never flushes before the reboot (it was streamed off the device over SSH).
This is not caused by DSC, EDID version, TV-side settings, dock firmware, or link bandwidth — each was varied and eliminated. A direct SST USB-C→HDMI adapter to the same TV, from the same handheld, never reproduces it; only the MST path does.
Steps for reproducing this issue:
- Attach a DisplayPort MST dock to the Legion Go S USB-C port.
- Connect an external display to the dock's HDMI output.
- The kernel oopses on modeset; with default sysctls the device reboots and loops until HDMI is disconnected.
Trace
Sep 05 14:51:10 steamdeck kernel: Oops: Oops: 0000 [#1] SMP NOPTI
Sep 05 14:51:10 steamdeck kernel: CPU: 2 UID: 0 PID: 133 Comm: kworker/2:2 Not tainted 7.2.0-valve1-1-neptune-72-gd39b4282853d #1 PREEMPT(full) 46b08c52c58762febc19b0dbaa99295faa854f5e
Sep 05 14:51:10 steamdeck kernel: Hardware name: LENOVO 83N6/LNVNB161216, BIOS S0CN24WW 07/31/2025
Sep 05 14:51:10 steamdeck kernel: Workqueue: events dm_freesync_mccs_ddc_worker [amdgpu]
Sep 05 14:51:10 steamdeck kernel: RIP: 0010:i2c_transfer+0x79/0x150
Sep 05 14:51:10 steamdeck kernel: Code: 00 00 00 48 8d 7b 28 e8 45 c2 3c 00 8b 54 24 04 85 c0 75 32 bd f5 ff ff ff eb 51 9c 58 f6 c4 02 74 ba 48 8b 43 20 89 54 24 04 <48> 8b 00 48 3d a0 56 72 a1 0f 85 8e 00 00 00 48 8d 7b 28 e8 8f d7
Sep 05 14:51:10 steamdeck kernel: RSP: 0018:ffffcd7e00627d30 EFLAGS: 00010246
Sep 05 14:51:10 steamdeck kernel: RAX: 0000000000000000 RBX: ffff8d27877c8dd0 RCX: ffff8d27877c8000
Sep 05 14:51:10 steamdeck kernel: RDX: 0000000000000001 RSI: ffffcd7e00627d60 RDI: ffff8d27877c8dd0
Sep 05 14:51:10 steamdeck kernel: RBP: ffffcd7e00627d60 R08: 8080808080808080 R09: ffff8d2b848b0fa0
Sep 05 14:51:10 steamdeck kernel: R10: ffff8d26014bed00 R11: fefefefefefefeff R12: ffff8d2b848b0f80
Sep 05 14:51:10 steamdeck kernel: R13: ffffcd7e00627e68 R14: 0000000000000000 R15: ffff8d26014bed00
Sep 05 14:51:10 steamdeck kernel: FS: 0000000000000000(0000) GS:ffff8d2be0e59000(0000) knlGS:0000000000000000
Sep 05 14:51:10 steamdeck kernel: CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
Sep 05 14:51:10 steamdeck kernel: CR2: 0000000000000000 CR3: 0000000244a20000 CR4: 0000000000f50ef0
Sep 05 14:51:10 steamdeck kernel: PKRU: 55555554
Sep 05 14:51:10 steamdeck kernel: Call Trace:
Sep 05 14:51:10 steamdeck kernel: <TASK>
Sep 05 14:51:10 steamdeck kernel: dm_freesync_mccs_ddc_worker+0x16f/0x200 [amdgpu ffaf3f8c966013d35e76f603dfcbfdc61fb9eccb]
Sep 05 14:51:10 steamdeck kernel: ? process_one_work+0x19f/0x370
Sep 05 14:51:10 steamdeck kernel: process_one_work+0x19f/0x370
Sep 05 14:51:10 steamdeck kernel: worker_thread+0x1b1/0x310
Sep 05 14:51:10 steamdeck kernel: ? __pfx_worker_thread+0x10/0x10
Sep 05 14:51:10 steamdeck kernel: kthread+0xe4/0x120
Sep 05 14:51:10 steamdeck kernel: ? __pfx_kthread+0x10/0x10
Sep 05 14:51:10 steamdeck kernel: ret_from_fork+0x2a3/0x350
Sep 05 14:51:10 steamdeck kernel: ? __pfx_kthread+0x10/0x10
Analysis
The worker was introduced by 96ea4acfb840 ("[NOT-FOR-UPSTREAM] drm/amd/display: add FreeSync MCCS implementation"). The symbol does not exist upstream.
It selects the DDC adapter with roughly:
if (aconn->dc_link->aux_mode)
adap = &aconn->dm_dp_aux.aux.ddc;
ret = i2c_transfer(adap, msgs, 1);
Correct for a physical DP connector whose embedded AUX object was initialised. Not correct for an MST virtual connector: that amdgpu_dm_connector is zero-allocated and its embedded dm_dp_aux is never initialised, yet it shares a dc_link with aux_mode == true. The worker therefore uses a zeroed adapter whose lock_ops is NULL, and i2c_transfer() faults while taking the bus lock — consistent with RAX=0, CR2=0, and the fault occurring before any transfer. The correct transport for MST is the remote port adapter (aconn->mst_output_port->aux.ddc).
Two further problems in the same path:
- The work appears to be scheduled whenever the FreeSync/VRR info packet changes, without checking whether the connector is MST or VRR-capable. This connector reports
vrr_capable=0andpassive_vrr_capable=0, yet the worker still runs. - The queued work stores a raw
aconnpointer with no lifetime reference, so unplugging betweenschedule_work()and execution looks like a use-after-free.
Suggested fix
- Gate MCCS work on a sink that actually advertises the FreeSync MCCS VCP.
- Use the MST port's remote AUX DDC adapter for MST connectors.
- Hold connector / MST-port references until the async work completes or is cancelled.
A minimal containment fix would be to skip MCCS work entirely when mst_output_port != NULL.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by locating the downstream amdgpu FreeSync MCCS implementation introduced by commit 96ea4acfb840, especially dm_freesync_mccs_ddc_worker and its scheduling path. Reproduce the MST HDMI hotplug failure and inspect adapter selection, VRR/MCCS gating, and queued connector lifetime. Done means the MST path no longer dereferences a NULL adapter or outlives its references while valid FreeSync handling remains intact.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, linux
- Domain
- computer-graphics, operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100