On Sun, 26 Apr 2009 11:46:26 +0200 (CEST) "Rafael J. Wysocki" <rjw@xxxxxxx> wrote: > This message has been generated automatically as a part of a report > of regressions introduced between 2.6.28 and 2.6.29. > > The following bug entry is on the current list of known regressions > introduced between 2.6.28 and 2.6.29. Please verify if it still > should be listed and let me know (either way). > > > Bug-Entry : http://bugzilla.kernel.org/show_bug.cgi?id=12765 > Subject : i915 VT switch with AIGLX causes X lock up > Submitter : Sitsofe Wheeler <sitsofe@xxxxxxxxx> > Date : 2009-02-21 15:38 (65 days old) > First-Bad-Commit: > http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=14d200c5e5bd19219d930bbb9a5a22758c8f5bec > References : > http://marc.info/?l=linux-kernel&m=123523074304955&w=4 I think we had a workaround for this (attached), but it sounds like Robert has tracked down the root cause (search for "Broken vblanks on Intel" on dri-devel@xxxxxxxxxxxxxxxxxxxxx). Will try to get the fix into the Intel driver soon. Fortunately this doesn't seem to be biting a lot of people (at least not that I've heard); I certainly have a hard time reproducing it. -- Jesse Barnes, Intel Open Source Technology Center
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 69aa0ab..c41cba4 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -341,7 +341,7 @@ int drm_control(struct drm_device *dev, void *data, * vblank events since the system was booted, including lost events due to * modesetting activity. */ -u32 drm_vblank_count(struct drm_device *dev, int crtc) +unsigned int drm_vblank_count(struct drm_device *dev, int crtc) { return atomic_read(&dev->_vblank_count[crtc]); } @@ -522,6 +522,11 @@ out: return ret; } +#define frame_after_eq(a,b) \ + (typecheck(unsigned int, a) && \ + typecheck(unsigned int, b) && \ + ((int)(a) - (int)(b) >= 0)) + /** * Wait for VBLANK. * @@ -589,10 +594,12 @@ int drm_wait_vblank(struct drm_device *dev, void *data, DRM_DEBUG("waiting on vblank count %d, crtc %d\n", vblwait->request.sequence, crtc); dev->last_vblank_wait[crtc] = vblwait->request.sequence; + + /* Wait for the sequence number to pass or IRQs to get disabled */ DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ, - (((drm_vblank_count(dev, crtc) - - vblwait->request.sequence) <= (1 << 23)) || - !dev->irq_enabled)); + frame_after_eq(drm_vblank_count(dev, crtc), + vblwait->request.sequence) || + !dev->irq_enabled); if (ret != -EINTR) { struct timeval now;