Conversation
On DP unplug the DCP firmware first tears down the link on its own (HPD removal, M3 power down, set_device_enabled 1 -> 0) and only then processes the clear swap queued by iomfb_poweroff(). That teardown was measured at ~53 ms, just above the 50 ms the driver waited. The timeout silently set dcp->crashed, after which dcp_crtc_atomic_check() rejects every commit on the CRTC with -EINVAL until reboot: the monitor is detected on the next plug but never gets a modeset (black screen), and the compositor cannot even disable the output. Wait up to 1000 ms, matching the setPowerState(0) wait below. Even then, a clear swap queued behind a slow operation (unplug during a modeset, or right after resume where powering on took about a second) can miss the deadline, so don't treat a timeout as a crash at all: warn and continue powering off, like the setPowerState(0) wait does. Real firmware crashes are reported via dcp_rtk_crashed(). A late reply is safe since the swap cookie is refcounted. Link: AsahiLinux#634 Signed-off-by: Alexey Makhov <makhov.alex@gmail.com>
If the RTKit crashed callback fires while iomfb_poweroff() waits for the clear swap, the wait runs into its timeout and the function then queues abort_swaps, which RTKit refuses for a crashed co-processor, and waits another second for a reply that cannot arrive. Return right after the timeout when dcp->crashed is set. This is the same exit the function took on any clear swap timeout before, so callers already handle it. The unlocked read of dcp->crashed matches dcp_crtc_atomic_check(); a stale value only means taking the previous, slower but safe path. Signed-off-by: Alexey Makhov <makhov.alex@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On a MacBookPro18,3 (M1 Pro) running fairydust, hot-plugging a USB-C DP monitor sometimes leaves it black until reboot. DP-1 is reported as connected, but every commit on the CRTC fails with
-EINVAL, and the compositor can't even disable the output. Details in #634.Root cause
iomfb_poweroff()submits a clear swap and waits 50 ms for it. On timeout it setsdcp->crashed = trueand returns without logging anything. From then ondcp_crtc_atomic_check()rejects every commit on that CRTC.On DP unplug the firmware first does its own teardown (
display HPD removed,power_down_M3,set_device_enabled_gated: 1 -> 0) and only then swallows the clear swap. On a failing unplug that took ~53 ms. The DCP keeps working normally afterwards (later hotplug callbacks and syslog messages all arrive), so this isn't a real crash. I saw the pattern in 3 separate boots.Fix
setPowerState(0)wait that follows. On timeout, warn and continue powering off, the same way thesetPowerState(0)timeout is already handled.dcp->crashedis then only set bydcp_rtk_crashed(). A longer wait alone isn't enough: a clear swap queued behind a slow operation (an unplug during a modeset, or right after resume, where powering on took about 1 s) could still miss the deadline. A late reply is safe because the swap cookie is refcounted.abort_swaps(RTKit refuses messages to a crashed co-processor) and waiting another second. This is the same exit the function took on any timeout before, so callers already handle it.How a real crash is handled is unchanged:
dcp_rtk_crashed()setsdcp->crashedand disconnects the connector, anddcp_crtc_atomic_check()rejects every commit.History: the 50 ms wait with
crashed = trueis in the original "drm/apple: Add DCP display driver" commit (f2bc92ff49a9) with no stated reason, and it most likely predates external DP hotplug.Trade-off: if the firmware hangs without RTKit reporting a crash, each poweroff now stalls for up to about 2 s instead of the pipe being rejected right away. The screen is dark either way, but this version recovers if the firmware responds again.
Not addressed here: the DRM hotplug event from the Type-C disconnect is sent before DCP has processed the unplug, so the compositor's disable always queues behind the firmware teardown.
Testing
On 7.1.13-fd-1-ARCH (fairydust
ce9f2eba72c0), 4 boots, with and without a second USB-C dock attached:#634 also describes a second failure with the same symptom (the port's cd321x stops entering DP altmode). That one is upstream of appledrm and is not fixed here.