diff options
Diffstat (limited to 'bsd-core')
| -rw-r--r-- | bsd-core/drmP.h | 1 | ||||
| -rw-r--r-- | bsd-core/drm_drv.c | 1 | ||||
| -rw-r--r-- | bsd-core/drm_irq.c | 45 | ||||
| -rw-r--r-- | bsd-core/drm_lock.c | 7 | 
4 files changed, 32 insertions, 22 deletions
| diff --git a/bsd-core/drmP.h b/bsd-core/drmP.h index 88ea4e69..65d7fae4 100644 --- a/bsd-core/drmP.h +++ b/bsd-core/drmP.h @@ -739,6 +739,7 @@ struct drm_device {  	struct mtx	  dev_lock;	/* protects everything else */  #endif  	DRM_SPINTYPE	  drw_lock; +	DRM_SPINTYPE	  tsk_lock;  				/* Usage Counters */  	int		  open_count;	/* Outstanding files open	   */ diff --git a/bsd-core/drm_drv.c b/bsd-core/drm_drv.c index 740a8b57..9bd6079f 100644 --- a/bsd-core/drm_drv.c +++ b/bsd-core/drm_drv.c @@ -206,6 +206,7 @@ int drm_attach(device_t nbdev, drm_pci_id_list_t *idlist)  	mtx_init(&dev->irq_lock, "drmirq", NULL, MTX_DEF);  	mtx_init(&dev->vbl_lock, "drmvbl", NULL, MTX_DEF);  	mtx_init(&dev->drw_lock, "drmdrw", NULL, MTX_DEF); +	mtx_init(&dev->tsk_lock, "drmtsk", NULL, MTX_DEF);  #endif  	id_entry = drm_find_description(pci_get_vendor(dev->device), diff --git a/bsd-core/drm_irq.c b/bsd-core/drm_irq.c index c3ecd28b..a066cfc9 100644 --- a/bsd-core/drm_irq.c +++ b/bsd-core/drm_irq.c @@ -578,41 +578,42 @@ static void drm_locked_task(void *context, int pending __unused)  {  	struct drm_device *dev = context; -	DRM_LOCK(); -	for (;;) { -		int ret; - -		if (drm_lock_take(&dev->lock.hw_lock->lock, -		    DRM_KERNEL_CONTEXT)) -		{ -			dev->lock.file_priv = NULL; /* kernel owned */ -			dev->lock.lock_time = jiffies; -			atomic_inc(&dev->counts[_DRM_STAT_LOCKS]); -			break;  /* Got lock */ -		} +	DRM_SPINLOCK(&dev->tsk_lock); -		/* Contention */ -#if defined(__FreeBSD__) && __FreeBSD_version > 500000 -		ret = mtx_sleep((void *)&dev->lock.lock_queue, &dev->dev_lock, -		    PZERO | PCATCH, "drmlk2", 0); -#else -		ret = tsleep((void *)&dev->lock.lock_queue, PZERO | PCATCH, -		    "drmlk2", 0); -#endif -		if (ret != 0) -			return; +	DRM_LOCK(); /* XXX drm_lock_take() should do it's own locking */ +	if (dev->locked_task_call == NULL || +	    drm_lock_take(&dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT) == 0) { +		DRM_UNLOCK(); +		DRM_SPINUNLOCK(&dev->tsk_lock); +		return;  	} + +	dev->lock.file_priv = NULL; /* kernel owned */ +	dev->lock.lock_time = jiffies; +	atomic_inc(&dev->counts[_DRM_STAT_LOCKS]); +  	DRM_UNLOCK();  	dev->locked_task_call(dev);  	drm_lock_free(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT); + +	dev->locked_task_call = NULL; + +	DRM_SPINUNLOCK(&dev->tsk_lock);  }  void  drm_locked_tasklet(struct drm_device *dev,  		   void (*tasklet)(struct drm_device *dev))  { +	DRM_SPINLOCK(&dev->tsk_lock); +	if (dev->locked_task_call != NULL) { +		DRM_SPINUNLOCK(&dev->tsk_lock); +		return; +	} +  	dev->locked_task_call = tasklet; +	DRM_SPINUNLOCK(&dev->tsk_lock);  	taskqueue_enqueue(taskqueue_swi, &dev->locked_task);  } diff --git a/bsd-core/drm_lock.c b/bsd-core/drm_lock.c index 9101dec8..80ebb71d 100644 --- a/bsd-core/drm_lock.c +++ b/bsd-core/drm_lock.c @@ -180,6 +180,13 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv)  	    _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) != lock->context)  		return EINVAL; +	DRM_SPINLOCK(&dev->tsk_lock); +	if (dev->locked_task_call != NULL) { +		dev->locked_task_call(dev); +		dev->locked_task_call = NULL; +	} +	DRM_SPINUNLOCK(&dev->tsk_lock); +  	atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]);  	DRM_LOCK(); | 
