[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