|
@@ -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)
|