[PATCH 4/4] drm/omap: fix race issue when unloading omapdrm
Rob Clark
robdclark at gmail.com
Wed Apr 2 07:08:41 PDT 2014
On Wed, Apr 2, 2014 at 8:38 AM, Tomi Valkeinen <tomi.valkeinen at ti.com> wrote:
> At module unload, omap_fbdev_free() gets called which releases the
> framebuffers. However, the framebuffers are still used by crtcs, and
> will be released only later at vsync. The driver doesn't wait for this,
> and goes on to release the rest of the resources, which often
> causes a crash.
>
> This patchs adds a omap_crtc_flush() function which waits until the crtc
> has finished with its apply queue and page flips.
>
> The function utilizes a simple polling while-loop, as the performance is
> not an issue here.
>
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen at ti.com>
Reviewed-by: Rob Clark <robdclark at gmail.com>
> ---
> drivers/gpu/drm/omapdrm/omap_crtc.c | 19 +++++++++++++++++++
> drivers/gpu/drm/omapdrm/omap_drv.c | 6 ++++++
> drivers/gpu/drm/omapdrm/omap_drv.h | 1 +
> 3 files changed, 26 insertions(+)
>
> diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
> index e7b643c178a6..4f624c59a660 100644
> --- a/drivers/gpu/drm/omapdrm/omap_crtc.c
> +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
> @@ -620,6 +620,25 @@ static void omap_crtc_post_apply(struct omap_drm_apply *apply)
> /* nothing needed for post-apply */
> }
>
> +void omap_crtc_flush(struct drm_crtc *crtc)
> +{
> + struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
> + int loops = 0;
> +
> + while (!list_empty(&omap_crtc->pending_applies) ||
> + !list_empty(&omap_crtc->queued_applies) ||
> + omap_crtc->event || omap_crtc->old_fb) {
> +
> + if (++loops > 10) {
> + dev_err(crtc->dev->dev,
> + "omap_crtc_flush() timeout\n");
> + break;
> + }
> +
> + schedule_timeout_uninterruptible(msecs_to_jiffies(20));
> + }
> +}
> +
> static const char *channel_names[] = {
> [OMAP_DSS_CHANNEL_LCD] = "lcd",
> [OMAP_DSS_CHANNEL_DIGIT] = "tv",
> diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
> index f16a07d1668d..c8270e4b26f3 100644
> --- a/drivers/gpu/drm/omapdrm/omap_drv.c
> +++ b/drivers/gpu/drm/omapdrm/omap_drv.c
> @@ -513,12 +513,18 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
> static int dev_unload(struct drm_device *dev)
> {
> struct omap_drm_private *priv = dev->dev_private;
> + int i;
>
> DBG("unload: dev=%p", dev);
>
> drm_kms_helper_poll_fini(dev);
>
> omap_fbdev_free(dev);
> +
> + /* flush crtcs so the fbs get released */
> + for (i = 0; i < priv->num_crtcs; i++)
> + omap_crtc_flush(priv->crtcs[i]);
> +
> omap_modeset_free(dev);
> omap_gem_deinit(dev);
>
> diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
> index 428b2981fd68..284b80fc3c54 100644
> --- a/drivers/gpu/drm/omapdrm/omap_drv.h
> +++ b/drivers/gpu/drm/omapdrm/omap_drv.h
> @@ -163,6 +163,7 @@ void omap_crtc_pre_init(void);
> void omap_crtc_pre_uninit(void);
> struct drm_crtc *omap_crtc_init(struct drm_device *dev,
> struct drm_plane *plane, enum omap_channel channel, int id);
> +void omap_crtc_flush(struct drm_crtc *crtc);
>
> struct drm_plane *omap_plane_init(struct drm_device *dev,
> int plane_id, bool private_plane);
> --
> 1.8.3.2
>
More information about the dri-devel
mailing list