xf86-video-amdgpu: Branch 'master' - 3 commits

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Dec 13 11:21:12 UTC 2018


 src/amdgpu_kms.c      |   96 +++++++++++++++++++++++++++++++++++++++++---------
 src/drmmode_display.c |   16 +++++---
 src/drmmode_display.h |    7 +++
 3 files changed, 97 insertions(+), 22 deletions(-)

New commits:
commit bcfa6c258fdf41a9928f8a3c78fc528d0fafee25
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Wed Nov 21 18:32:04 2018 +0100

    Automatically try re-enabling TearFree after a flip failed
    
    Specifically, after both the page flip and vblank ioctls failed, but
    then the vblank ioctl started working again. This can happen
    intermittently e.g. when hotplugging a DP display. Previously, TearFree
    would stay disabled in that case until a modeset was triggered somehow.
    
    Bugzilla: https://bugs.freedesktop.org/103791
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 44a3c8a..506e5f7 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -748,15 +748,32 @@ amdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
 
 	if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
 				 1, drm_queue_seq, NULL, NULL)) {
-		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
-			   "drmmode_wait_vblank failed for PRIME update: %s\n",
-			   strerror(errno));
+		if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_VBLANK_FAILED)) {
+			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+				   "drmmode_wait_vblank failed for PRIME update: %s\n",
+				   strerror(errno));
+			drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_VBLANK_FAILED;
+		}
+
 		drmmode_crtc->drmmode->event_context.vblank_handler(pAMDGPUEnt->fd,
 								    0, 0, 0,
 								    (void*)drm_queue_seq);
 		drmmode_crtc->wait_flip_nesting_level++;
 		amdgpu_drm_queue_handle_deferred(xf86_crtc);
+		return;
+	}
+
+	if (drmmode_crtc->scanout_status ==
+	    (DRMMODE_SCANOUT_FLIP_FAILED | DRMMODE_SCANOUT_VBLANK_FAILED)) {
+		/* The page flip and vblank ioctls failed before, but the vblank
+		 * ioctl is working again, so we can try re-enabling TearFree
+		 */
+		xf86_crtc->funcs->set_mode_major(xf86_crtc, &xf86_crtc->mode,
+						 xf86_crtc->rotation,
+						 xf86_crtc->x, xf86_crtc->y);
 	}
+
+	drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_VBLANK_FAILED;
 }
 
 static void
@@ -807,12 +824,22 @@ amdgpu_prime_scanout_flip(PixmapDirtyUpdatePtr ent)
 	if (drmmode_page_flip_target_relative(pAMDGPUEnt, drmmode_crtc,
 					      drmmode_crtc->flip_pending->handle,
 					      0, drm_queue_seq, 0) != 0) {
-		xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s\n",
-			   __func__, strerror(errno));
+		if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED)) {
+			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+				   "flip queue failed in %s: %s, TearFree inactive\n",
+				   __func__, strerror(errno));
+			drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_FLIP_FAILED;
+		}
+
 		amdgpu_drm_abort_entry(drm_queue_seq);
 		return;
 	}
 
+	if (drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED) {
+		xf86DrvMsg(scrn->scrnIndex, X_INFO, "TearFree active again\n");
+		drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_FLIP_FAILED;
+	}
+
 	drmmode_crtc->scanout_id = scanout_id;
 	drmmode_crtc->scanout_update_pending = drm_queue_seq;
 }
@@ -1029,15 +1056,32 @@ amdgpu_scanout_update(xf86CrtcPtr xf86_crtc)
 
 	if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
 				 1, drm_queue_seq, NULL, NULL)) {
-		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
-			   "drmmode_wait_vblank failed for scanout update: %s\n",
-			   strerror(errno));
+		if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_VBLANK_FAILED)) {
+			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+				   "drmmode_wait_vblank failed for scanout update: %s\n",
+				   strerror(errno));
+			drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_VBLANK_FAILED;
+		}
+
 		drmmode_crtc->drmmode->event_context.vblank_handler(pAMDGPUEnt->fd,
 								    0, 0, 0,
 								    (void*)drm_queue_seq);
 		drmmode_crtc->wait_flip_nesting_level++;
 		amdgpu_drm_queue_handle_deferred(xf86_crtc);
+		return;
+	}
+
+	if (drmmode_crtc->scanout_status ==
+	    (DRMMODE_SCANOUT_FLIP_FAILED | DRMMODE_SCANOUT_VBLANK_FAILED)) {
+		/* The page flip and vblank ioctls failed before, but the vblank
+		 * ioctl is working again, so we can try re-enabling TearFree
+		 */
+		xf86_crtc->funcs->set_mode_major(xf86_crtc, &xf86_crtc->mode,
+						 xf86_crtc->rotation,
+						 xf86_crtc->x, xf86_crtc->y);
 	}
+
+	drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_VBLANK_FAILED;
 }
 
 static void
@@ -1089,9 +1133,13 @@ amdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info,
 	if (drmmode_page_flip_target_relative(pAMDGPUEnt, drmmode_crtc,
 					      drmmode_crtc->flip_pending->handle,
 					      0, drm_queue_seq, 0) != 0) {
-		xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s, "
-			   "TearFree inactive until next modeset\n",
-			   __func__, strerror(errno));
+		if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED)) {
+			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+				   "flip queue failed in %s: %s, TearFree inactive\n",
+				   __func__, strerror(errno));
+			drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_FLIP_FAILED;
+		}
+
 		amdgpu_drm_abort_entry(drm_queue_seq);
 		RegionCopy(DamageRegion(drmmode_crtc->scanout_damage),
 			   &drmmode_crtc->scanout_last_region);
@@ -1103,6 +1151,11 @@ amdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info,
 		return;
 	}
 
+	if (drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED) {
+		xf86DrvMsg(scrn->scrnIndex, X_INFO, "TearFree active again\n");
+		drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_FLIP_FAILED;
+	}
+
 	drmmode_crtc->scanout_id = scanout_id;
 	drmmode_crtc->scanout_update_pending = drm_queue_seq;
 }
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index b2b16df..aab330c 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -91,6 +91,12 @@ struct drmmode_fb {
 	uint32_t handle;
 };
 
+enum drmmode_scanout_status {
+	DRMMODE_SCANOUT_OK,
+	DRMMODE_SCANOUT_FLIP_FAILED = 1u << 0,
+	DRMMODE_SCANOUT_VBLANK_FAILED = 1u << 1,
+};
+
 struct drmmode_scanout {
 	struct amdgpu_buffer *bo;
 	PixmapPtr pixmap;
@@ -110,6 +116,7 @@ typedef struct {
 	unsigned scanout_id;
 	uintptr_t scanout_update_pending;
 	Bool tear_free;
+	enum drmmode_scanout_status scanout_status;
 	Bool vrr_enabled;
 
 	PixmapPtr prime_scanout_pixmap;
commit 4e7a24ac5a64e402146953ec5850d13c05742116
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Wed Nov 21 17:54:18 2018 +0100

    Cancel pending scanout update in drmmode_crtc_scanout_update
    
    drmmode_crtc_scanout_update does the equivalent of a scanout update,
    so no need to do it again. This might also avoid issues if there's a
    pending scanout update at this point.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index bd5eb5e..2a22777 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -790,11 +790,17 @@ drmmode_crtc_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
 		*fb = amdgpu_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap);
 		*x = *y = 0;
 
-		amdgpu_scanout_do_update(crtc, scanout_id,
-					 screen->GetWindowPixmap(screen->root),
-					 extents);
-		RegionEmpty(DamageRegion(drmmode_crtc->scanout_damage));
-		amdgpu_glamor_finish(scrn);
+		if (amdgpu_scanout_do_update(crtc, scanout_id,
+					     screen->GetWindowPixmap(screen->root),
+					     extents)) {
+			RegionEmpty(DamageRegion(drmmode_crtc->scanout_damage));
+			amdgpu_glamor_finish(scrn);
+
+			if (!drmmode_crtc->flip_pending) {
+				amdgpu_drm_abort_entry(drmmode_crtc->
+						       scanout_update_pending);
+			}
+		}
 	}
 }
 
commit 500fadb16285146e91f62fce3a0ce1360ca684ba
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Wed Nov 21 12:42:22 2018 +0100

    Perform scanout buffer update immediately if drmmode_wait_vblank fails
    
    Otherwise the damaged screen contents may never be displayed in that
    case.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 92782de..44a3c8a 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -717,6 +717,7 @@ amdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
 {
 	ScreenPtr screen = dirty->slave_dst->drawable.pScreen;
 	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
 	xf86CrtcPtr xf86_crtc = amdgpu_prime_dirty_to_crtc(dirty);
 	drmmode_crtc_private_ptr drmmode_crtc;
 	uintptr_t drm_queue_seq;
@@ -739,19 +740,23 @@ amdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
 	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "amdgpu_drm_queue_alloc failed for PRIME update\n");
+		amdgpu_prime_scanout_update_handler(xf86_crtc, 0, 0, NULL);
 		return;
 	}
 
+	drmmode_crtc->scanout_update_pending = drm_queue_seq;
+
 	if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
 				 1, drm_queue_seq, NULL, NULL)) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "drmmode_wait_vblank failed for PRIME update: %s\n",
 			   strerror(errno));
-		amdgpu_drm_abort_entry(drm_queue_seq);
-		return;
+		drmmode_crtc->drmmode->event_context.vblank_handler(pAMDGPUEnt->fd,
+								    0, 0, 0,
+								    (void*)drm_queue_seq);
+		drmmode_crtc->wait_flip_nesting_level++;
+		amdgpu_drm_queue_handle_deferred(xf86_crtc);
 	}
-
-	drmmode_crtc->scanout_update_pending = drm_queue_seq;
 }
 
 static void
@@ -979,8 +984,9 @@ static void
 amdgpu_scanout_update(xf86CrtcPtr xf86_crtc)
 {
 	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
+	ScrnInfoPtr scrn = xf86_crtc->scrn;
+	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
 	uintptr_t drm_queue_seq;
-	ScrnInfoPtr scrn;
 	DamagePtr pDamage;
 	RegionPtr pRegion;
 	BoxRec extents;
@@ -1005,7 +1011,6 @@ amdgpu_scanout_update(xf86CrtcPtr xf86_crtc)
 		return;
 	}
 
-	scrn = xf86_crtc->scrn;
 	drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc,
 					       AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
 					       AMDGPU_DRM_QUEUE_ID_DEFAULT,
@@ -1016,19 +1021,23 @@ amdgpu_scanout_update(xf86CrtcPtr xf86_crtc)
 	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "amdgpu_drm_queue_alloc failed for scanout update\n");
+		amdgpu_scanout_update_handler(xf86_crtc, 0, 0, drmmode_crtc);
 		return;
 	}
 
+	drmmode_crtc->scanout_update_pending = drm_queue_seq;
+
 	if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
 				 1, drm_queue_seq, NULL, NULL)) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "drmmode_wait_vblank failed for scanout update: %s\n",
 			   strerror(errno));
-		amdgpu_drm_abort_entry(drm_queue_seq);
-		return;
+		drmmode_crtc->drmmode->event_context.vblank_handler(pAMDGPUEnt->fd,
+								    0, 0, 0,
+								    (void*)drm_queue_seq);
+		drmmode_crtc->wait_flip_nesting_level++;
+		amdgpu_drm_queue_handle_deferred(xf86_crtc);
 	}
-
-	drmmode_crtc->scanout_update_pending = drm_queue_seq;
 }
 
 static void


More information about the xorg-commit mailing list