diff options
Diffstat (limited to 'drivers/gpu/drm/omapdrm')
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_crtc.c | 36 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_drv.c | 30 | ||||
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_drv.h | 2 |
3 files changed, 39 insertions, 29 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 8cbac72a1015..aa719ebfe787 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -254,30 +254,6 @@ static const struct dss_mgr_ops mgr_ops = { * 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_pending_vblank_event *event; - struct drm_device *dev = crtc->dev; - unsigned long flags; - - /* Destroy the pending vertical blanking event associated with the - * pending page flip, if any, and disable vertical blanking interrupts. - */ - - spin_lock_irqsave(&dev->event_lock, flags); - - event = omap_crtc->event; - omap_crtc->event = NULL; - - if (event && event->base.file_priv == file) { - event->base.destroy(&event->base); - drm_crtc_vblank_put(crtc); - } - - spin_unlock_irqrestore(&dev->event_lock, flags); -} - static void omap_crtc_complete_page_flip(struct drm_crtc *crtc) { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); @@ -291,7 +267,17 @@ static void omap_crtc_complete_page_flip(struct drm_crtc *crtc) omap_crtc->event = NULL; if (event) { - drm_crtc_send_vblank_event(crtc, event); + list_del(&event->base.link); + + /* + * Queue the event for delivery if it's still linked to a file + * handle, otherwise just destroy it. + */ + if (event->base.file_priv) + drm_crtc_send_vblank_event(crtc, event); + else + event->base.destroy(&event->base); + wake_up(&omap_crtc->flip_wait); drm_crtc_vblank_put(crtc); } diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 72a5a88a6419..2e7706355eb6 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -118,6 +118,7 @@ static int omap_atomic_commit(struct drm_device *dev, { struct omap_drm_private *priv = dev->dev_private; struct omap_atomic_state_commit *commit; + unsigned long flags; unsigned int i; int ret; @@ -150,6 +151,17 @@ static int omap_atomic_commit(struct drm_device *dev, priv->commit.pending |= commit->crtcs; spin_unlock(&priv->commit.lock); + /* Keep track of all CRTC events to unlink them in preclose(). */ + spin_lock_irqsave(&dev->event_lock, flags); + for (i = 0; i < dev->mode_config.num_crtc; ++i) { + struct drm_crtc_state *cstate = state->crtc_states[i]; + + if (cstate && cstate->event) + list_add_tail(&cstate->event->base.link, + &priv->commit.events); + } + spin_unlock_irqrestore(&dev->event_lock, flags); + /* Swap the state, this is the point of no return. */ drm_atomic_helper_swap_state(dev, state); @@ -632,6 +644,7 @@ static int dev_load(struct drm_device *dev, unsigned long flags) priv->wq = alloc_ordered_workqueue("omapdrm", 0); init_waitqueue_head(&priv->commit.wait); spin_lock_init(&priv->commit.lock); + INIT_LIST_HEAD(&priv->commit.events); spin_lock_init(&priv->list_lock); INIT_LIST_HEAD(&priv->obj_list); @@ -752,12 +765,23 @@ 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; + struct drm_pending_event *event; + unsigned long flags; DBG("preclose: dev=%p", dev); - for (i = 0; i < priv->num_crtcs; ++i) - omap_crtc_cancel_page_flip(priv->crtcs[i], file); + /* + * Unlink all pending CRTC events to make sure they won't be queued up + * by a pending asynchronous commit. + */ + spin_lock_irqsave(&dev->event_lock, flags); + list_for_each_entry(event, &priv->commit.events, link) { + if (event->file_priv == file) { + file->event_space += event->event->length; + event->file_priv = NULL; + } + } + spin_unlock_irqrestore(&dev->event_lock, flags); } 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 c7ef4d8977ec..81c60284bfb0 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h @@ -109,6 +109,7 @@ struct omap_drm_private { /* atomic commit */ struct { + struct list_head events; wait_queue_head_t wait; u32 pending; spinlock_t lock; /* Protects commit.pending */ @@ -142,7 +143,6 @@ void omap_fbdev_free(struct drm_device *dev); const struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc); enum omap_channel omap_crtc_channel(struct drm_crtc *crtc); -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, |