Skip to content

backend-drm: make sure unused CRTC is disabled before atomic commit

Problem Description

On our platform, we connected two monitors for video playback. After hot-plugging the HDMI connector of one of the monitors several times, there is a certain probability that weston will hang.

Trouble Shooting

The log printed by the drm backend on our platform is as follows. There are two outputs on our platform, HDMI-A-1 and HDMI-A-2, and the corresponding CRTC ids are 33 and 39 respectively. When the connector of HDMI-A-2 is unplugged, the output is not destroyed immediately.

[03:25:20.363] [repaint] flushed pending_state 0xaaaad3cf7320
[03:25:20.369] **DRM: head 'HDMI-A-2' updated, connector 43 is disconnected.**
[03:25:20.369] [atomic][CRTC:33] flip processing started
[03:25:20.369] [atomic][CRTC:33] flip processing completed
[03:25:20.369] Output 'HDMI-A-2' no heads left, disabling.
[03:25:20.369] destroy output while page flip pending
[03:25:20.370] [repaint] Beginning repaint; pending_state 0xaaaad3cde2a0
[03:25:20.370] Weston scene graph at 70206.090884320:

In flip processing, the output HDMI-A-2 will be destroyed. However, this processing is after atomic commit for output HDMI-A-1.

[03:25:20.373]    [atomic] applying output 0 (HDMI-A-1) state
[03:25:20.373]        [CRTC:33] 23 (MODE_ID) -> 57 (0x39)
[03:25:20.373]        [CRTC:33] 22 (ACTIVE) -> 1 (0x1)
[03:25:20.373]        [CONN:41] 20 (CRTC_ID) -> 33 (0x21)
...
[03:25:20.373]        [PLANE:31] 18 (IN_FENCE_FD) -> 85 (0x55)
[03:25:20.373] [atomic] drmModeAtomicCommit
[03:25:20.373] atomic: couldn't commit new state: Invalid argument
[03:25:20.373] repaint-flush failed: Invalid argument
[03:25:20.373] [repaint] flushed pending_state 0xaaaad3cde2a0
[03:25:20.373] background surface gone
[03:25:20.395] panel surface gone
[03:25:20.396] [atomic][CRTC:39] flip processing started
[03:25:20.396]    [atomic] previous state invalid; starting with fresh state
[03:25:20.396]    [atomic] disabling inactive head HDMI-A-2
[03:25:20.396]        [CONN:43] 20 (CRTC_ID) -> 0
[03:25:20.396]    [atomic] starting with plane 31 disabled
[03:25:20.396]        [PLANE:31] 20 (CRTC_ID) -> 0 (0x0)
[03:25:20.396]        [PLANE:31] 17 (FB_ID) -> 0 (0x0)
[03:25:20.396]    [atomic] starting with plane 34 disabled
[03:25:20.396]        [PLANE:34] 20 (CRTC_ID) -> 0 (0x0)
[03:25:20.396]        [PLANE:34] 17 (FB_ID) -> 0 (0x0)
[03:25:20.396]    [atomic] starting with plane 37 disabled
[03:25:20.396]        [PLANE:37] 20 (CRTC_ID) -> 0 (0x0)
[03:25:20.396]        [PLANE:37] 17 (FB_ID) -> 0 (0x0)
[03:25:20.396]    [atomic] applying output 1 (HDMI-A-2) state
[03:25:20.396]        [atomic] DPMS state differs, modeset OK
[03:25:20.396]        [CRTC:39] 23 (MODE_ID) -> 0 (0x0)
[03:25:20.396]        [CRTC:39] 22 (ACTIVE) -> 0 (0x0)
[03:25:20.396]        [PLANE:37] 17 (FB_ID) -> 0 (0x0)
...
[03:25:20.397]        [PLANE:37] FORMAT: UNKNOWN
[03:25:20.397] [atomic] drmModeAtomicCommit
[03:25:20.397] atomic: couldn't commit new state: Invalid argument
[03:25:20.432] [atomic][CRTC:39] flip processing completed

In this case, weston may not be able to disable the CRTC (id 39) of output HDMI-A-2 before atomic commit, as HDMI-A-2 has not been destroyed, making Weston believe that the CRTC 39 is still in use. This will cause atomic commit failure and weston cannot schedule the next repaint time, the draw loop will hang.

Fix

To fix this issue, when output is pending to be destroyed, i.e. drm_output::destroy_pending is true, its CRTC should be disabled before atomic commit. After adding this patch, weston works well when the above situation occurs.

Merge request reports