[PATCH xf86-video-amdgpu] Store FB for each CRTC in drmmode_flipdata_rec
Alex Deucher
alexdeucher at gmail.com
Mon Jul 30 18:12:57 UTC 2018
On Fri, Jul 27, 2018 at 12:04 PM, Michel Dänzer <michel at daenzer.net> wrote:
> From: Michel Dänzer <michel.daenzer at amd.com>
>
> We were only storing the FB provided by the client, but on CRTCs with
> TearFree enabled, we use a separate FB. This could cause
> drmmode_flip_handler to fail to clear drmmode_crtc->flip_pending, which
> could result in a hang when waiting for the pending flip to complete. We
> were trying to avoid that by always clearing drmmode_crtc->flip_pending
> when TearFree is enabled, but that wasn't reliable, because
> drmmode_crtc->tear_free can already be FALSE at this point when
> disabling TearFree.
>
> Now that we're keeping track of each CRTC's flip FB separately,
> drmmode_flip_handler can reliably clear flip_pending, and we no longer
> need the TearFree hack.
>
> Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
> ---
> src/drmmode_display.c | 47 ++++++++++++++++++++++++-------------------
> src/drmmode_display.h | 2 +-
> 2 files changed, 27 insertions(+), 22 deletions(-)
>
> diff --git a/src/drmmode_display.c b/src/drmmode_display.c
> index 92f58c157..e58e15d7b 100644
> --- a/src/drmmode_display.c
> +++ b/src/drmmode_display.c
> @@ -3051,17 +3051,21 @@ drmmode_flip_abort(xf86CrtcPtr crtc, void *event_data)
> drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
> AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn);
> drmmode_flipdata_ptr flipdata = event_data;
> + int crtc_id = drmmode_get_crtc_id(crtc);
> + struct drmmode_fb **fb = &flipdata->fb[crtc_id];
> +
> + if (drmmode_crtc->flip_pending == *fb) {
> + drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending,
> + NULL);
> + }
> + drmmode_fb_reference(pAMDGPUEnt->fd, fb, NULL);
>
> if (--flipdata->flip_count == 0) {
> if (!flipdata->fe_crtc)
> flipdata->fe_crtc = crtc;
> flipdata->abort(flipdata->fe_crtc, flipdata->event_data);
> - drmmode_fb_reference(pAMDGPUEnt->fd, &flipdata->fb, NULL);
> free(flipdata);
> }
> -
> - drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending,
> - NULL);
> }
>
> static void
> @@ -3070,6 +3074,8 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even
> AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(crtc->scrn);
> drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
> drmmode_flipdata_ptr flipdata = event_data;
> + int crtc_id = drmmode_get_crtc_id(crtc);
> + struct drmmode_fb **fb = &flipdata->fb[crtc_id];
>
> /* Is this the event whose info shall be delivered to higher level? */
> if (crtc == flipdata->fe_crtc) {
> @@ -3078,13 +3084,12 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even
> flipdata->fe_usec = usec;
> }
>
> - drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->fb,
> - flipdata->fb);
> - if (drmmode_crtc->tear_free ||
> - drmmode_crtc->flip_pending == flipdata->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);
>
> if (--flipdata->flip_count == 0) {
> /* Deliver MSC & UST from reference/current CRTC to flip event
> @@ -3096,7 +3101,6 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even
> else
> flipdata->handler(crtc, frame, usec, flipdata->event_data);
>
> - drmmode_fb_reference(pAMDGPUEnt->fd, &flipdata->fb, NULL);
> free(flipdata);
> }
> }
> @@ -3875,21 +3879,22 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
> xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
> xf86CrtcPtr crtc = NULL;
> drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private;
> - int i;
> uint32_t flip_flags = flip_sync == FLIP_ASYNC ? DRM_MODE_PAGE_FLIP_ASYNC : 0;
> drmmode_flipdata_ptr flipdata;
> uintptr_t drm_queue_seq = 0;
> + struct drmmode_fb *fb;
> + int i = 0;
>
> - flipdata = calloc(1, sizeof(drmmode_flipdata_rec));
> + flipdata = calloc(1, sizeof(*flipdata) + config->num_crtc *
> + sizeof(flipdata->fb[0]));
> if (!flipdata) {
> xf86DrvMsg(scrn->scrnIndex, X_WARNING,
> "flip queue: data alloc failed.\n");
> goto error;
> }
>
> - drmmode_fb_reference(pAMDGPUEnt->fd, &flipdata->fb,
> - amdgpu_pixmap_get_fb(new_front));
> - if (!flipdata->fb) {
> + fb = amdgpu_pixmap_get_fb(new_front);
> + if (!fb) {
> ErrorF("Failed to get FB for flip\n");
> goto error;
> }
> @@ -3910,8 +3915,6 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
> flipdata->fe_crtc = ref_crtc;
>
> for (i = 0; i < config->num_crtc; i++) {
> - struct drmmode_fb *fb = flipdata->fb;
> -
> crtc = config->crtc[i];
> drmmode_crtc = crtc->driver_private;
>
> @@ -3947,8 +3950,9 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
> goto next;
> }
>
> - fb = amdgpu_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap);
> - if (!fb) {
> + drmmode_fb_reference(pAMDGPUEnt->fd, &flipdata->fb[i],
> + amdgpu_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap));
> + if (!flipdata->fb[i]) {
> ErrorF("Failed to get FB for TearFree flip\n");
> goto error;
> }
> @@ -3963,6 +3967,8 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
> amdgpu_drm_abort_entry(drmmode_crtc->scanout_update_pending);
> drmmode_crtc->scanout_update_pending = 0;
> }
> + } else {
> + drmmode_fb_reference(pAMDGPUEnt->fd, &flipdata->fb[i], fb);
> }
>
> if (crtc == ref_crtc) {
> @@ -3988,8 +3994,8 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
> }
>
> next:
> - drmmode_fb_reference(pAMDGPUEnt->fd,
> - &drmmode_crtc->flip_pending, fb);
> + drmmode_fb_reference(pAMDGPUEnt->fd, &drmmode_crtc->flip_pending,
> + flipdata->fb[i]);
> drm_queue_seq = 0;
> }
>
> @@ -4007,7 +4013,6 @@ error:
> drmmode_flip_abort(crtc, flipdata);
> else {
> abort(NULL, data);
> - drmmode_fb_reference(pAMDGPUEnt->fd, &flipdata->fb, NULL);
> free(flipdata);
> }
>
> diff --git a/src/drmmode_display.h b/src/drmmode_display.h
> index 8b949f79d..5618c6b40 100644
> --- a/src/drmmode_display.h
> +++ b/src/drmmode_display.h
> @@ -74,7 +74,6 @@ typedef struct {
> } drmmode_rec, *drmmode_ptr;
>
> typedef struct {
> - struct drmmode_fb *fb;
> void *event_data;
> int flip_count;
> unsigned int fe_frame;
> @@ -82,6 +81,7 @@ typedef struct {
> xf86CrtcPtr fe_crtc;
> amdgpu_drm_handler_proc handler;
> amdgpu_drm_abort_proc abort;
> + struct drmmode_fb *fb[0];
Don't some compilers have problems with zero sized arrays? Other than
that looks good to me:
Reviewed-by: Alex Deucher <alexander.deucher at amd.com>
Alex
> } drmmode_flipdata_rec, *drmmode_flipdata_ptr;
>
> struct drmmode_fb {
> --
> 2.18.0
>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
More information about the amd-gfx
mailing list