Commit e9621ec0 authored by Tom Denis's avatar Tom Denis Committed by Michel Dänzer
Browse files

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 Denis's avatarTom St Denis <tom.stdenis@amd.com>
Reviewed-by: Michel Dänzer's avatarMichel Dänzer <michel.daenzer@amd.com>
parent db3bb206
......@@ -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",
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment