On Wed, Apr 2, 2014 at 8:38 AM, Tomi Valkeinen <tomi.valkeinen@xxxxxx> 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@xxxxxx> Reviewed-by: Rob Clark <robdclark@xxxxxxxxx> > --- > 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 > _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel