summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2015-01-18 16:57:36 +0200
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2015-06-12 22:52:45 +0300
commit1d5e5ea1f6061ec9ad4f43928697f479aeb884c6 (patch)
tree316b7d55f847846b55cc6dd6db36cf87da001d7b
parentf13ab00567273c70ffbecb59e8f11491cc108bbd (diff)
downloadlinux-1d5e5ea1f6061ec9ad4f43928697f479aeb884c6.tar.bz2
drm: omapdrm: Cancel pending page flips when closing device
Pending page flips must be cancelled when closing the device, otherwise their completion at next vblank will result in nasty effects, including possible oopses due to resources required to complete the page flip being freed. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
-rw-r--r--drivers/gpu/drm/omapdrm/omap_crtc.c21
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.c6
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.h1
3 files changed, 27 insertions, 1 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 85129d56cf4c..a60f4e49b55f 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -263,9 +263,28 @@ static const struct dss_mgr_ops mgr_ops = {
};
/* -----------------------------------------------------------------------------
- * Setup and Flush
+ * Setup, Flush and Page Flip
*/
+void omap_crtc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file)
+{
+ struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+ struct drm_device *dev = crtc->dev;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->event_lock, flags);
+
+ /* Only complete events queued for our file handle. */
+ if (omap_crtc->flip_event &&
+ file == omap_crtc->flip_event->base.file_priv) {
+ drm_send_vblank_event(dev, omap_crtc->pipe,
+ omap_crtc->flip_event);
+ omap_crtc->flip_event = NULL;
+ }
+
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+}
+
static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
{
struct omap_crtc *omap_crtc =
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index 47fb99b3a375..cf1b37e5374b 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -630,7 +630,13 @@ static void dev_lastclose(struct drm_device *dev)
static void dev_preclose(struct drm_device *dev, struct drm_file *file)
{
+ struct omap_drm_private *priv = dev->dev_private;
+ unsigned int i;
+
DBG("preclose: dev=%p", dev);
+
+ for (i = 0; i < priv->num_crtcs; ++i)
+ omap_crtc_cancel_page_flip(priv->crtcs[i], file);
}
static void dev_postclose(struct drm_device *dev, struct drm_file *file)
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index f1005b46a193..774b9f6ab2d6 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -136,6 +136,7 @@ const struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc);
enum omap_channel omap_crtc_channel(struct drm_crtc *crtc);
int omap_crtc_flush(struct drm_crtc *crtc);
int omap_crtc_queue_unpin(struct drm_crtc *crtc, struct drm_framebuffer *fb);
+void omap_crtc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file);
void omap_crtc_pre_init(void);
void omap_crtc_pre_uninit(void);
struct drm_crtc *omap_crtc_init(struct drm_device *dev,