xf86-video-ati: Branch 'master'

Michel Dänzer daenzer at kemper.freedesktop.org
Tue Aug 9 09:08:24 UTC 2016


 src/drmmode_display.c |   54 +++++++++++++++++++++++++++++++++++++++++++-------
 src/drmmode_display.h |    2 +
 src/radeon_kms.c      |    4 +--
 src/radeon_present.c  |    4 +--
 src/radeon_video.c    |    2 -
 5 files changed, 54 insertions(+), 12 deletions(-)

New commits:
commit 9090309e057dc703d1a5bffd88e6cae14108cfc3
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Tue May 10 18:45:30 2016 +0900

    Wait for pending flips to complete before turning off an output or CRTC
    
    At least with older kernels, the flip may never complete otherwise,
    which can result in us hanging in drmmode_set_mode_major.
    
    Fixes: https://bugs.launchpad.net/ubuntu/+source/xserver-xorg-video-ati/+bug/1577170
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index b39651c..0401724 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -307,9 +307,15 @@ drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode)
 	CARD64 ust;
 	int ret;
 
+	drmmode_crtc->pending_dpms_mode = mode;
+
 	if (drmmode_crtc->dpms_mode == DPMSModeOn && mode != DPMSModeOn) {
 		drmVBlank vbl;
 
+		/* Wait for any pending flip to finish */
+		if (drmmode_crtc->flip_pending)
+			return;
+
 		/*
 		 * On->Off transition: record the last vblank time,
 		 * sequence number and frame period.
@@ -367,10 +373,14 @@ drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
 	drmmode_ptr drmmode = drmmode_crtc->drmmode;
 
 	/* Disable unused CRTCs */
-	if (!crtc->enabled || mode != DPMSModeOn)
+	if (!crtc->enabled || mode != DPMSModeOn) {
+		/* Wait for any pending flip to finish */
+		if (drmmode_crtc->flip_pending)
+			return;
+
 		drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
 			       0, 0, 0, NULL, 0, NULL);
-	else if (drmmode_crtc->dpms_mode != DPMSModeOn)
+	} else if (drmmode_crtc->dpms_mode != DPMSModeOn)
 		crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation,
 					    crtc->x, crtc->y);
 }
@@ -1232,6 +1242,7 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
 	drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, mode_res->crtcs[num]);
 	drmmode_crtc->drmmode = drmmode;
 	drmmode_crtc->dpms_mode = DPMSModeOff;
+	drmmode_crtc->pending_dpms_mode = DPMSModeOff;
 	crtc->driver_private = drmmode_crtc;
 	drmmode_crtc_hw_id(crtc);
 
@@ -1357,9 +1368,16 @@ drmmode_output_dpms(xf86OutputPtr output, int mode)
 	if (!koutput)
 		return;
 
-	if (mode != DPMSModeOn && crtc)
+	if (mode != DPMSModeOn && crtc) {
+		drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
 		drmmode_do_crtc_dpms(crtc, mode);
 
+		/* Wait for any pending flip to finish */
+		if (drmmode_crtc->flip_pending)
+			return;
+	}
+
 	drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id,
 				    drmmode_output->dpms_enum_id, mode);
 
@@ -2190,9 +2208,32 @@ static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
 };
 
 static void
-drmmode_flip_abort(xf86CrtcPtr crtc, void *event_data)
+drmmode_clear_pending_flip(xf86CrtcPtr crtc)
 {
 	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+	drmmode_crtc->flip_pending = FALSE;
+
+	if (drmmode_crtc->pending_dpms_mode != DPMSModeOn &&
+	    drmmode_crtc->dpms_mode != drmmode_crtc->pending_dpms_mode) {
+		xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+		int o;
+
+		for (o = 0; o < xf86_config->num_output; o++) {
+			xf86OutputPtr output = xf86_config->output[o];
+
+			if (output->crtc != crtc)
+				continue;
+
+			drmmode_output_dpms(output, drmmode_crtc->pending_dpms_mode);
+			drmmode_crtc_dpms(crtc, drmmode_crtc->pending_dpms_mode);
+		}
+	}
+}
+
+static void
+drmmode_flip_abort(xf86CrtcPtr crtc, void *event_data)
+{
 	drmmode_flipdata_ptr flipdata = event_data;
 
 	if (--flipdata->flip_count == 0) {
@@ -2202,13 +2243,12 @@ drmmode_flip_abort(xf86CrtcPtr crtc, void *event_data)
 		free(flipdata);
 	}
 
-	drmmode_crtc->flip_pending = FALSE;
+	drmmode_clear_pending_flip(crtc);
 }
 
 static void
 drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *event_data)
 {
-	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 	RADEONInfoPtr info = RADEONPTR(crtc->scrn);
 	drmmode_flipdata_ptr flipdata = event_data;
 
@@ -2232,7 +2272,7 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even
 		free(flipdata);
 	}
 
-	drmmode_crtc->flip_pending = FALSE;
+	drmmode_clear_pending_flip(crtc);
 }
 
 
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 83c6482..c1109f7 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -88,6 +88,8 @@ typedef struct {
     unsigned scanout_id;
     Bool scanout_update_pending;
     int dpms_mode;
+    /* For when a flip is pending when DPMS off requested */
+    int pending_dpms_mode;
     CARD64 dpms_last_ust;
     uint32_t dpms_last_seq;
     int dpms_last_fps;
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index da11358..264b6a1 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -430,7 +430,7 @@ radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id)
     Bool force;
 
     if (!xf86_crtc->enabled ||
-	drmmode_crtc->dpms_mode != DPMSModeOn ||
+	drmmode_crtc->pending_dpms_mode != DPMSModeOn ||
 	!drmmode_crtc->scanout[scanout_id].pixmap)
 	return FALSE;
 
@@ -564,7 +564,7 @@ radeon_scanout_update(xf86CrtcPtr xf86_crtc)
     if (!xf86_crtc->enabled ||
 	drmmode_crtc->scanout_update_pending ||
 	!drmmode_crtc->scanout[0].pixmap ||
-	drmmode_crtc->dpms_mode != DPMSModeOn)
+	drmmode_crtc->pending_dpms_mode != DPMSModeOn)
 	return;
 
     pDamage = drmmode_crtc->scanout[0].damage;
diff --git a/src/radeon_present.c b/src/radeon_present.c
index 52943fb..93c18a8 100644
--- a/src/radeon_present.c
+++ b/src/radeon_present.c
@@ -268,7 +268,7 @@ radeon_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap,
 	if (!drmmode_crtc || drmmode_crtc->rotate.bo != NULL)
 	    return FALSE;
 
-	if (drmmode_crtc->dpms_mode == DPMSModeOn)
+	if (drmmode_crtc->pending_dpms_mode == DPMSModeOn)
 	    num_crtcs_on++;
     }
 
@@ -396,7 +396,7 @@ modeset:
 	if (!crtc->enabled)
 	    continue;
 
-	if (drmmode_crtc->dpms_mode == DPMSModeOn)
+	if (drmmode_crtc->pending_dpms_mode == DPMSModeOn)
 	    crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation,
 					crtc->x, crtc->y);
 	else
diff --git a/src/radeon_video.c b/src/radeon_video.c
index e08d8e0..d058986 100644
--- a/src/radeon_video.c
+++ b/src/radeon_video.c
@@ -71,7 +71,7 @@ radeon_box_area(BoxPtr box)
 Bool radeon_crtc_is_enabled(xf86CrtcPtr crtc)
 {
     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
-    return drmmode_crtc->dpms_mode == DPMSModeOn;
+    return drmmode_crtc->pending_dpms_mode == DPMSModeOn;
 }
 
 xf86CrtcPtr


More information about the xorg-commit mailing list