diff options
author | Michel Dänzer <michel.daenzer@amd.com> | 2019-01-16 10:26:59 +0100 |
---|---|---|
committer | Michel Dänzer <michel@daenzer.net> | 2019-01-17 11:34:04 +0100 |
commit | e72a02ba1d35743fefd939458b9d8cddce86e7f5 (patch) | |
tree | 68ee6e9290d6d92abf91978e66d9f55a8a809000 /src | |
parent | a1b479c7d0066c481af920f297d6af9009dda11e (diff) |
Only update drmmode_crtc->flip_pending after actually submitting a flip
And only clear it if it matches the framebuffer of the completed flip
being processed.
Fixes
(WW) AMDGPU(0): flip queue failed: Device or resource busy
(WW) AMDGPU(0): Page flip failed: Device or resource busy
(EE) AMDGPU(0): present flip failed
due to clobbering drmmode_crtc->flip_pending.
Reproducer: Enable TearFree, run warzone2100 fullscreen, toggle
Vertical sync on/off under Video Options. Discovered while investigating
https://bugs.freedesktop.org/109364 .
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/amdgpu_kms.c | 66 | ||||
-rw-r--r-- | src/drmmode_display.c | 15 |
2 files changed, 43 insertions, 38 deletions
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c index feefd67..05becb2 100644 --- a/src/amdgpu_kms.c +++ b/src/amdgpu_kms.c @@ -491,10 +491,14 @@ amdgpu_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data) { AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn); drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + struct drmmode_fb *fb = event_data; drmmode_crtc->scanout_update_pending = 0; - drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending, - NULL); + + if (drmmode_crtc->flip_pending == fb) { + drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending, + NULL); + } } static void @@ -503,9 +507,9 @@ amdgpu_scanout_flip_handler(xf86CrtcPtr crtc, uint32_t msc, uint64_t usec, { AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn); drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + struct drmmode_fb *fb = event_data; - drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->fb, - drmmode_crtc->flip_pending); + drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->fb, fb); amdgpu_scanout_flip_abort(crtc, event_data); } @@ -786,24 +790,31 @@ amdgpu_prime_scanout_flip(PixmapDirtyUpdatePtr ent) drmmode_crtc_private_ptr drmmode_crtc; uintptr_t drm_queue_seq; unsigned scanout_id; + struct drmmode_fb *fb; if (!crtc || !crtc->enabled) return; drmmode_crtc = crtc->driver_private; + scanout_id = drmmode_crtc->scanout_id ^ 1; if (drmmode_crtc->scanout_update_pending || - !drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap || + !drmmode_crtc->scanout[scanout_id].pixmap || drmmode_crtc->dpms_mode != DPMSModeOn) return; - scanout_id = drmmode_crtc->scanout_id ^ 1; if (!amdgpu_prime_scanout_do_update(crtc, scanout_id)) return; + fb = amdgpu_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap); + if (!fb) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "Failed to get FB for PRIME flip.\n"); + return; + } + drm_queue_seq = amdgpu_drm_queue_alloc(crtc, AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, - AMDGPU_DRM_QUEUE_ID_DEFAULT, - NULL, + AMDGPU_DRM_QUEUE_ID_DEFAULT, fb, amdgpu_scanout_flip_handler, amdgpu_scanout_flip_abort, TRUE); if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) { @@ -812,18 +823,9 @@ amdgpu_prime_scanout_flip(PixmapDirtyUpdatePtr ent) return; } - drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending, - amdgpu_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap)); - if (!drmmode_crtc->flip_pending) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "Failed to get FB for PRIME flip.\n"); - amdgpu_drm_abort_entry(drm_queue_seq); - return; - } - if (drmmode_page_flip_target_relative(pAMDGPUEnt, drmmode_crtc, - drmmode_crtc->flip_pending->handle, - 0, drm_queue_seq, 1) != 0) { + fb->handle, 0, drm_queue_seq, 1) + != 0) { if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED)) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s, TearFree inactive\n", @@ -842,6 +844,7 @@ amdgpu_prime_scanout_flip(PixmapDirtyUpdatePtr ent) drmmode_crtc->scanout_id = scanout_id; drmmode_crtc->scanout_update_pending = drm_queue_seq; + drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending, fb); } static void @@ -1094,6 +1097,7 @@ amdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info, AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); uintptr_t drm_queue_seq; unsigned scanout_id; + struct drmmode_fb *fb; if (drmmode_crtc->scanout_update_pending || drmmode_crtc->flip_pending || @@ -1109,10 +1113,16 @@ amdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info, amdgpu_glamor_flush(scrn); RegionEmpty(region); + fb = amdgpu_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap); + if (!fb) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "Failed to get FB for scanout flip.\n"); + return; + } + drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc, AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, - AMDGPU_DRM_QUEUE_ID_DEFAULT, - NULL, + AMDGPU_DRM_QUEUE_ID_DEFAULT, fb, amdgpu_scanout_flip_handler, amdgpu_scanout_flip_abort, TRUE); if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) { @@ -1121,18 +1131,9 @@ amdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info, return; } - drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending, - amdgpu_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap)); - if (!drmmode_crtc->flip_pending) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "Failed to get FB for scanout flip.\n"); - amdgpu_drm_abort_entry(drm_queue_seq); - return; - } - if (drmmode_page_flip_target_relative(pAMDGPUEnt, drmmode_crtc, - drmmode_crtc->flip_pending->handle, - 0, drm_queue_seq, 1) != 0) { + fb->handle, 0, drm_queue_seq, 1) + != 0) { if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED)) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s, TearFree inactive\n", @@ -1158,6 +1159,7 @@ amdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info, drmmode_crtc->scanout_id = scanout_id; drmmode_crtc->scanout_update_pending = drm_queue_seq; + drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending, fb); } static void AMDGPUBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL) diff --git a/src/drmmode_display.c b/src/drmmode_display.c index aea53ad..859c01e 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -3210,12 +3210,14 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even flipdata->fe_usec = usec; } - if (drmmode_crtc->flip_pending == *fb) { - drmmode_fb_reference(pAMDGPUEnt->fd, - &drmmode_crtc->flip_pending, NULL); + if (*fb) { + if (drmmode_crtc->flip_pending == *fb) { + drmmode_fb_reference(pAMDGPUEnt->fd, + &drmmode_crtc->flip_pending, NULL); + } + drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->fb, *fb); + drmmode_fb_reference(pAMDGPUEnt->fd, fb, NULL); } - drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->fb, *fb); - drmmode_fb_reference(pAMDGPUEnt->fd, fb, NULL); if (--flipdata->flip_count == 0) { /* Deliver MSC & UST from reference/current CRTC to flip event @@ -4125,9 +4127,10 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, drmmode_crtc->ignore_damage = TRUE; } - next: drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending, flipdata->fb[crtc_id]); + + next: drm_queue_seq = 0; } |