[PATCH xserver] modesetting: Also disable CRTC in drmmode_output_disable()

Lyude Paul lyude at redhat.com
Fri Jun 8 00:30:34 UTC 2018


So, this did actually work on older kernels at one point in time,
however it seems that this working was a result of some of the Linux
kernel's atomic modesetting helpers not preserving the CRTC's enabled
state in the right spots. This was fixed in:

846c7dfc1193 ("drm/atomic: Try to preserve the crtc enabled state in drm_atomic_remove_fb, v2")

As a result, atomic commits which simply disassociate a DRM connector
with it's CRTC while leaving the CRTC in an enabled state aren't enough
to disable the CRTC, and result in the atomic commit failing. This
currently can cause issues with MST hotplugging where X will end up
failing to disable the MST outputs after they've left the system. A
simple reproducer:

- Start up Xorg
- Connect an MST hub with displays connected to it
- Remove the hub
- Now there should be CRTCs stuck on the orphaned MST connectors, and X
  won't be able to reclaim them.

Signed-off-by: Lyude Paul <lyude at redhat.com>
Cc: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
---
 hw/xfree86/drivers/modesetting/drmmode_display.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index 859a21a9d..375be4234 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -695,18 +695,21 @@ drmmode_output_disable(xf86OutputPtr output)
 {
     modesettingPtr ms = modesettingPTR(output->scrn);
     drmmode_output_private_ptr drmmode_output = output->driver_private;
+    xf86CrtcPtr crtc = drmmode_output->current_crtc;
     drmModeAtomicReq *req = drmModeAtomicAlloc();
     uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
-    int ret;
+    int ret = 0;
 
     assert(ms->atomic_modeset);
 
     if (!req)
         return 1;
 
-    /* XXX Can we disable all outputs without disabling CRTC right away? */
-    ret = connector_add_prop(req, drmmode_output,
-                             DRMMODE_CONNECTOR_CRTC_ID, 0);
+    ret |= connector_add_prop(req, drmmode_output,
+                              DRMMODE_CONNECTOR_CRTC_ID, 0);
+    if (crtc)
+        ret |= crtc_add_dpms_props(req, crtc, DPMSModeOff, NULL);
+
     if (ret == 0)
         ret = drmModeAtomicCommit(ms->fd, req, flags, NULL);
 
-- 
2.17.1



More information about the xorg-devel mailing list