diff options
| -rw-r--r-- | linux-core/drmP.h | 5 | ||||
| -rw-r--r-- | linux-core/drm_irq.c | 22 | 
2 files changed, 15 insertions, 12 deletions
| diff --git a/linux-core/drmP.h b/linux-core/drmP.h index 69d31e14..d7b1960c 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -840,13 +840,12 @@ struct drm_device {  	atomic_t *vblank_refcount;	/* number of users of vblank interrupts per crtc */  	u32 *last_vblank;		/* protected by dev->vbl_lock, used */  					/* for wraparound handling */ -	u32 *vblank_offset;		/* used to track how many vblanks */  	int *vblank_enabled;		/* so we don't call enable more than  					   once per disable */ -	u32 *vblank_premodeset;		/*  were lost during modeset */ +	u32 *vblank_premodeset;		/* for compensation of spurious wraparounds */  	struct timer_list vblank_disable_timer; -	unsigned long max_vblank_count; /**< size of vblank counter register */ +	u32 max_vblank_count;		/**< size of vblank counter register */  	spinlock_t tasklet_lock;	/**< For drm_locked_tasklet */  	void (*locked_tasklet_func)(struct drm_device *dev); diff --git a/linux-core/drm_irq.c b/linux-core/drm_irq.c index ccb3ca89..3627a890 100644 --- a/linux-core/drm_irq.c +++ b/linux-core/drm_irq.c @@ -112,8 +112,6 @@ static void drm_vblank_cleanup(struct drm_device *dev)  		 DRM_MEM_DRIVER);  	drm_free(dev->vblank_premodeset, sizeof(*dev->vblank_premodeset) *  		 dev->num_crtcs, DRM_MEM_DRIVER); -	drm_free(dev->vblank_offset, sizeof(*dev->vblank_offset) * dev->num_crtcs, -		 DRM_MEM_DRIVER);  	dev->num_crtcs = 0;  } @@ -162,10 +160,6 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)  	if (!dev->vblank_premodeset)  		goto err; -	dev->vblank_offset = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER); -	if (!dev->vblank_offset) -		goto err; -  	/* Zero per-crtc vblank stuff */  	for (i = 0; i < num_crtcs; i++) {  		init_waitqueue_head(&dev->vbl_queue[i]); @@ -330,8 +324,7 @@ int drm_control(struct drm_device *dev, void *data,   */  u32 drm_vblank_count(struct drm_device *dev, int crtc)  { -	return atomic_read(&dev->_vblank_count[crtc]) + -		dev->vblank_offset[crtc]; +	return atomic_read(&dev->_vblank_count[crtc]);  }  EXPORT_SYMBOL(drm_vblank_count); @@ -457,7 +450,18 @@ int drm_modeset_ctl(struct drm_device *dev, void *data,  		break;  	case _DRM_POST_MODESET:  		new = dev->driver->get_vblank_counter(dev, crtc); -		dev->vblank_offset[crtc] = dev->vblank_premodeset[crtc] - new; + +		/* Compensate for spurious wraparound */ +		if (new < dev->vblank_premodeset[crtc]) { +			atomic_sub(dev->max_vblank_count + new - +				   dev->vblank_premodeset[crtc], +				   &dev->_vblank_count[crtc]); +			DRM_DEBUG("vblank_premodeset[%d]=0x%x, new=0x%x " +				 "=> _vblank_count[%d]-=0x%x\n", crtc, +				 dev->vblank_premodeset[crtc], new, +				 crtc, dev->max_vblank_count + new - +				 dev->vblank_premodeset[crtc]); +		}  		break;  	default:  		ret = -EINVAL; | 
