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

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Nov 16 15:52:35 UTC 2018


 src/amdgpu_dri2.c      |    4 -
 src/amdgpu_drm_queue.c |  110 ++++++++++++++++++++++++++++---------------------
 src/amdgpu_drm_queue.h |    3 -
 src/amdgpu_kms.c       |   10 ++--
 src/amdgpu_present.c   |    3 -
 src/drmmode_display.c  |    3 -
 6 files changed, 78 insertions(+), 55 deletions(-)

New commits:
commit 51ba6dddee40c3688d4c7b12eabeab516ed153b7
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Fri Nov 9 11:00:04 2018 +0100

    Move deferred vblank events to separate drm_vblank_deferred list
    
    It was still possible for nested xorg_list_for_each_entry_safe loops
    to occur over the drm_vblank_signalled list, which could mess up that
    list. Moving deferred events to a separate list allows processing the
    drm_vblank_signalled list without xorg_list_for_each_entry_safe.
    
    v2:
    * Refactor drm_handle_vblank_signalled helper function, less code
      duplication => better readability (Alex Deucher)
    
    Bugzilla: https://bugs.freedesktop.org/108600
    Acked-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/amdgpu_drm_queue.c b/src/amdgpu_drm_queue.c
index 808941b..56d593d 100644
--- a/src/amdgpu_drm_queue.c
+++ b/src/amdgpu_drm_queue.c
@@ -56,6 +56,7 @@ static int amdgpu_drm_queue_refcnt;
 static struct xorg_list amdgpu_drm_queue;
 static struct xorg_list amdgpu_drm_flip_signalled;
 static struct xorg_list amdgpu_drm_vblank_signalled;
+static struct xorg_list amdgpu_drm_vblank_deferred;
 static uintptr_t amdgpu_drm_queue_seq;
 
 
@@ -112,6 +113,31 @@ amdgpu_drm_queue_handler(int fd, unsigned int frame, unsigned int sec,
 }
 
 /*
+ * Handle signalled vblank events. If we're waiting for a flip event,
+ * put events for that CRTC in the vblank_deferred list.
+ */
+static void
+amdgpu_drm_handle_vblank_signalled(void)
+{
+	drmmode_crtc_private_ptr drmmode_crtc;
+	struct amdgpu_drm_queue_entry *e;
+
+	while (!xorg_list_is_empty(&amdgpu_drm_vblank_signalled)) {
+		e = xorg_list_first_entry(&amdgpu_drm_vblank_signalled,
+					  struct amdgpu_drm_queue_entry, list);
+		drmmode_crtc = e->crtc->driver_private;
+
+		if (drmmode_crtc->wait_flip_nesting_level == 0) {
+			amdgpu_drm_queue_handle_one(e);
+			continue;
+		}
+
+		xorg_list_del(&e->list);
+		xorg_list_append(&e->list, &amdgpu_drm_vblank_deferred);
+	}
+}
+
+/*
  * Handle deferred DRM vblank events
  *
  * This function must be called after amdgpu_drm_wait_pending_flip, once
@@ -127,12 +153,18 @@ amdgpu_drm_queue_handle_deferred(xf86CrtcPtr crtc)
 	    --drmmode_crtc->wait_flip_nesting_level > 0)
 		return;
 
-	xorg_list_for_each_entry_safe(e, tmp, &amdgpu_drm_vblank_signalled, list) {
-		drmmode_crtc_private_ptr drmmode_crtc = e->crtc->driver_private;
+	/* Put previously deferred vblank events for this CRTC back in the
+	 * signalled queue
+	 */
+	xorg_list_for_each_entry_safe(e, tmp, &amdgpu_drm_vblank_deferred, list) {
+		if (e->crtc != crtc)
+			continue;
 
-		if (drmmode_crtc->wait_flip_nesting_level == 0)
-			amdgpu_drm_queue_handle_one(e);
+		xorg_list_del(&e->list);
+		xorg_list_append(&e->list, &amdgpu_drm_vblank_signalled);
 	}
+
+	amdgpu_drm_handle_vblank_signalled();
 }
 
 /*
@@ -205,6 +237,13 @@ amdgpu_drm_abort_entry(uintptr_t seq)
 		}
 	}
 
+	xorg_list_for_each_entry_safe(e, tmp, &amdgpu_drm_vblank_deferred, list) {
+		if (e->seq == seq) {
+			amdgpu_drm_abort_one(e);
+			return;
+		}
+	}
+
 	xorg_list_for_each_entry_safe(e, tmp, &amdgpu_drm_queue, list) {
 		if (e->seq == seq) {
 			amdgpu_drm_abort_one(e);
@@ -235,7 +274,7 @@ amdgpu_drm_abort_id(uint64_t id)
 int
 amdgpu_drm_handle_event(int fd, drmEventContext *event_context)
 {
-	struct amdgpu_drm_queue_entry *e, *tmp;
+	struct amdgpu_drm_queue_entry *e;
 	int r;
 
 	r = drmHandleEvent(fd, event_context);
@@ -246,12 +285,7 @@ amdgpu_drm_handle_event(int fd, drmEventContext *event_context)
 		amdgpu_drm_queue_handle_one(e);
 	}
 
-	xorg_list_for_each_entry_safe(e, tmp, &amdgpu_drm_vblank_signalled, list) {
-		drmmode_crtc_private_ptr drmmode_crtc = e->crtc->driver_private;
-
-		if (drmmode_crtc->wait_flip_nesting_level == 0)
-			amdgpu_drm_queue_handle_one(e);
-	}
+	amdgpu_drm_handle_vblank_signalled();
 
 	return r;
 }
@@ -298,6 +332,7 @@ amdgpu_drm_queue_init(ScrnInfoPtr scrn)
 	xorg_list_init(&amdgpu_drm_queue);
 	xorg_list_init(&amdgpu_drm_flip_signalled);
 	xorg_list_init(&amdgpu_drm_vblank_signalled);
+	xorg_list_init(&amdgpu_drm_vblank_deferred);
 }
 
 /*
commit e2c7369cae65069aa93eed1c0b678f975ce5c274
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Mon Nov 5 19:02:31 2018 +0100

    Explicitly keep track of whether a DRM event is for a flip or not
    
    When an async flip is performed, and TearFree is enabled on the CRTC
    used for timing, we schedule a vblank event for completing the page
    flip. The DRM event queuing code treated this event like a vblank event,
    but it needs to be treated like a page flip event.
    
    Acked-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/amdgpu_dri2.c b/src/amdgpu_dri2.c
index 96b2d17..ff1b94a 100644
--- a/src/amdgpu_dri2.c
+++ b/src/amdgpu_dri2.c
@@ -981,7 +981,7 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
 
 	drm_queue_seq = amdgpu_drm_queue_alloc(crtc, client, AMDGPU_DRM_QUEUE_ID_DEFAULT,
 					       wait_info, amdgpu_dri2_frame_event_handler,
-					       amdgpu_dri2_frame_event_abort);
+					       amdgpu_dri2_frame_event_abort, FALSE);
 	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "Allocating DRM queue event entry failed.\n");
@@ -1121,7 +1121,7 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
 
 	drm_queue_seq = amdgpu_drm_queue_alloc(crtc, client, AMDGPU_DRM_QUEUE_ID_DEFAULT,
 					       swap_info, amdgpu_dri2_frame_event_handler,
-					       amdgpu_dri2_frame_event_abort);
+					       amdgpu_dri2_frame_event_abort, FALSE);
 	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "Allocating DRM queue entry failed.\n");
diff --git a/src/amdgpu_drm_queue.c b/src/amdgpu_drm_queue.c
index 4b51d46..808941b 100644
--- a/src/amdgpu_drm_queue.c
+++ b/src/amdgpu_drm_queue.c
@@ -48,6 +48,7 @@ struct amdgpu_drm_queue_entry {
 	xf86CrtcPtr crtc;
 	amdgpu_drm_handler_proc handler;
 	amdgpu_drm_abort_proc abort;
+	Bool is_flip;
 	unsigned int frame;
 };
 
@@ -86,8 +87,8 @@ amdgpu_drm_abort_one(struct amdgpu_drm_queue_entry *e)
 }
 
 static void
-amdgpu_drm_queue_handler(struct xorg_list *signalled, unsigned int frame,
-			 unsigned int sec, unsigned int usec, void *user_ptr)
+amdgpu_drm_queue_handler(int fd, unsigned int frame, unsigned int sec,
+			 unsigned int usec, void *user_ptr)
 {
 	uintptr_t seq = (uintptr_t)user_ptr;
 	struct amdgpu_drm_queue_entry *e, *tmp;
@@ -102,35 +103,15 @@ amdgpu_drm_queue_handler(struct xorg_list *signalled, unsigned int frame,
 			xorg_list_del(&e->list);
 			e->usec = (uint64_t)sec * 1000000 + usec;
 			e->frame = frame;
-			xorg_list_append(&e->list, signalled);
+			xorg_list_append(&e->list, e->is_flip ?
+					 &amdgpu_drm_flip_signalled :
+					 &amdgpu_drm_vblank_signalled);
 			break;
 		}
 	}
 }
 
 /*
- * Signal a DRM page flip event
- */
-static void
-amdgpu_drm_page_flip_handler(int fd, unsigned int frame, unsigned int sec,
-			     unsigned int usec, void *user_ptr)
-{
-	amdgpu_drm_queue_handler(&amdgpu_drm_flip_signalled, frame, sec, usec,
-				 user_ptr);
-}
-
-/*
- * Signal a DRM vblank event
- */
-static void
-amdgpu_drm_vblank_handler(int fd, unsigned int frame, unsigned int sec,
-			  unsigned int usec, void *user_ptr)
-{
-	amdgpu_drm_queue_handler(&amdgpu_drm_vblank_signalled, frame, sec, usec,
-				 user_ptr);
-}
-
-/*
  * Handle deferred DRM vblank events
  *
  * This function must be called after amdgpu_drm_wait_pending_flip, once
@@ -162,7 +143,8 @@ uintptr_t
 amdgpu_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client,
 		       uint64_t id, void *data,
 		       amdgpu_drm_handler_proc handler,
-		       amdgpu_drm_abort_proc abort)
+		       amdgpu_drm_abort_proc abort,
+		       Bool is_flip)
 {
 	struct amdgpu_drm_queue_entry *e;
 
@@ -180,6 +162,7 @@ amdgpu_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client,
 	e->data = data;
 	e->handler = handler;
 	e->abort = abort;
+	e->is_flip = is_flip;
 
 	xorg_list_append(&e->list, &amdgpu_drm_queue);
 
@@ -306,8 +289,8 @@ amdgpu_drm_queue_init(ScrnInfoPtr scrn)
 	drmmode_ptr drmmode = &info->drmmode;
 
 	drmmode->event_context.version = 2;
-	drmmode->event_context.vblank_handler = amdgpu_drm_vblank_handler;
-	drmmode->event_context.page_flip_handler = amdgpu_drm_page_flip_handler;
+	drmmode->event_context.vblank_handler = amdgpu_drm_queue_handler;
+	drmmode->event_context.page_flip_handler = amdgpu_drm_queue_handler;
 
 	if (amdgpu_drm_queue_refcnt++)
 		return;
diff --git a/src/amdgpu_drm_queue.h b/src/amdgpu_drm_queue.h
index 4e7c8f4..72ab036 100644
--- a/src/amdgpu_drm_queue.h
+++ b/src/amdgpu_drm_queue.h
@@ -46,7 +46,8 @@ void amdgpu_drm_queue_handle_deferred(xf86CrtcPtr crtc);
 uintptr_t amdgpu_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client,
 				 uint64_t id, void *data,
 				 amdgpu_drm_handler_proc handler,
-				 amdgpu_drm_abort_proc abort);
+				 amdgpu_drm_abort_proc abort,
+				 Bool is_flip);
 void amdgpu_drm_abort_client(ClientPtr client);
 void amdgpu_drm_abort_entry(uintptr_t seq);
 void amdgpu_drm_abort_id(uint64_t id);
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 5a5fee2..2622409 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -664,7 +664,8 @@ amdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
 					       AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
 					       AMDGPU_DRM_QUEUE_ID_DEFAULT, NULL,
 					       amdgpu_prime_scanout_update_handler,
-					       amdgpu_prime_scanout_update_abort);
+					       amdgpu_prime_scanout_update_abort,
+					       FALSE);
 	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "amdgpu_drm_queue_alloc failed for PRIME update\n");
@@ -712,7 +713,7 @@ amdgpu_prime_scanout_flip(PixmapDirtyUpdatePtr ent)
 					       AMDGPU_DRM_QUEUE_ID_DEFAULT,
 					       NULL,
 					       amdgpu_scanout_flip_handler,
-					       amdgpu_scanout_flip_abort);
+					       amdgpu_scanout_flip_abort, TRUE);
 	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "Allocating DRM event queue entry failed for PRIME flip.\n");
@@ -940,7 +941,8 @@ amdgpu_scanout_update(xf86CrtcPtr xf86_crtc)
 					       AMDGPU_DRM_QUEUE_ID_DEFAULT,
 					       drmmode_crtc,
 					       amdgpu_scanout_update_handler,
-					       amdgpu_scanout_update_abort);
+					       amdgpu_scanout_update_abort,
+					       FALSE);
 	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "amdgpu_drm_queue_alloc failed for scanout update\n");
@@ -989,7 +991,7 @@ amdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info,
 					       AMDGPU_DRM_QUEUE_ID_DEFAULT,
 					       NULL,
 					       amdgpu_scanout_flip_handler,
-					       amdgpu_scanout_flip_abort);
+					       amdgpu_scanout_flip_abort, TRUE);
 	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "Allocating DRM event queue entry failed.\n");
diff --git a/src/amdgpu_present.c b/src/amdgpu_present.c
index eabe0f3..f9e07a5 100644
--- a/src/amdgpu_present.c
+++ b/src/amdgpu_present.c
@@ -157,7 +157,8 @@ amdgpu_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
 					       AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
 					       event_id, event,
 					       amdgpu_present_vblank_handler,
-					       amdgpu_present_vblank_abort);
+					       amdgpu_present_vblank_abort,
+					       FALSE);
 	if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
 		free(event);
 		return BadAlloc;
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 871a645..23c7349 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -3973,7 +3973,8 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 		drm_queue_seq = amdgpu_drm_queue_alloc(crtc, client, id,
 						       flipdata,
 						       drmmode_flip_handler,
-						       drmmode_flip_abort);
+						       drmmode_flip_abort,
+						       TRUE);
 		if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
 			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 				   "Allocating DRM queue event entry failed.\n");
commit eda571222f5a6be47f8897e82d85199bb9d95251
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Mon Nov 5 18:07:54 2018 +0100

    Use drm_abort_one in drm_queue_handler
    
    At this point, we've already established that e->handler is NULL, no
    need to check again in drm_queue_handle_one. This also makes it clearer
    what's happening.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/amdgpu_drm_queue.c b/src/amdgpu_drm_queue.c
index 0353562..4b51d46 100644
--- a/src/amdgpu_drm_queue.c
+++ b/src/amdgpu_drm_queue.c
@@ -72,6 +72,19 @@ amdgpu_drm_queue_handle_one(struct amdgpu_drm_queue_entry *e)
 	free(e);
 }
 
+/*
+ * Abort one queued DRM entry, removing it
+ * from the list, calling the abort function and
+ * freeing the memory
+ */
+static void
+amdgpu_drm_abort_one(struct amdgpu_drm_queue_entry *e)
+{
+	xorg_list_del(&e->list);
+	e->abort(e->crtc, e->data);
+	free(e);
+}
+
 static void
 amdgpu_drm_queue_handler(struct xorg_list *signalled, unsigned int frame,
 			 unsigned int sec, unsigned int usec, void *user_ptr)
@@ -82,7 +95,7 @@ amdgpu_drm_queue_handler(struct xorg_list *signalled, unsigned int frame,
 	xorg_list_for_each_entry_safe(e, tmp, &amdgpu_drm_queue, list) {
 		if (e->seq == seq) {
 			if (!e->handler) {
-				amdgpu_drm_queue_handle_one(e);
+				amdgpu_drm_abort_one(e);
 				break;
 			}
 
@@ -174,19 +187,6 @@ amdgpu_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client,
 }
 
 /*
- * Abort one queued DRM entry, removing it
- * from the list, calling the abort function and
- * freeing the memory
- */
-static void
-amdgpu_drm_abort_one(struct amdgpu_drm_queue_entry *e)
-{
-	xorg_list_del(&e->list);
-	e->abort(e->crtc, e->data);
-	free(e);
-}
-
-/*
  * Abort drm queue entries for a client
  *
  * NOTE: This keeps the entries in the list until the DRM event arrives,


More information about the xorg-commit mailing list