Skip to content

drm/apple: don't latch ->crashed on a poweroff swap timeout - #582

Open
haripako wants to merge 1 commit into
AsahiLinux:asahifrom
haripako:drm-apple-poweroff-no-latch
Open

drm/apple: don't latch ->crashed on a poweroff swap timeout#582
haripako wants to merge 1 commit into
AsahiLinux:asahifrom
haripako:drm-apple-poweroff-no-latch

Conversation

@haripako

Copy link
Copy Markdown

iomfb_poweroff() waits 50 ms for the poweroff clear swap and, on timeout, sets
dcp->crashed and returns without logging anything.

That flag is permanent and fatal. dcp_crtc_atomic_check() opens with
if (dcp->crashed) return -EINVAL; and nothing ever clears it, so from that
moment every atomic commit for the device is rejected and the display does not
come back until reboot.

It is not a crash. After the timeout the DCP keeps working — it renegotiates the
link, publishes its mode list and asserts HPD (dcp_hotplug() connected:1 nr_modes:23). ->crashed is otherwise set only by dcp_rtk_crashed(), the
RTKit crash callback, which also logs. RTKit reported no crash in any of these
runs.

This keeps the control flow identical, leaves ->crashed alone and emits a
dev_warn so the timeout is visible at all.

How it was found

Observed on a MacBook Pro 13" M1 (j293) driving DisplayPort alt mode over USB-C.
Cold plug works; the first hot unplug kills the external output for the rest of
the boot. The compositor logs failed to commit: Invalid argument for all 23
modes the monitor offers, from 3440x1440 down to 640x480, and nothing in the
kernel log explains it — of the three -EINVAL exits in
dcp_crtc_atomic_check() only two log a dev_err, and the silent one is this.

Confirmed with kprobes on each of the three exits: 110 hits on the ->crashed
branch, all returning -22, with zero "DCP has crashed" messages
. The timeout is
intermittent — it fired on 2 of 6 unplug cycles — which is why the failure looked
erratic.

With this applied, 6 unplug/replug cycles completed 8 modesets with no failures,
including the two cycles where the timeout did fire.

Full traces and the validation run are at
https://github.com/haripako/dp-altmode (validacion/).

Notes

  • Tested on linux-asahi 7.1.6 (asahi-7.1.6-1); the patch applies unchanged to
    asahi as of today, where the code is still present.
  • iomfb_template.c is included once per IOMFB version, so this covers both the
    v12_3 and v13_3 paths.
  • Reaching DisplayPort alt mode on M1 at all needed an out-of-tree device tree
    and a backport of the fairydust cd321x HPD forwarding. This fix is
    independent of both
    — it is in the poweroff path and applies to any CRTC
    being disabled, including the internal panel, though that path was not
    reproduced here.

iomfb_poweroff() submits a clear swap and waits 50 ms for the DCP to
acknowledge it. On timeout it sets dcp->crashed and returns, without
logging anything.

That flag is permanent and fatal. dcp_crtc_atomic_check() starts with:

	if (dcp->crashed)
		return -EINVAL;

so from that moment on every atomic commit for the device is rejected.
There is no path that clears the flag, so the display never comes back
until the machine is rebooted.

This is not a crash. After the timeout the DCP keeps working: it
renegotiates the link, publishes its mode list and asserts HPD
(dcp_hotplug() connected:1 nr_modes:23). Only ->crashed, which is
otherwise set exclusively by dcp_rtk_crashed() - the RTKit crash
callback - makes the device unusable. RTKit never reported a crash in
any of these runs.

Observed on a MacBook Pro 13" M1 (j293) with DisplayPort alt mode over
USB-C. Cold plug works, but the first hot unplug kills the external
output for the rest of the boot. The compositor logs "failed to commit:
Invalid argument" for all 23 modes the monitor offers, from 3440x1440
down to 640x480, and nothing in the kernel log explains why: of the
three -EINVAL exits in dcp_crtc_atomic_check() only two log a dev_err,
and the silent one is this.

Confirmed with kprobes placed on each of the three exits: 110 hits on
the ->crashed branch, all returning -22, with zero "DCP has crashed"
messages in the log.

The timeout is intermittent - it fired on 2 of 6 unplug cycles - which
is why the failure looked erratic.

Note that dcp_poweroff() is reached from apple_crtc_atomic_disable()
for any CRTC being disabled, not just an external one, so the same
timeout can in principle latch the flag while turning off the internal
panel. That path was not reproduced here.

Keep the control flow identical but leave ->crashed alone, and warn so
the timeout is at least visible. With this applied, 6 unplug/replug
cycles completed 8 modesets with no failures, including the two cycles
where the timeout did fire.

Signed-off-by: Francisco Vargas <haripako@gmail.com>
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