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

Michel Dänzer daenzer at kemper.freedesktop.org
Tue Oct 6 01:18:01 PDT 2015


 src/amdgpu_dri2.c     |   20 ++++++---
 src/amdgpu_drv.h      |    1 
 src/amdgpu_kms.c      |    5 --
 src/amdgpu_present.c  |   85 ++++++++++++++++++++++++++++++--------
 src/amdgpu_probe.c    |    4 -
 src/amdgpu_probe.h    |    3 -
 src/drmmode_display.c |  109 +++++++++++++++++++++++++++-----------------------
 src/drmmode_display.h |   10 +++-
 8 files changed, 150 insertions(+), 87 deletions(-)

New commits:
commit 4b92b960c7705be8b3a5dee17b2341864d7ca9bb
Author: Tom St Denis <tom.stdenis at amd.com>
Date:   Mon Oct 5 10:00:09 2015 -0400

    cleanup the entity rec
    
    Based on radeon commit: b32a0a3de84a44b9af4f1ca8be19f10d7fa31b12
    
    Some of these were set, some of them were
    always opposites, so clean things up.
    
    Signed-off-by: Tom St Denis <tom.stdenis at amd.com>
    Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>

diff --git a/src/amdgpu_drv.h b/src/amdgpu_drv.h
index ff3bc02..4797693 100644
--- a/src/amdgpu_drv.h
+++ b/src/amdgpu_drv.h
@@ -223,7 +223,6 @@ typedef struct {
 #endif
 
 	Bool IsSecondary;
-	Bool IsPrimary;
 
 	Bool shadow_fb;
 	void *fb_shadow;
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 19ee1b1..32a34cb 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -724,7 +724,6 @@ Bool AMDGPUPreInit_KMS(ScrnInfoPtr pScrn, int flags)
 
 	info = AMDGPUPTR(pScrn);
 	info->IsSecondary = FALSE;
-	info->IsPrimary = FALSE;
 	info->pEnt =
 	    xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]);
 	if (info->pEnt->location.type != BUS_PCI
@@ -741,12 +740,8 @@ Bool AMDGPUPreInit_KMS(ScrnInfoPtr pScrn, int flags)
 	if (xf86IsEntityShared(pScrn->entityList[0])) {
 		if (xf86IsPrimInitDone(pScrn->entityList[0])) {
 			info->IsSecondary = TRUE;
-			pAMDGPUEnt->pSecondaryScrn = pScrn;
 		} else {
-			info->IsPrimary = TRUE;
 			xf86SetPrimInitDone(pScrn->entityList[0]);
-			pAMDGPUEnt->pPrimaryScrn = pScrn;
-			pAMDGPUEnt->HasSecondary = FALSE;
 		}
 	}
 
diff --git a/src/amdgpu_probe.c b/src/amdgpu_probe.c
index 7a1a556..481271b 100644
--- a/src/amdgpu_probe.c
+++ b/src/amdgpu_probe.c
@@ -237,7 +237,6 @@ static Bool amdgpu_get_scrninfo(int entity_num, void *pci_dev)
 
 		pPriv->ptr = xnfcalloc(sizeof(AMDGPUEntRec), 1);
 		pAMDGPUEnt = pPriv->ptr;
-		pAMDGPUEnt->HasSecondary = FALSE;
 
 		if (amdgpu_open_drm_master(pScrn)) {
 			goto error_fd;
@@ -255,7 +254,6 @@ static Bool amdgpu_get_scrninfo(int entity_num, void *pci_dev)
 		}
 	} else {
 		pAMDGPUEnt = pPriv->ptr;
-		pAMDGPUEnt->HasSecondary = TRUE;
 	}
 
 	xf86SetEntityInstanceForScreen(pScrn, pEnt->index,
@@ -356,7 +354,6 @@ amdgpu_platform_probe(DriverPtr pDriver,
 
 		pPriv->ptr = xnfcalloc(sizeof(AMDGPUEntRec), 1);
 		pAMDGPUEnt = pPriv->ptr;
-		pAMDGPUEnt->HasSecondary = FALSE;
 		pAMDGPUEnt->fd = amdgpu_kernel_open_fd(pScrn, dev->pdev, dev);
 		if (pAMDGPUEnt->fd < 0)
 			goto error_fd;
@@ -373,7 +370,6 @@ amdgpu_platform_probe(DriverPtr pDriver,
 		}
 	} else {
 		pAMDGPUEnt = pPriv->ptr;
-		pAMDGPUEnt->HasSecondary = TRUE;
 	}
 	pAMDGPUEnt->platform_dev = dev;
 
diff --git a/src/amdgpu_probe.h b/src/amdgpu_probe.h
index 6c187ce..4b4fefb 100644
--- a/src/amdgpu_probe.h
+++ b/src/amdgpu_probe.h
@@ -75,11 +75,8 @@ typedef struct {
 } AMDGPUCardInfo;
 
 typedef struct {
-	Bool HasSecondary;
 	Bool HasCRTC2;		/* All cards except original Radeon  */
 
-	ScrnInfoPtr pSecondaryScrn;
-	ScrnInfoPtr pPrimaryScrn;
 	amdgpu_device_handle pDev;
 
 	int fd;			/* for sharing across zaphod heads   */
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 35c0453..d75a629 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1523,7 +1523,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r
 			if (!AMDGPUZaphodStringMatches(pScrn, s, name))
 				goto out_free_encoders;
 		} else {
-			if (info->IsPrimary && (num != 0))
+			if (!info->IsSecondary && (num != 0))
 				goto out_free_encoders;
 			else if (info->IsSecondary && (num != 1))
 				goto out_free_encoders;
commit fe100fd6bf483228eaf64b959c56a68e8dac4447
Author: Tom St Denis <tom.stdenis at amd.com>
Date:   Mon Oct 5 10:45:33 2015 -0400

    present: Handle DPMS off in radeon_present_get_ust_msc
    
    Based on radeon commit: 95f5d09e3667ded027ae648c97eb4737d8bf67c5
    
    The DRM_IOCTL_WAIT_VBLANK ioctl may return an error during DPMS off,
    which would trigger an error message in drmmode_crtc_get_ust_msc.
    
    Signed-off-by: Tom St Denis <tom.stdenis at amd.com>
    Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>

diff --git a/src/amdgpu_present.c b/src/amdgpu_present.c
index cd20dba..5e5ed72 100644
--- a/src/amdgpu_present.c
+++ b/src/amdgpu_present.c
@@ -87,7 +87,13 @@ amdgpu_present_get_crtc(WindowPtr window)
 static int
 amdgpu_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc)
 {
-	return drmmode_crtc_get_ust_msc(crtc->devPrivate, ust, msc);
+	xf86CrtcPtr xf86_crtc = crtc->devPrivate;
+	drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
+
+	if (drmmode_crtc->dpms_mode != DPMSModeOn)
+		return BadAlloc;
+
+	return drmmode_crtc_get_ust_msc(xf86_crtc, ust, msc);
 }
 
 /*
commit bfa925a04815cee5fd57b99447cb2ee0e158036c
Author: Tom St Denis <tom.stdenis at amd.com>
Date:   Mon Oct 5 10:10:51 2015 -0400

    present: Look at all CRTCs to determine if we can flip
    
    Based on radeon commit 211862b777d0be251a4662f5dd24f2d400544c09
    
    Inspired by modesetting driver change by Kenneth Graunke.
    
    Signed-off-by: Tom St Denis <tom.stdenis at amd.com>
    Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>

diff --git a/src/amdgpu_present.c b/src/amdgpu_present.c
index cbf733a..cd20dba 100644
--- a/src/amdgpu_present.c
+++ b/src/amdgpu_present.c
@@ -213,6 +213,9 @@ amdgpu_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap,
 	ScreenPtr screen = window->drawable.pScreen;
 	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
 	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+	int num_crtcs_on;
+	int i;
 
 	if (!scrn->vtSema)
 		return FALSE;
@@ -226,17 +229,20 @@ amdgpu_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap,
 	if (info->drmmode.dri2_flipping)
 		return FALSE;
 
-	if (crtc) {
-		xf86CrtcPtr xf86_crtc = crtc->devPrivate;
-		drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
+	for (i = 0, num_crtcs_on = 0; i < config->num_crtc; i++) {
+		drmmode_crtc_private_ptr drmmode_crtc = config->crtc[i]->driver_private;
+
+		if (!config->crtc[i]->enabled)
+			continue;
 
-		if (!drmmode_crtc ||
-		    drmmode_crtc->rotate.bo != NULL ||
-		    drmmode_crtc->dpms_mode != DPMSModeOn)
+		if (!drmmode_crtc || drmmode_crtc->rotate.bo != NULL)
 			return FALSE;
+
+		if (drmmode_crtc->dpms_mode == DPMSModeOn)
+			num_crtcs_on++;
 	}
 
-	return TRUE;
+	return num_crtcs_on > 0;
 }
 
 /*
commit a1e47e76322619ed037ebce27974a4e3792940c2
Author: Tom St Denis <tom.stdenis at amd.com>
Date:   Mon Oct 5 10:41:22 2015 -0400

    present: Fall back to modeset for unflip operation
    
    Based on radeon commit: 802d33e474a82262d9cdf11b03568b0c4929cd0d
    
    It's not always possible to use the page flip ioctl for this, e.g.
    during DPMS off. We were previously just skipping the unflip in that
    case, which could result in hangs when setting DPMS off while a
    fullscreen Present app is running, e.g. at the GNOME3 lock screen.
    
    Signed-off-by: Tom St Denis <tom.stdenis at amd.com>
    Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>

diff --git a/src/amdgpu_present.c b/src/amdgpu_present.c
index 3db8cad..cbf733a 100644
--- a/src/amdgpu_present.c
+++ b/src/amdgpu_present.c
@@ -318,31 +318,51 @@ amdgpu_present_unflip(ScreenPtr screen, uint64_t event_id)
 {
 	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
 	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
 	struct amdgpu_present_vblank_event *event;
 	PixmapPtr pixmap = screen->GetScreenPixmap(screen);
 	struct amdgpu_buffer *bo;
-	Bool ret;
+	int i;
 
 	if (!amdgpu_present_check_flip(NULL, screen->root, pixmap, TRUE))
-		return;
+		goto modeset;
 
 	bo = amdgpu_get_pixmap_bo(pixmap);
-	if (!bo)
-		return;
+	if (!bo) {
+		ErrorF("%s: amdgpu_get_pixmap_bo failed, display might freeze\n", __func__);
+		goto modeset;
+	}
 
 	event = calloc(1, sizeof(struct amdgpu_present_vblank_event));
-	if (!event)
-		return;
+	if (!event) {
+		ErrorF("%s: calloc failed, display might freeze\n", __func__);
+		goto modeset;
+	}
 
 	event->event_id = event_id;
 
-	ret = amdgpu_do_pageflip(scrn, AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, bo,
-				 event_id, event, -1, amdgpu_present_flip_event,
-				 amdgpu_present_flip_abort);
-	if (!ret) {
-		xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present unflip failed\n");
-		info->drmmode.present_flipping = FALSE;
+	if (amdgpu_do_pageflip(scrn, AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, bo,
+			       event_id, event, -1, amdgpu_present_flip_event,
+			       amdgpu_present_flip_abort))
+		return;
+
+modeset:
+	for (i = 0; i < config->num_crtc; i++) {
+		xf86CrtcPtr crtc = config->crtc[i];
+		drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+		if (!crtc->enabled)
+			continue;
+
+		if (drmmode_crtc->dpms_mode == DPMSModeOn)
+			crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation,
+						    crtc->x, crtc->y);
+		else
+			drmmode_crtc->need_modeset = TRUE;
 	}
+
+	present_event_notify(event_id, 0, 0);
+	info->drmmode.present_flipping = FALSE;
 }
 
 static present_screen_info_rec amdgpu_present_screen_info = {
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index a57c628..35c0453 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -712,6 +712,9 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 
 		if (crtc->scrn->pScreen)
 			xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen);
+
+		drmmode_crtc->need_modeset = FALSE;
+
 		/* go through all the outputs and force DPMS them back on? */
 		for (i = 0; i < xf86_config->num_output; i++) {
 			xf86OutputPtr output = xf86_config->output[i];
@@ -1089,17 +1092,25 @@ static void drmmode_output_destroy(xf86OutputPtr output)
 static void drmmode_output_dpms(xf86OutputPtr output, int mode)
 {
 	drmmode_output_private_ptr drmmode_output = output->driver_private;
+	xf86CrtcPtr crtc = output->crtc;
 	drmModeConnectorPtr koutput = drmmode_output->mode_output;
 	drmmode_ptr drmmode = drmmode_output->drmmode;
 
-	if (mode != DPMSModeOn && output->crtc)
-		drmmode_do_crtc_dpms(output->crtc, mode);
+	if (mode != DPMSModeOn && crtc)
+		drmmode_do_crtc_dpms(crtc, mode);
 
 	drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id,
 				    drmmode_output->dpms_enum_id, mode);
 
-	if (mode == DPMSModeOn && output->crtc)
-		drmmode_do_crtc_dpms(output->crtc, mode);
+	if (mode == DPMSModeOn && crtc) {
+		drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+		if (drmmode_crtc->need_modeset)
+			drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation,
+					       crtc->x, crtc->y);
+		else
+			drmmode_do_crtc_dpms(output->crtc, mode);
+	}
 }
 
 static Bool drmmode_property_ignore(drmModePropertyPtr prop)
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 78ac9b7..e44e693 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -99,6 +99,9 @@ typedef struct {
 	uint32_t interpolated_vblanks;
 	uint16_t lut_r[256], lut_g[256], lut_b[256];
 	int prime_pixmap_x;
+
+	/* Modeset needed for DPMS on */
+	Bool need_modeset;
 } drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
 
 typedef struct {
commit bac21dfc8e60a07f08158b13fab1f3a9b9d27d1b
Author: Tom St Denis <tom.stdenis at amd.com>
Date:   Mon Oct 5 10:37:50 2015 -0400

    Don't attempt a DRI2/Present page flip while the other one is flipping
    
    Based on radeon commit 49f5b0bc301414df049e00d226034e3d6e56421b
    
    Fixes corrupted display and hangs when switching between DRI2 and DRI3
    fullscreen apps, e.g. a compositor using DRI3 and a fullscreen app using
    DRI2 or vice versa.
    
    Signed-off-by: Tom St Denis <tom.stdenis at amd.com>
    Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>

diff --git a/src/amdgpu_dri2.c b/src/amdgpu_dri2.c
index 1370551..756d6ad 100644
--- a/src/amdgpu_dri2.c
+++ b/src/amdgpu_dri2.c
@@ -528,6 +528,7 @@ static void
 amdgpu_dri2_flip_event_handler(ScrnInfoPtr scrn, uint32_t frame, uint64_t usec,
 			       void *event_data)
 {
+	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
 	DRI2FrameEventPtr flip = event_data;
 	unsigned tv_sec, tv_usec;
 	DrawablePtr drawable;
@@ -572,6 +573,7 @@ amdgpu_dri2_flip_event_handler(ScrnInfoPtr scrn, uint32_t frame, uint64_t usec,
 		DRI2SwapComplete(flip->client, drawable, frame, tv_sec, tv_usec,
 				 DRI2_FLIP_COMPLETE, flip->event_complete,
 				 flip->event_data);
+		info->drmmode.dri2_flipping = FALSE;
 		break;
 	default:
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
@@ -590,6 +592,7 @@ amdgpu_dri2_schedule_flip(ScrnInfoPtr scrn, ClientPtr client,
 			  DRI2BufferPtr back, DRI2SwapEventPtr func,
 			  void *data, unsigned int target_msc)
 {
+	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
 	struct dri2_buffer_priv *back_priv;
 	struct amdgpu_buffer *bo = NULL;
 	DRI2FrameEventPtr flip_info;
@@ -616,10 +619,14 @@ amdgpu_dri2_schedule_flip(ScrnInfoPtr scrn, ClientPtr client,
 	back_priv = back->driverPrivate;
 	bo = amdgpu_get_pixmap_bo(back_priv->pixmap);
 
-	return amdgpu_do_pageflip(scrn, client, bo, AMDGPU_DRM_QUEUE_ID_DEFAULT,
-				  flip_info, ref_crtc_hw_id,
-				  amdgpu_dri2_flip_event_handler,
-				  amdgpu_dri2_flip_event_abort);
+	if (amdgpu_do_pageflip(scrn, client, bo, AMDGPU_DRM_QUEUE_ID_DEFAULT,
+			       flip_info, ref_crtc_hw_id,
+			       amdgpu_dri2_flip_event_handler,
+			       amdgpu_dri2_flip_event_abort)) {
+		info->drmmode.dri2_flipping = TRUE;
+		return TRUE;
+	}
+	return FALSE;
 }
 
 static Bool update_front(DrawablePtr draw, DRI2BufferPtr front)
@@ -698,8 +705,11 @@ static Bool
 can_flip(ScrnInfoPtr pScrn, DrawablePtr draw,
 	 DRI2BufferPtr front, DRI2BufferPtr back)
 {
+	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
+
 	return draw->type == DRAWABLE_WINDOW &&
-	    AMDGPUPTR(pScrn)->allowPageFlip &&
+	    info->allowPageFlip &&
+	    !info->drmmode.present_flipping &&
 	    pScrn->vtSema &&
 	    DRI2CanFlip(draw) && can_exchange(pScrn, draw, front, back);
 }
diff --git a/src/amdgpu_present.c b/src/amdgpu_present.c
index 75a4ba3..3db8cad 100644
--- a/src/amdgpu_present.c
+++ b/src/amdgpu_present.c
@@ -50,6 +50,7 @@
 
 struct amdgpu_present_vblank_event {
 	uint64_t event_id;
+	xf86CrtcPtr crtc;
 };
 
 static uint32_t crtc_select(int crtc_id)
@@ -222,6 +223,9 @@ amdgpu_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap,
 	if (!sync_flip)
 		return FALSE;
 
+	if (info->drmmode.dri2_flipping)
+		return FALSE;
+
 	if (crtc) {
 		xf86CrtcPtr xf86_crtc = crtc->devPrivate;
 		drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
@@ -242,8 +246,12 @@ amdgpu_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap,
 static void
 amdgpu_present_flip_event(ScrnInfoPtr scrn, uint32_t msc, uint64_t ust, void *pageflip_data)
 {
+	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
 	struct amdgpu_present_vblank_event *event = pageflip_data;
 
+	if (!event->crtc)
+		info->drmmode.present_flipping = FALSE;
+
 	present_event_notify(event->event_id, ust, msc);
 	free(event);
 }
@@ -269,6 +277,7 @@ amdgpu_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc,
 {
 	ScreenPtr screen = crtc->pScreen;
 	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
 	struct amdgpu_present_vblank_event *event;
 	xf86CrtcPtr xf86_crtc = crtc->devPrivate;
 	int crtc_id = xf86_crtc ? drmmode_get_crtc_id(xf86_crtc) : -1;
@@ -287,6 +296,7 @@ amdgpu_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc,
 		return FALSE;
 
 	event->event_id = event_id;
+	event->crtc = xf86_crtc;
 
 	ret = amdgpu_do_pageflip(scrn, AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, bo,
 				 event_id, event, crtc_id,
@@ -294,6 +304,8 @@ amdgpu_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc,
 				 amdgpu_present_flip_abort);
 	if (!ret)
 		xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present flip failed\n");
+	else
+		info->drmmode.present_flipping = TRUE;
 
 	return ret;
 }
@@ -305,6 +317,7 @@ static void
 amdgpu_present_unflip(ScreenPtr screen, uint64_t event_id)
 {
 	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
 	struct amdgpu_present_vblank_event *event;
 	PixmapPtr pixmap = screen->GetScreenPixmap(screen);
 	struct amdgpu_buffer *bo;
@@ -326,8 +339,10 @@ amdgpu_present_unflip(ScreenPtr screen, uint64_t event_id)
 	ret = amdgpu_do_pageflip(scrn, AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, bo,
 				 event_id, event, -1, amdgpu_present_flip_event,
 				 amdgpu_present_flip_abort);
-	if (!ret)
+	if (!ret) {
 		xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present unflip failed\n");
+		info->drmmode.present_flipping = FALSE;
+	}
 }
 
 static present_screen_info_rec amdgpu_present_screen_info = {
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index d541d47..78ac9b7 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -54,6 +54,9 @@ typedef struct {
 	int count_crtcs;
 
 	Bool delete_dp_12_displays;
+
+	Bool dri2_flipping;
+	Bool present_flipping;
 } drmmode_rec, *drmmode_ptr;
 
 typedef struct {
commit a5f7f2e68bad1935f5ad52286033237467f77302
Author: Tom St Denis <tom.stdenis at amd.com>
Date:   Mon Oct 5 13:12:23 2015 -0400

    Move amdgpu_drm_handler/abort_proc fields to drmmode_flipdata_re
    
    Based on radeon commit de5ddd09db82141b263338dcf0c28e01f58268ee
    
    Their values are the same for all DRM flip ioctl calls within a single
    radeon_do_pageflip() call.
    
    Signed-off-by: Tom St Denis <tom.stdenis at amd.com>
    Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 174cda3..a57c628 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1816,7 +1816,7 @@ drmmode_flip_abort(ScrnInfoPtr scrn, void *event_data)
 	drmmode_flipdata_ptr flipdata = flipcarrier->flipdata;
 
 	if (flipdata->flip_count == 1)
-		flipcarrier->abort(scrn, flipdata->event_data);
+		flipdata->abort(scrn, flipdata->event_data);
 
 	drmmode_flip_free(flipcarrier);
 }
@@ -1837,9 +1837,9 @@ drmmode_flip_handler(ScrnInfoPtr scrn, uint32_t frame, uint64_t usec, void *even
 	if (flipdata->flip_count == 1) {
 		/* Deliver cached msc, ust from reference crtc to flip event handler */
 		if (flipdata->event_data)
-			flipcarrier->handler(scrn, flipdata->fe_frame,
-					     flipdata->fe_usec,
-					     flipdata->event_data);
+			flipdata->handler(scrn, flipdata->fe_frame,
+					  flipdata->fe_usec,
+					  flipdata->event_data);
 
 		/* Release framebuffer */
 		drmModeRmFB(flipdata->drmmode->fd, flipdata->old_fb_id);
@@ -2314,6 +2314,8 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 
 	flipdata->event_data = data;
 	flipdata->drmmode = drmmode;
+	flipdata->handler = handler;
+	flipdata->abort = abort;
 
 	for (i = 0; i < config->num_crtc; i++) {
 		if (!config->crtc[i]->enabled)
@@ -2335,8 +2337,6 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 		flipcarrier->dispatch_me =
 		    (drmmode_crtc->hw_id == ref_crtc_hw_id);
 		flipcarrier->flipdata = flipdata;
-		flipcarrier->handler = handler;
-		flipcarrier->abort = abort;
 
 		drm_queue = amdgpu_drm_queue_alloc(scrn, client, id,
 						   flipcarrier,
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index 177dfc7..d541d47 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -63,13 +63,13 @@ typedef struct {
 	void *event_data;
 	unsigned int fe_frame;
 	uint64_t fe_usec;
+	amdgpu_drm_handler_proc handler;
+	amdgpu_drm_abort_proc abort;
 } drmmode_flipdata_rec, *drmmode_flipdata_ptr;
 
 typedef struct {
 	drmmode_flipdata_ptr flipdata;
 	Bool dispatch_me;
-	amdgpu_drm_handler_proc handler;
-	amdgpu_drm_abort_proc abort;
 } drmmode_flipevtcarrier_rec, *drmmode_flipevtcarrier_ptr;
 
 struct drmmode_scanout {
commit e14e3560bff2537d3ad4c93d2b31442a122cde66
Author: Tom St Denis <tom.stdenis at amd.com>
Date:   Mon Oct 5 13:08:43 2015 -0400

    Simplify amdgpu_do_pageflip() error handling slightly more
    
    Based on radeon commit e8c0f6319fbf4c3ea11e22ab1a68837031bdec8c
    
    We don't need the local variable old_fb_id.
    
    Signed-off-by: Tom St Denis <tom.stdenis at amd.com>
    
    [ Michel Dänzer: fix up slightly to better match radeon formatting ]
    
    Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 9b3896e..174cda3 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -2264,9 +2264,9 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 	drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private;
 	drmmode_ptr drmmode = drmmode_crtc->drmmode;
 	unsigned int pitch;
-	int i, old_fb_id;
+	int i;
 	int height;
-	drmmode_flipdata_ptr flipdata;
+	drmmode_flipdata_ptr flipdata = NULL;
 	drmmode_flipevtcarrier_ptr flipcarrier = NULL;
 	struct amdgpu_drm_queue_entry *drm_queue = NULL;
 	union gbm_bo_handle bo_handle;
@@ -2283,25 +2283,25 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 		if (amdgpu_bo_export(new_front->bo.amdgpu,
 				amdgpu_bo_handle_type_kms,
 				&handle))
-			goto error_out;
+			goto error;
 	}
 
-	/*
-	 * Create a new handle for the back buffer
-	 */
-	old_fb_id = drmmode->fb_id;
-
-	if (drmModeAddFB(drmmode->fd, scrn->virtualX, height,
-			 scrn->depth, scrn->bitsPerPixel, pitch,
-			 handle, &drmmode->fb_id)) {
-		goto error_out;
-	}
 	flipdata = calloc(1, sizeof(drmmode_flipdata_rec));
 	if (!flipdata) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "flip queue: data alloc failed.\n");
-		goto error_undo;
+		goto error;
 	}
+
+	/*
+	 * Create a new handle for the back buffer
+	 */
+	flipdata->old_fb_id = drmmode->fb_id;
+	if (drmModeAddFB(drmmode->fd, scrn->virtualX, height,
+			 scrn->depth, scrn->bitsPerPixel, pitch,
+			 handle, &drmmode->fb_id))
+		goto error;
+
 	/*
 	 * Queue flips on all enabled CRTCs
 	 * Note that if/when we get per-CRTC buffers, we'll have to update this.
@@ -2314,7 +2314,6 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 
 	flipdata->event_data = data;
 	flipdata->drmmode = drmmode;
-	flipdata->old_fb_id = old_fb_id;
 
 	for (i = 0; i < config->num_crtc; i++) {
 		if (!config->crtc[i]->enabled)
@@ -2327,7 +2326,7 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 		if (!flipcarrier) {
 			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 				   "flip queue: carrier alloc failed.\n");
-			goto error_undo;
+			goto error;
 		}
 
 		/* Only the reference crtc will finally deliver its page flip
@@ -2346,7 +2345,7 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 		if (!drm_queue) {
 			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 				   "Allocating DRM queue event entry failed.\n");
-			goto error_undo;
+			goto error;
 		}
 
 		if (drmModePageFlip(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
@@ -2354,7 +2353,7 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 				    drm_queue)) {
 			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 				   "flip queue failed: %s\n", strerror(errno));
-			goto error_undo;
+			goto error;
 		}
 		flipcarrier = NULL;
 		drm_queue = NULL;
@@ -2363,10 +2362,10 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 	if (flipdata->flip_count > 0)
 		return TRUE;
 
-error_undo:
-	if (!flipdata || flipdata->flip_count <= 1) {
+error:
+	if (flipdata && flipdata->flip_count <= 1) {
 		drmModeRmFB(drmmode->fd, drmmode->fb_id);
-		drmmode->fb_id = old_fb_id;
+		drmmode->fb_id = flipdata->old_fb_id;
 	}
 
 	if (drm_queue)
@@ -2376,7 +2375,6 @@ error_undo:
 	else if (flipdata && flipdata->flip_count <= 1)
 		free(flipdata);
 
-error_out:
 	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",
 		   strerror(errno));
 	return FALSE;
commit e9621ec0e2400f62db320c560a739b29258edb87
Author: Tom St Denis <tom.stdenis at amd.com>
Date:   Mon Oct 5 09:34:47 2015 -0400

    Increase robustness against DRM page flip ioctl failures
    
    Based on radeon commit 8fc22360d5520469c82092ccb0fcf2af330c573f
    
    Centralize cleanup, only clean up things that have been allocated for
    the failed ioctl call.
    
    Fixes double-free after a flip ioctl failure.
    
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=89681
    
    Signed-off-by: Tom St Denis <tom.stdenis at amd.com>
    Reviewed-by: Michel Dänzer <michel.daenzer at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 7328bfd..9b3896e 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1806,9 +1806,6 @@ drmmode_flip_free(drmmode_flipevtcarrier_ptr flipcarrier)
 	if (--flipdata->flip_count > 0)
 		return;
 
-	/* Release framebuffer */
-	drmModeRmFB(flipdata->drmmode->fd, flipdata->old_fb_id);
-
 	free(flipdata);
 }
 
@@ -1837,10 +1834,16 @@ drmmode_flip_handler(ScrnInfoPtr scrn, uint32_t frame, uint64_t usec, void *even
 		flipdata->fe_usec = usec;
 	}
 
-	/* Deliver cached msc, ust from reference crtc to flip event handler */
-	if (flipdata->event_data && flipdata->flip_count == 1)
-		flipcarrier->handler(scrn, flipdata->fe_frame, flipdata->fe_usec,
-				     flipdata->event_data);
+	if (flipdata->flip_count == 1) {
+		/* Deliver cached msc, ust from reference crtc to flip event handler */
+		if (flipdata->event_data)
+			flipcarrier->handler(scrn, flipdata->fe_frame,
+					     flipdata->fe_usec,
+					     flipdata->event_data);
+
+		/* Release framebuffer */
+		drmModeRmFB(flipdata->drmmode->fd, flipdata->old_fb_id);
+	}
 
 	drmmode_flip_free(flipcarrier);
 }
@@ -2262,10 +2265,10 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 	drmmode_ptr drmmode = drmmode_crtc->drmmode;
 	unsigned int pitch;
 	int i, old_fb_id;
-	int height, emitted = 0;
+	int height;
 	drmmode_flipdata_ptr flipdata;
 	drmmode_flipevtcarrier_ptr flipcarrier = NULL;
-	struct amdgpu_drm_queue_entry *drm_queue = 0;
+	struct amdgpu_drm_queue_entry *drm_queue = NULL;
 	union gbm_bo_handle bo_handle;
 	uint32_t handle;
 
@@ -2311,6 +2314,7 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 
 	flipdata->event_data = data;
 	flipdata->drmmode = drmmode;
+	flipdata->old_fb_id = old_fb_id;
 
 	for (i = 0; i < config->num_crtc; i++) {
 		if (!config->crtc[i]->enabled)
@@ -2323,8 +2327,6 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 		if (!flipcarrier) {
 			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 				   "flip queue: carrier alloc failed.\n");
-			if (emitted == 0)
-				free(flipdata);
 			goto error_undo;
 		}
 
@@ -2352,25 +2354,27 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
 				    drm_queue)) {
 			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 				   "flip queue failed: %s\n", strerror(errno));
-			free(flipcarrier);
-			if (emitted == 0)
-				free(flipdata);
 			goto error_undo;
 		}
-		emitted++;
+		flipcarrier = NULL;
+		drm_queue = NULL;
 	}
 
-	flipdata->old_fb_id = old_fb_id;
-	return TRUE;
+	if (flipdata->flip_count > 0)
+		return TRUE;
 
 error_undo:
+	if (!flipdata || flipdata->flip_count <= 1) {
+		drmModeRmFB(drmmode->fd, drmmode->fb_id);
+		drmmode->fb_id = old_fb_id;
+	}
+
 	if (drm_queue)
 		amdgpu_drm_abort_entry(drm_queue);
-	else
+	else if (flipcarrier)
 		drmmode_flip_abort(scrn, flipcarrier);
-
-	drmModeRmFB(drmmode->fd, drmmode->fb_id);
-	drmmode->fb_id = old_fb_id;
+	else if (flipdata && flipdata->flip_count <= 1)
+		free(flipdata);
 
 error_out:
 	xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",


More information about the xorg-commit mailing list