aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2014-04-02 07:31:57 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2014-04-14 05:34:14 -0400
commite2f8fd74ec1bf15cb2abc1b11f7d9fa09581024e (patch)
tree020db67510226850520f26769da44549f46d050f
parentea7e3a662814447cd329390feddd04b9ec0a4b82 (diff)
drm/omap: fix race issue when unloading omapdrm
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@ti.com> Reviewed-by: Rob Clark <robdclark@gmail.com>
-rw-r--r--drivers/gpu/drm/omapdrm/omap_crtc.c19
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.c6
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.h1
3 files changed, 26 insertions, 0 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 0acbe62901d9..161a74a3ac5e 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -621,6 +621,25 @@ static void omap_crtc_post_apply(struct omap_drm_apply *apply)
621 /* nothing needed for post-apply */ 621 /* nothing needed for post-apply */
622} 622}
623 623
624void omap_crtc_flush(struct drm_crtc *crtc)
625{
626 struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
627 int loops = 0;
628
629 while (!list_empty(&omap_crtc->pending_applies) ||
630 !list_empty(&omap_crtc->queued_applies) ||
631 omap_crtc->event || omap_crtc->old_fb) {
632
633 if (++loops > 10) {
634 dev_err(crtc->dev->dev,
635 "omap_crtc_flush() timeout\n");
636 break;
637 }
638
639 schedule_timeout_uninterruptible(msecs_to_jiffies(20));
640 }
641}
642
624static const char *channel_names[] = { 643static const char *channel_names[] = {
625 [OMAP_DSS_CHANNEL_LCD] = "lcd", 644 [OMAP_DSS_CHANNEL_LCD] = "lcd",
626 [OMAP_DSS_CHANNEL_DIGIT] = "tv", 645 [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)
513static int dev_unload(struct drm_device *dev) 513static int dev_unload(struct drm_device *dev)
514{ 514{
515 struct omap_drm_private *priv = dev->dev_private; 515 struct omap_drm_private *priv = dev->dev_private;
516 int i;
516 517
517 DBG("unload: dev=%p", dev); 518 DBG("unload: dev=%p", dev);
518 519
519 drm_kms_helper_poll_fini(dev); 520 drm_kms_helper_poll_fini(dev);
520 521
521 omap_fbdev_free(dev); 522 omap_fbdev_free(dev);
523
524 /* flush crtcs so the fbs get released */
525 for (i = 0; i < priv->num_crtcs; i++)
526 omap_crtc_flush(priv->crtcs[i]);
527
522 omap_modeset_free(dev); 528 omap_modeset_free(dev);
523 omap_gem_deinit(dev); 529 omap_gem_deinit(dev);
524 530
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);
163void omap_crtc_pre_uninit(void); 163void omap_crtc_pre_uninit(void);
164struct drm_crtc *omap_crtc_init(struct drm_device *dev, 164struct drm_crtc *omap_crtc_init(struct drm_device *dev,
165 struct drm_plane *plane, enum omap_channel channel, int id); 165 struct drm_plane *plane, enum omap_channel channel, int id);
166void omap_crtc_flush(struct drm_crtc *crtc);
166 167
167struct drm_plane *omap_plane_init(struct drm_device *dev, 168struct drm_plane *omap_plane_init(struct drm_device *dev,
168 int plane_id, bool private_plane); 169 int plane_id, bool private_plane);