[PATCH 06/31] drm: omapdrm: Cancel pending page flips when closing device

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxxxxx>
---
 drivers/gpu/drm/omapdrm/omap_crtc.c | 21 ++++++++++++++++++++-
 drivers/gpu/drm/omapdrm/omap_drv.c  |  6 ++++++
 drivers/gpu/drm/omapdrm/omap_drv.h  |  1 +
 3 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 85129d5..a60f4e4 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 47fb99b..cf1b37e 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 f1005b4..774b9f6 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,
-- 
2.0.5

_______________________________________________
dri-devel mailing list
dri-devel@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/dri-devel





[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux