From c1e902ded4d39adbce88035061529ca4385477d0 Mon Sep 17 00:00:00 2001 From: Chromatischer Date: Thu, 17 Sep 2026 15:21:48 +0200 Subject: [PATCH] drm: apple: don't latch ->crashed when the poweroff clear swap times out iomfb_poweroff() submits a clear swap and waits 50 ms for it. When the display is a Type-C output that has already been unplugged, the firmware has nothing left to swap to and swallows the request: IOMFB: swap_submit_dcp: swallowed swap ID 1348 as fControllerPowerState is 0 for External Display The completion misses its window, the wait times out, and ->crashed is set with nothing logged. dcp_crtc_atomic_check() then returns -EINVAL for every commit on that CRTC, so the next plug trains the link, reads a 256-byte EDID and a full mode list, and reports the connector as connected -- while the screen stays dark. The compositor walks every mode down to 640x480, has each one rejected, and gives up. Only a reboot clears it. One unplug is enough to reach that state. The DCP has not crashed: a real firmware crash arrives through dcp_rtk_crashed(), which sets the same flag and says so. A swallowed clear swap on the way down is the ordinary unplug. Warn instead, and keep the early return. Carrying on into iomfb_abort_swaps_dcp() and setPowerState(0) leaves less state behind and matches what the setPowerState(0) wait further down already does on its own timeout, so it was tried first -- but for a display that is already gone it is worse. The dptx HPD deassert then fails: apple-dcp 271c00000.dcp: failed to deassert Type-C DPTX HPD: -110 and the next plug borrows the route and reports connected=0 without ever asserting HPD, so the display does not come back at all. The early return is load-bearing. Tested on J313 (M1 MacBook Air, t8103) with a Type-C to HDMI adapter. Plug, unplug, replug and suspend/resume all bring the display back; before, one unplug left it enumerated but unusable for the rest of the boot. Signed-off-by: Chromatischer Assisted-by: Claude:claude-opus-5 --- drivers/gpu/drm/apple/iomfb_template.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/apple/iomfb_template.c b/drivers/gpu/drm/apple/iomfb_template.c index c0b533c4f8a3c7..eeca899917f10a 100644 --- a/drivers/gpu/drm/apple/iomfb_template.c +++ b/drivers/gpu/drm/apple/iomfb_template.c @@ -936,7 +936,15 @@ void DCP_FW_NAME(iomfb_poweroff)(struct apple_dcp *dcp) swap_id = cookie->swap_id; kref_put(&cookie->refcount, release_swap_cookie); if (ret <= 0) { - dcp->crashed = true; + /* + * An unplugged display leaves this swap unacknowledged. That + * is not a crash, and ->crashed rejects every later commit on + * this CRTC until reboot. Return rather than continuing the + * teardown: that path fails the dptx HPD deassert and the + * display never comes back. + */ + dev_warn(dcp->dev, + "poweroff: clear swap did not complete in 50 ms\n"); return; }