diff options
| author | Christopher James Halse Rogers <christopher.halse.rogers@canonical.com> | 2011-04-27 16:10:57 +1000 | 
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2011-05-04 10:11:55 +1000 | 
| commit | 498548ec69c6897fe4376b2ca90758762fa0b817 (patch) | |
| tree | 9e7fa6f5d7e58ab2acb688c7a9e4653856cf4e49 /drivers/gpu/drm/drm_irq.c | |
| parent | eaa4f5e1d0b816291a59a47917e569c0384f2b6f (diff) | |
| download | olio-linux-3.10-498548ec69c6897fe4376b2ca90758762fa0b817.tar.xz olio-linux-3.10-498548ec69c6897fe4376b2ca90758762fa0b817.zip  | |
drm: Send pending vblank events before disabling vblank.
This is the least-bad behaviour.  It means that we signal the
vblank event before it actually happens, but since we're disabling
vblanks there's no guarantee that it will *ever* happen otherwise.
This prevents GL applications which use WaitMSC from hanging
indefinitely.
Signed-off-by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_irq.c')
| -rw-r--r-- | drivers/gpu/drm/drm_irq.c | 23 | 
1 files changed, 23 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 741457bd1c4..a1f12cb043d 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -932,11 +932,34 @@ EXPORT_SYMBOL(drm_vblank_put);  void drm_vblank_off(struct drm_device *dev, int crtc)  { +	struct drm_pending_vblank_event *e, *t; +	struct timeval now;  	unsigned long irqflags; +	unsigned int seq;  	spin_lock_irqsave(&dev->vbl_lock, irqflags);  	vblank_disable_and_save(dev, crtc);  	DRM_WAKEUP(&dev->vbl_queue[crtc]); + +	/* Send any queued vblank events, lest the natives grow disquiet */ +	seq = drm_vblank_count_and_time(dev, crtc, &now); +	list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) { +		if (e->pipe != crtc) +			continue; +		DRM_DEBUG("Sending premature vblank event on disable: \ +			  wanted %d, current %d\n", +			  e->event.sequence, seq); + +		e->event.sequence = seq; +		e->event.tv_sec = now.tv_sec; +		e->event.tv_usec = now.tv_usec; +		drm_vblank_put(dev, e->pipe); +		list_move_tail(&e->base.link, &e->base.file_priv->event_list); +		wake_up_interruptible(&e->base.file_priv->event_wait); +		trace_drm_vblank_event_delivered(e->base.pid, e->pipe, +						 e->event.sequence); +	} +  	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);  }  EXPORT_SYMBOL(drm_vblank_off);  |