[Intel-gfx] [PATCH] [drm/i915] Handle swap buffers in work proc instead of softirq

Eric Anholt eric at anholt.net
Sat Oct 18 00:23:30 CEST 2008


On Fri, 2008-10-17 at 00:44 -0700, Keith Packard wrote:
> Swap buffers must hold both the DRM lock and the struct_mutex to access
> both drawable clip lists and the hardware ring. struct_mutex may only be
> acquired in a non-interrupt context. This means that vblank will be entirely
> executed outside of IRQ context, which is not ideal, but should avoid
> lengthy delays while the ring is full along with making it actually work
> reliably.

OK, this looks a lot nicer.  I also like moving from planes to pipes in
vblank handling code, since it's pipes and not planes that produce
vblank events.  But I fear that there's some pipe/plane confusion going
on here.

> @@ -165,7 +170,7 @@ static void i915_vblank_do_swaps(struct drm_device *dev)
>  	list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) {
>  		drm_i915_vbl_swap_t *vbl_swap =
>  			list_entry(list, drm_i915_vbl_swap_t, head);
> -		int pipe = i915_get_pipe(dev, vbl_swap->plane);
> +		int pipe = vbl_swap->pipe;
>  
>  		if ((counter[pipe] - vbl_swap->sequence) > (1<<23))
>  			continue;

OK, so we're getting counter[pipe] = drm_vblank_count(dev, pipe)

The prototype of that one is:

u32 drm_vblank_count(struct drm_device *dev, int crtc)

so you should be in the clear there since a crtc is a pipe not a plane.

> -void
> -i915_gem_vblank_work_handler(struct work_struct *work)
> +i915_vblank_work_handler(struct work_struct *work)
>  {
>  	drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
> -						    mm.vblank_work);
> +						    vblank_work);
>  	struct drm_device *dev = dev_priv->dev;
> +	unsigned long irqflags;
>  
> -	if (dev->lock.hw_lock != NULL) {
> -		drm_locked_tasklet(dev, i915_vblank_tasklet);
> +	if (dev->lock.hw_lock == NULL) {
> +		i915_vblank_tasklet(dev);
>  		return;
> -	} else {
> -		mutex_lock(&dev->struct_mutex);
> -		i915_vblank_do_swaps(dev);
> -		mutex_unlock(&dev->struct_mutex);
>  	}
> +	
> +	spin_lock_irqsave(&dev->tasklet_lock, irqflags);
> +	dev->locked_tasklet_func = i915_vblank_tasklet;
> +	spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
> +
> +	/* Try to get the lock now, if this fails, the lock
> +	 * holder will execute the tasklet during unlock
> +	 */
> +	if (!drm_lock_take(&dev->lock, DRM_KERNEL_CONTEXT))
> +		return;
> +	
> +	dev->lock.lock_time = jiffies;
> +	atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);
> +
> +	spin_lock_irqsave(&dev->tasklet_lock, irqflags);
> +	dev->locked_tasklet_func = NULL;
> +	spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
> +
> +	i915_vblank_tasklet(dev);
> +	drm_lock_free(&dev->lock, DRM_KERNEL_CONTEXT);
>  }

I had to stare at this one for a bit -- there's a race to get
vblank_tasklet executed twice, but I think that's harmless because the
tasklet should get 0 hits in that case and not do anything.

> -	if (dev_priv->swaps_pending >= 100) {
> +	if (dev_priv->swaps_pending >= 10) {
>  		DRM_DEBUG("Too many swaps queued\n");
> +		DRM_DEBUG(" pipe 0: %d pipe 1: %d\n",
> +			  drm_vblank_count(dev, i915_get_plane(dev, 0)),
> +			  drm_vblank_count(dev, i915_get_plane(dev, 1)));

Here you've got count[pipe] = drm_vblank_count(dev, plane).

That seems wrong.

Other than that, it looks good to me.

-- 
Eric Anholt
eric at anholt.net                         eric.anholt at intel.com


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 197 bytes
Desc: This is a digitally signed message part
URL: <http://lists.freedesktop.org/archives/intel-gfx/attachments/20081017/bdb03f47/attachment.sig>


More information about the Intel-gfx mailing list