diff options
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/drm_auth.c | 29 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_bufs.c | 20 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_context.c | 10 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_drv.c | 33 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_fops.c | 201 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_ioctl.c | 57 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_lock.c | 42 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_proc.c | 8 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_stub.c | 105 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 81 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 10 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 30 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_mem.c | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/r300_cmdbuf.c | 11 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_cp.c | 73 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_drv.h | 14 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_state.c | 166 | 
18 files changed, 563 insertions, 332 deletions
diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c index a73462723d2..ca7a9ef5007 100644 --- a/drivers/gpu/drm/drm_auth.c +++ b/drivers/gpu/drm/drm_auth.c @@ -45,14 +45,15 @@   * the one with matching magic number, while holding the drm_device::struct_mutex   * lock.   */ -static struct drm_file *drm_find_file(struct drm_device * dev, drm_magic_t magic) +static struct drm_file *drm_find_file(struct drm_master *master, drm_magic_t magic)  {  	struct drm_file *retval = NULL;  	struct drm_magic_entry *pt;  	struct drm_hash_item *hash; +	struct drm_device *dev = master->minor->dev;  	mutex_lock(&dev->struct_mutex); -	if (!drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) { +	if (!drm_ht_find_item(&master->magiclist, (unsigned long)magic, &hash)) {  		pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item);  		retval = pt->priv;  	} @@ -71,11 +72,11 @@ static struct drm_file *drm_find_file(struct drm_device * dev, drm_magic_t magic   * associated the magic number hash key in drm_device::magiclist, while holding   * the drm_device::struct_mutex lock.   */ -static int drm_add_magic(struct drm_device * dev, struct drm_file * priv, +static int drm_add_magic(struct drm_master *master, struct drm_file *priv,  			 drm_magic_t magic)  {  	struct drm_magic_entry *entry; - +	struct drm_device *dev = master->minor->dev;  	DRM_DEBUG("%d\n", magic);  	entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC); @@ -83,11 +84,10 @@ static int drm_add_magic(struct drm_device * dev, struct drm_file * priv,  		return -ENOMEM;  	memset(entry, 0, sizeof(*entry));  	entry->priv = priv; -  	entry->hash_item.key = (unsigned long)magic;  	mutex_lock(&dev->struct_mutex); -	drm_ht_insert_item(&dev->magiclist, &entry->hash_item); -	list_add_tail(&entry->head, &dev->magicfree); +	drm_ht_insert_item(&master->magiclist, &entry->hash_item); +	list_add_tail(&entry->head, &master->magicfree);  	mutex_unlock(&dev->struct_mutex);  	return 0; @@ -102,20 +102,21 @@ static int drm_add_magic(struct drm_device * dev, struct drm_file * priv,   * Searches and unlinks the entry in drm_device::magiclist with the magic   * number hash key, while holding the drm_device::struct_mutex lock.   */ -static int drm_remove_magic(struct drm_device * dev, drm_magic_t magic) +static int drm_remove_magic(struct drm_master *master, drm_magic_t magic)  {  	struct drm_magic_entry *pt;  	struct drm_hash_item *hash; +	struct drm_device *dev = master->minor->dev;  	DRM_DEBUG("%d\n", magic);  	mutex_lock(&dev->struct_mutex); -	if (drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) { +	if (drm_ht_find_item(&master->magiclist, (unsigned long)magic, &hash)) {  		mutex_unlock(&dev->struct_mutex);  		return -EINVAL;  	}  	pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item); -	drm_ht_remove_item(&dev->magiclist, hash); +	drm_ht_remove_item(&master->magiclist, hash);  	list_del(&pt->head);  	mutex_unlock(&dev->struct_mutex); @@ -153,9 +154,9 @@ int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)  				++sequence;	/* reserve 0 */  			auth->magic = sequence++;  			spin_unlock(&lock); -		} while (drm_find_file(dev, auth->magic)); +		} while (drm_find_file(file_priv->master, auth->magic));  		file_priv->magic = auth->magic; -		drm_add_magic(dev, file_priv, auth->magic); +		drm_add_magic(file_priv->master, file_priv, auth->magic);  	}  	DRM_DEBUG("%u\n", auth->magic); @@ -181,9 +182,9 @@ int drm_authmagic(struct drm_device *dev, void *data,  	struct drm_file *file;  	DRM_DEBUG("%u\n", auth->magic); -	if ((file = drm_find_file(dev, auth->magic))) { +	if ((file = drm_find_file(file_priv->master, auth->magic))) {  		file->authenticated = 1; -		drm_remove_magic(dev, auth->magic); +		drm_remove_magic(file_priv->master, auth->magic);  		return 0;  	}  	return -EINVAL; diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index bde64b84166..dc3ce3e0a0a 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c @@ -54,9 +54,9 @@ static struct drm_map_list *drm_find_matching_map(struct drm_device *dev,  {  	struct drm_map_list *entry;  	list_for_each_entry(entry, &dev->maplist, head) { -		if (entry->map && map->type == entry->map->type && +		if (entry->map && (entry->master == dev->primary->master) && (map->type == entry->map->type) &&  		    ((entry->map->offset == map->offset) || -		     (map->type == _DRM_SHM && map->flags==_DRM_CONTAINS_LOCK))) { +		     ((map->type == _DRM_SHM) && (map->flags&_DRM_CONTAINS_LOCK)))) {  			return entry;  		}  	} @@ -210,12 +210,12 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset,  		map->offset = (unsigned long)map->handle;  		if (map->flags & _DRM_CONTAINS_LOCK) {  			/* Prevent a 2nd X Server from creating a 2nd lock */ -			if (dev->lock.hw_lock != NULL) { +			if (dev->primary->master->lock.hw_lock != NULL) {  				vfree(map->handle);  				drm_free(map, sizeof(*map), DRM_MEM_MAPS);  				return -EBUSY;  			} -			dev->sigdata.lock = dev->lock.hw_lock = map->handle;	/* Pointer to lock */ +			dev->sigdata.lock = dev->primary->master->lock.hw_lock = map->handle;	/* Pointer to lock */  		}  		break;  	case _DRM_AGP: { @@ -319,6 +319,7 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset,  	list->user_token = list->hash.key << PAGE_SHIFT;  	mutex_unlock(&dev->struct_mutex); +	list->master = dev->primary->master;  	*maplist = list;  	return 0;  	} @@ -345,7 +346,7 @@ int drm_addmap_ioctl(struct drm_device *dev, void *data,  	struct drm_map_list *maplist;  	int err; -	if (!(capable(CAP_SYS_ADMIN) || map->type == _DRM_AGP)) +	if (!(capable(CAP_SYS_ADMIN) || map->type == _DRM_AGP || map->type == _DRM_SHM))  		return -EPERM;  	err = drm_addmap_core(dev, map->offset, map->size, map->type, @@ -380,10 +381,12 @@ int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map)  	struct drm_map_list *r_list = NULL, *list_t;  	drm_dma_handle_t dmah;  	int found = 0; +	struct drm_master *master;  	/* Find the list entry for the map and remove it */  	list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) {  		if (r_list->map == map) { +			master = r_list->master;  			list_del(&r_list->head);  			drm_ht_remove_key(&dev->map_hash,  					  r_list->user_token >> PAGE_SHIFT); @@ -409,6 +412,13 @@ int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map)  		break;  	case _DRM_SHM:  		vfree(map->handle); +		if (master) { +			if (dev->sigdata.lock == master->lock.hw_lock) +				dev->sigdata.lock = NULL; +			master->lock.hw_lock = NULL;   /* SHM removed */ +			master->lock.file_priv = NULL; +			wake_up_interruptible(&master->lock.lock_queue); +		}  		break;  	case _DRM_AGP:  	case _DRM_SCATTER_GATHER: diff --git a/drivers/gpu/drm/drm_context.c b/drivers/gpu/drm/drm_context.c index d505f695421..809ec0f0345 100644 --- a/drivers/gpu/drm/drm_context.c +++ b/drivers/gpu/drm/drm_context.c @@ -256,12 +256,13 @@ static int drm_context_switch(struct drm_device * dev, int old, int new)   * hardware lock is held, clears the drm_device::context_flag and wakes up   * drm_device::context_wait.   */ -static int drm_context_switch_complete(struct drm_device * dev, int new) +static int drm_context_switch_complete(struct drm_device *dev, +				       struct drm_file *file_priv, int new)  {  	dev->last_context = new;	/* PRE/POST: This is the _only_ writer. */  	dev->last_switch = jiffies; -	if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { +	if (!_DRM_LOCK_IS_HELD(file_priv->master->lock.hw_lock->lock)) {  		DRM_ERROR("Lock isn't held after context switch\n");  	} @@ -420,7 +421,7 @@ int drm_newctx(struct drm_device *dev, void *data,  	struct drm_ctx *ctx = data;  	DRM_DEBUG("%d\n", ctx->handle); -	drm_context_switch_complete(dev, ctx->handle); +	drm_context_switch_complete(dev, file_priv, ctx->handle);  	return 0;  } @@ -442,9 +443,6 @@ int drm_rmctx(struct drm_device *dev, void *data,  	struct drm_ctx *ctx = data;  	DRM_DEBUG("%d\n", ctx->handle); -	if (ctx->handle == DRM_KERNEL_CONTEXT + 1) { -		file_priv->remove_auth_on_close = 1; -	}  	if (ctx->handle != DRM_KERNEL_CONTEXT) {  		if (dev->driver->context_dtor)  			dev->driver->context_dtor(dev, ctx->handle); diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 3cb87a932b3..9f04ca37df6 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -74,6 +74,9 @@ static struct drm_ioctl_desc drm_ioctls[] = {  	DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),  	DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH), +	DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY), +	DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY), +  	DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY),  	DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),  	DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), @@ -138,8 +141,6 @@ static struct drm_ioctl_desc drm_ioctls[] = {   */  int drm_lastclose(struct drm_device * dev)  { -	struct drm_magic_entry *pt, *next; -	struct drm_map_list *r_list, *list_t;  	struct drm_vma_entry *vma, *vma_temp;  	int i; @@ -149,12 +150,6 @@ int drm_lastclose(struct drm_device * dev)  		dev->driver->lastclose(dev);  	DRM_DEBUG("driver lastclose completed\n"); -	if (dev->unique) { -		drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER); -		dev->unique = NULL; -		dev->unique_len = 0; -	} -  	if (dev->irq_enabled)  		drm_irq_uninstall(dev); @@ -164,16 +159,6 @@ int drm_lastclose(struct drm_device * dev)  	drm_drawable_free_all(dev);  	del_timer(&dev->timer); -	/* Clear pid list */ -	if (dev->magicfree.next) { -		list_for_each_entry_safe(pt, next, &dev->magicfree, head) { -			list_del(&pt->head); -			drm_ht_remove_item(&dev->magiclist, &pt->hash_item); -			drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); -		} -		drm_ht_remove(&dev->magiclist); -	} -  	/* Clear AGP information */  	if (drm_core_has_AGP(dev) && dev->agp) {  		struct drm_agp_mem *entry, *tempe; @@ -205,13 +190,6 @@ int drm_lastclose(struct drm_device * dev)  		drm_free(vma, sizeof(*vma), DRM_MEM_VMAS);  	} -	list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) { -		if (!(r_list->map->flags & _DRM_DRIVER)) { -			drm_rmmap_locked(dev, r_list->map); -			r_list = NULL; -		} -	} -  	if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist) {  		for (i = 0; i < dev->queue_count; i++) {  			if (dev->queuelist[i]) { @@ -231,11 +209,6 @@ int drm_lastclose(struct drm_device * dev)  	if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))  		drm_dma_takedown(dev); -	if (dev->lock.hw_lock) { -		dev->sigdata.lock = dev->lock.hw_lock = NULL;	/* SHM removed */ -		dev->lock.file_priv = NULL; -		wake_up_interruptible(&dev->lock.lock_queue); -	}  	mutex_unlock(&dev->struct_mutex);  	DRM_DEBUG("lastclose completed\n"); diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 78eeed5caaf..f2285237df4 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -44,10 +44,8 @@ static int drm_open_helper(struct inode *inode, struct file *filp,  static int drm_setup(struct drm_device * dev)  { -	drm_local_map_t *map;  	int i;  	int ret; -	u32 sareapage;  	if (dev->driver->firstopen) {  		ret = dev->driver->firstopen(dev); @@ -55,14 +53,6 @@ static int drm_setup(struct drm_device * dev)  			return ret;  	} -	dev->magicfree.next = NULL; - -	/* prebuild the SAREA */ -	sareapage = max_t(unsigned, SAREA_MAX, PAGE_SIZE); -	i = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK, &map); -	if (i != 0) -		return i; -  	atomic_set(&dev->ioctl_count, 0);  	atomic_set(&dev->vma_count, 0);  	dev->buf_use = 0; @@ -77,16 +67,12 @@ static int drm_setup(struct drm_device * dev)  	for (i = 0; i < ARRAY_SIZE(dev->counts); i++)  		atomic_set(&dev->counts[i], 0); -	drm_ht_create(&dev->magiclist, DRM_MAGIC_HASH_ORDER); -	INIT_LIST_HEAD(&dev->magicfree); -  	dev->sigdata.lock = NULL; -	init_waitqueue_head(&dev->lock.lock_queue); +  	dev->queue_count = 0;  	dev->queue_reserved = 0;  	dev->queue_slots = 0;  	dev->queuelist = NULL; -	dev->irq_enabled = 0;  	dev->context_flag = 0;  	dev->interrupt_flag = 0;  	dev->dma_flag = 0; @@ -265,10 +251,42 @@ static int drm_open_helper(struct inode *inode, struct file *filp,  			goto out_free;  	} + +	/* if there is no current master make this fd it */  	mutex_lock(&dev->struct_mutex); -	if (list_empty(&dev->filelist)) -		priv->master = 1; +	if (!priv->minor->master) { +		/* create a new master */ +		priv->minor->master = drm_master_create(priv->minor); +		if (!priv->minor->master) { +			ret = -ENOMEM; +			goto out_free; +		} + +		priv->is_master = 1; +		/* take another reference for the copy in the local file priv */ +		priv->master = drm_master_get(priv->minor->master); +		priv->authenticated = 1; + +		mutex_unlock(&dev->struct_mutex); +		if (dev->driver->master_create) { +			ret = dev->driver->master_create(dev, priv->master); +			if (ret) { +				mutex_lock(&dev->struct_mutex); +				/* drop both references if this fails */ +				drm_master_put(&priv->minor->master); +				drm_master_put(&priv->master); +				mutex_unlock(&dev->struct_mutex); +				goto out_free; +			} +		} +	} else { +		/* get a reference to the master */ +		priv->master = drm_master_get(priv->minor->master); +		mutex_unlock(&dev->struct_mutex); +	} + +	mutex_lock(&dev->struct_mutex);  	list_add(&priv->lhead, &dev->filelist);  	mutex_unlock(&dev->struct_mutex); @@ -314,6 +332,74 @@ int drm_fasync(int fd, struct file *filp, int on)  }  EXPORT_SYMBOL(drm_fasync); +/* + * Reclaim locked buffers; note that this may be a bad idea if the current + * context doesn't have the hw lock... + */ +static void drm_reclaim_locked_buffers(struct drm_device *dev, struct file *f) +{ +	struct drm_file *file_priv = f->private_data; + +	if (drm_i_have_hw_lock(dev, file_priv)) { +		dev->driver->reclaim_buffers_locked(dev, file_priv); +	} else { +		unsigned long _end = jiffies + 3 * DRM_HZ; +		int locked = 0; + +		drm_idlelock_take(&file_priv->master->lock); + +		/* +		 * Wait for a while. +		 */ +		do { +			spin_lock_bh(&file_priv->master->lock.spinlock); +			locked = file_priv->master->lock.idle_has_lock; +			spin_unlock_bh(&file_priv->master->lock.spinlock); +			if (locked) +				break; +			schedule(); +		} while (!time_after_eq(jiffies, _end)); + +		if (!locked) { +			DRM_ERROR("reclaim_buffers_locked() deadlock. Please rework this\n" +				  "\tdriver to use reclaim_buffers_idlelocked() instead.\n" +				  "\tI will go on reclaiming the buffers anyway.\n"); +		} + +		dev->driver->reclaim_buffers_locked(dev, file_priv); +		drm_idlelock_release(&file_priv->master->lock); +	} +} + +static void drm_master_release(struct drm_device *dev, struct file *filp) +{ +	struct drm_file *file_priv = filp->private_data; + +	if (dev->driver->reclaim_buffers_locked && +	    file_priv->master->lock.hw_lock) +		drm_reclaim_locked_buffers(dev, filp); + +	if (dev->driver->reclaim_buffers_idlelocked && +	    file_priv->master->lock.hw_lock) { +		drm_idlelock_take(&file_priv->master->lock); +		dev->driver->reclaim_buffers_idlelocked(dev, file_priv); +		drm_idlelock_release(&file_priv->master->lock); +	} + + +	if (drm_i_have_hw_lock(dev, file_priv)) { +		DRM_DEBUG("File %p released, freeing lock for context %d\n", +			  filp, _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock)); +		drm_lock_free(&file_priv->master->lock, +			      _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock)); +	} + +	if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && +	    !dev->driver->reclaim_buffers_locked) { +		dev->driver->reclaim_buffers(dev, file_priv); +	} +} +  /**   * Release file.   * @@ -348,60 +434,9 @@ int drm_release(struct inode *inode, struct file *filp)  		  (long)old_encode_dev(file_priv->minor->device),  		  dev->open_count); -	if (dev->driver->reclaim_buffers_locked && dev->lock.hw_lock) { -		if (drm_i_have_hw_lock(dev, file_priv)) { -			dev->driver->reclaim_buffers_locked(dev, file_priv); -		} else { -			unsigned long endtime = jiffies + 3 * DRM_HZ; -			int locked = 0; - -			drm_idlelock_take(&dev->lock); - -			/* -			 * Wait for a while. -			 */ - -			do{ -				spin_lock_bh(&dev->lock.spinlock); -				locked = dev->lock.idle_has_lock; -				spin_unlock_bh(&dev->lock.spinlock); -				if (locked) -					break; -				schedule(); -			} while (!time_after_eq(jiffies, endtime)); - -			if (!locked) { -				DRM_ERROR("reclaim_buffers_locked() deadlock. Please rework this\n" -					  "\tdriver to use reclaim_buffers_idlelocked() instead.\n" -					  "\tI will go on reclaiming the buffers anyway.\n"); -			} - -			dev->driver->reclaim_buffers_locked(dev, file_priv); -			drm_idlelock_release(&dev->lock); -		} -	} - -	if (dev->driver->reclaim_buffers_idlelocked && dev->lock.hw_lock) { - -		drm_idlelock_take(&dev->lock); -		dev->driver->reclaim_buffers_idlelocked(dev, file_priv); -		drm_idlelock_release(&dev->lock); - -	} - -	if (drm_i_have_hw_lock(dev, file_priv)) { -		DRM_DEBUG("File %p released, freeing lock for context %d\n", -			  filp, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); - -		drm_lock_free(&dev->lock, -			      _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); -	} - - -	if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && -	    !dev->driver->reclaim_buffers_locked) { -		dev->driver->reclaim_buffers(dev, file_priv); -	} +	/* if the master has gone away we can't do anything with the lock */ +	if (file_priv->minor->master) +		drm_master_release(dev, filp);  	if (dev->driver->driver_features & DRIVER_GEM)  		drm_gem_release(dev, file_priv); @@ -428,12 +463,24 @@ int drm_release(struct inode *inode, struct file *filp)  	mutex_unlock(&dev->ctxlist_mutex);  	mutex_lock(&dev->struct_mutex); -	if (file_priv->remove_auth_on_close == 1) { + +	if (file_priv->is_master) {  		struct drm_file *temp; +		list_for_each_entry(temp, &dev->filelist, lhead) { +			if ((temp->master == file_priv->master) && +			    (temp != file_priv)) +				temp->authenticated = 0; +		} -		list_for_each_entry(temp, &dev->filelist, lhead) -			temp->authenticated = 0; +		if (file_priv->minor->master == file_priv->master) { +			/* drop the reference held my the minor */ +			drm_master_put(&file_priv->minor->master); +		}  	} + +	/* drop the reference held my the file priv */ +	drm_master_put(&file_priv->master); +	file_priv->is_master = 0;  	list_del(&file_priv->lhead);  	mutex_unlock(&dev->struct_mutex); @@ -448,9 +495,9 @@ int drm_release(struct inode *inode, struct file *filp)  	atomic_inc(&dev->counts[_DRM_STAT_CLOSES]);  	spin_lock(&dev->count_lock);  	if (!--dev->open_count) { -		if (atomic_read(&dev->ioctl_count) || dev->blocked) { -			DRM_ERROR("Device busy: %d %d\n", -				  atomic_read(&dev->ioctl_count), dev->blocked); +		if (atomic_read(&dev->ioctl_count)) { +			DRM_ERROR("Device busy: %d\n", +				  atomic_read(&dev->ioctl_count));  			spin_unlock(&dev->count_lock);  			unlock_kernel();  			return -EBUSY; diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 16829fb3089..e35126a3509 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -53,12 +53,13 @@ int drm_getunique(struct drm_device *dev, void *data,  		  struct drm_file *file_priv)  {  	struct drm_unique *u = data; +	struct drm_master *master = file_priv->master; -	if (u->unique_len >= dev->unique_len) { -		if (copy_to_user(u->unique, dev->unique, dev->unique_len)) +	if (u->unique_len >= master->unique_len) { +		if (copy_to_user(u->unique, master->unique, master->unique_len))  			return -EFAULT;  	} -	u->unique_len = dev->unique_len; +	u->unique_len = master->unique_len;  	return 0;  } @@ -81,36 +82,37 @@ int drm_setunique(struct drm_device *dev, void *data,  		  struct drm_file *file_priv)  {  	struct drm_unique *u = data; +	struct drm_master *master = file_priv->master;  	int domain, bus, slot, func, ret; -	if (dev->unique_len || dev->unique) +	if (master->unique_len || master->unique)  		return -EBUSY;  	if (!u->unique_len || u->unique_len > 1024)  		return -EINVAL; -	dev->unique_len = u->unique_len; -	dev->unique = drm_alloc(u->unique_len + 1, DRM_MEM_DRIVER); -	if (!dev->unique) +	master->unique_len = u->unique_len; +	master->unique = drm_alloc(u->unique_len + 1, DRM_MEM_DRIVER); +	if (!master->unique)  		return -ENOMEM; -	if (copy_from_user(dev->unique, u->unique, dev->unique_len)) +	if (copy_from_user(master->unique, u->unique, master->unique_len))  		return -EFAULT; -	dev->unique[dev->unique_len] = '\0'; +	master->unique[master->unique_len] = '\0';  	dev->devname =  	    drm_alloc(strlen(dev->driver->pci_driver.name) + -		      strlen(dev->unique) + 2, DRM_MEM_DRIVER); +		      strlen(master->unique) + 2, DRM_MEM_DRIVER);  	if (!dev->devname)  		return -ENOMEM;  	sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, -		dev->unique); +		master->unique);  	/* Return error if the busid submitted doesn't match the device's actual  	 * busid.  	 */ -	ret = sscanf(dev->unique, "PCI:%d:%d:%d", &bus, &slot, &func); +	ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func);  	if (ret != 3)  		return -EINVAL;  	domain = bus >> 8; @@ -125,34 +127,35 @@ int drm_setunique(struct drm_device *dev, void *data,  	return 0;  } -static int drm_set_busid(struct drm_device * dev) +static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv)  { +	struct drm_master *master = file_priv->master;  	int len; -	if (dev->unique != NULL) -		return 0; +	if (master->unique != NULL) +		return -EBUSY; -	dev->unique_len = 40; -	dev->unique = drm_alloc(dev->unique_len + 1, DRM_MEM_DRIVER); -	if (dev->unique == NULL) +	master->unique_len = 40; +	master->unique = drm_alloc(master->unique_len + 1, DRM_MEM_DRIVER); +	if (master->unique == NULL)  		return -ENOMEM; -	len = snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d", -		       drm_get_pci_domain(dev), dev->pdev->bus->number, +	len = snprintf(master->unique, master->unique_len, "pci:%04x:%02x:%02x.%d", +		       drm_get_pci_domain(dev), +		       dev->pdev->bus->number,  		       PCI_SLOT(dev->pdev->devfn),  		       PCI_FUNC(dev->pdev->devfn)); - -	if (len > dev->unique_len) -		DRM_ERROR("Unique buffer overflowed\n"); +	if (len > master->unique_len) +		DRM_ERROR("buffer overflow");  	dev->devname = -	    drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len + +	    drm_alloc(strlen(dev->driver->pci_driver.name) + master->unique_len +  		      2, DRM_MEM_DRIVER);  	if (dev->devname == NULL)  		return -ENOMEM;  	sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, -		dev->unique); +		master->unique);  	return 0;  } @@ -276,7 +279,7 @@ int drm_getstats(struct drm_device *dev, void *data,  	for (i = 0; i < dev->counters; i++) {  		if (dev->types[i] == _DRM_STAT_LOCK)  			stats->data[i].value = -			    (dev->lock.hw_lock ? dev->lock.hw_lock->lock : 0); +			    (file_priv->master->lock.hw_lock ? file_priv->master->lock.hw_lock->lock : 0);  		else  			stats->data[i].value = atomic_read(&dev->counts[i]);  		stats->data[i].type = dev->types[i]; @@ -318,7 +321,7 @@ int drm_setversion(struct drm_device *dev, void *data, struct drm_file *file_pri  			/*  			 * Version 1.1 includes tying of DRM to specific device  			 */ -			drm_set_busid(dev); +			drm_set_busid(dev, file_priv);  		}  	} diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c index 1cfa72031f8..46e7b28f070 100644 --- a/drivers/gpu/drm/drm_lock.c +++ b/drivers/gpu/drm/drm_lock.c @@ -52,6 +52,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)  {  	DECLARE_WAITQUEUE(entry, current);  	struct drm_lock *lock = data; +	struct drm_master *master = file_priv->master;  	int ret = 0;  	++file_priv->lock_count; @@ -64,26 +65,27 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)  	DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",  		  lock->context, task_pid_nr(current), -		  dev->lock.hw_lock->lock, lock->flags); +		  master->lock.hw_lock->lock, lock->flags);  	if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE))  		if (lock->context < 0)  			return -EINVAL; -	add_wait_queue(&dev->lock.lock_queue, &entry); -	spin_lock_bh(&dev->lock.spinlock); -	dev->lock.user_waiters++; -	spin_unlock_bh(&dev->lock.spinlock); +	add_wait_queue(&master->lock.lock_queue, &entry); +	spin_lock_bh(&master->lock.spinlock); +	master->lock.user_waiters++; +	spin_unlock_bh(&master->lock.spinlock); +  	for (;;) {  		__set_current_state(TASK_INTERRUPTIBLE); -		if (!dev->lock.hw_lock) { +		if (!master->lock.hw_lock) {  			/* Device has been unregistered */  			ret = -EINTR;  			break;  		} -		if (drm_lock_take(&dev->lock, lock->context)) { -			dev->lock.file_priv = file_priv; -			dev->lock.lock_time = jiffies; +		if (drm_lock_take(&master->lock, lock->context)) { +			master->lock.file_priv = file_priv; +			master->lock.lock_time = jiffies;  			atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);  			break;	/* Got lock */  		} @@ -95,11 +97,11 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)  			break;  		}  	} -	spin_lock_bh(&dev->lock.spinlock); -	dev->lock.user_waiters--; -	spin_unlock_bh(&dev->lock.spinlock); +	spin_lock_bh(&master->lock.spinlock); +	master->lock.user_waiters--; +	spin_unlock_bh(&master->lock.spinlock);  	__set_current_state(TASK_RUNNING); -	remove_wait_queue(&dev->lock.lock_queue, &entry); +	remove_wait_queue(&master->lock.lock_queue, &entry);  	DRM_DEBUG("%d %s\n", lock->context,  		  ret ? "interrupted" : "has lock"); @@ -108,14 +110,14 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)  	/* don't set the block all signals on the master process for now   	 * really probably not the correct answer but lets us debug xkb   	 * xserver for now */ -	if (!file_priv->master) { +	if (!file_priv->is_master) {  		sigemptyset(&dev->sigmask);  		sigaddset(&dev->sigmask, SIGSTOP);  		sigaddset(&dev->sigmask, SIGTSTP);  		sigaddset(&dev->sigmask, SIGTTIN);  		sigaddset(&dev->sigmask, SIGTTOU);  		dev->sigdata.context = lock->context; -		dev->sigdata.lock = dev->lock.hw_lock; +		dev->sigdata.lock = master->lock.hw_lock;  		block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);  	} @@ -154,6 +156,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)  int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv)  {  	struct drm_lock *lock = data; +	struct drm_master *master = file_priv->master;  	if (lock->context == DRM_KERNEL_CONTEXT) {  		DRM_ERROR("Process %d using kernel context %d\n", @@ -169,7 +172,7 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv)  	if (dev->driver->kernel_context_switch_unlock)  		dev->driver->kernel_context_switch_unlock(dev);  	else { -		if (drm_lock_free(&dev->lock,lock->context)) { +		if (drm_lock_free(&master->lock, lock->context)) {  			/* FIXME: Should really bail out here. */  		}  	} @@ -379,9 +382,10 @@ EXPORT_SYMBOL(drm_idlelock_release);  int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv)  { -	return (file_priv->lock_count && dev->lock.hw_lock && -		_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) && -		dev->lock.file_priv == file_priv); +	struct drm_master *master = file_priv->master; +	return (file_priv->lock_count && master->lock.hw_lock && +		_DRM_LOCK_IS_HELD(master->lock.hw_lock->lock) && +		master->lock.file_priv == file_priv);  }  EXPORT_SYMBOL(drm_i_have_hw_lock); diff --git a/drivers/gpu/drm/drm_proc.c b/drivers/gpu/drm/drm_proc.c index ae73b7f7249..7dbaa1a19ea 100644 --- a/drivers/gpu/drm/drm_proc.c +++ b/drivers/gpu/drm/drm_proc.c @@ -195,6 +195,7 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request,  			 int *eof, void *data)  {  	struct drm_minor *minor = (struct drm_minor *) data; +	struct drm_master *master = minor->master;  	struct drm_device *dev = minor->dev;  	int len = 0; @@ -203,13 +204,16 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request,  		return 0;  	} +	if (!master) +		return 0; +  	*start = &buf[offset];  	*eof = 0; -	if (dev->unique) { +	if (master->unique) {  		DRM_PROC_PRINT("%s %s %s\n",  			       dev->driver->pci_driver.name, -			       pci_name(dev->pdev), dev->unique); +			       pci_name(dev->pdev), master->unique);  	} else {  		DRM_PROC_PRINT("%s %s\n", dev->driver->pci_driver.name,  			       pci_name(dev->pdev)); diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 849c0a9fe7f..0f24c2dcd51 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -79,6 +79,104 @@ again:  	return new_id;  } +struct drm_master *drm_master_create(struct drm_minor *minor) +{ +	struct drm_master *master; + +	master = drm_calloc(1, sizeof(*master), DRM_MEM_DRIVER); +	if (!master) +		return NULL; + +	kref_init(&master->refcount); +	spin_lock_init(&master->lock.spinlock); +	init_waitqueue_head(&master->lock.lock_queue); +	drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER); +	INIT_LIST_HEAD(&master->magicfree); +	master->minor = minor; + +	list_add_tail(&master->head, &minor->master_list); + +	return master; +} + +struct drm_master *drm_master_get(struct drm_master *master) +{ +	kref_get(&master->refcount); +	return master; +} + +static void drm_master_destroy(struct kref *kref) +{ +	struct drm_master *master = container_of(kref, struct drm_master, refcount); +	struct drm_magic_entry *pt, *next; +	struct drm_device *dev = master->minor->dev; + +	list_del(&master->head); + +	if (dev->driver->master_destroy) +		dev->driver->master_destroy(dev, master); + +	if (master->unique) { +		drm_free(master->unique, strlen(master->unique) + 1, DRM_MEM_DRIVER); +		master->unique = NULL; +		master->unique_len = 0; +	} + +	list_for_each_entry_safe(pt, next, &master->magicfree, head) { +		list_del(&pt->head); +		drm_ht_remove_item(&master->magiclist, &pt->hash_item); +		drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); +	} + +	drm_ht_remove(&master->magiclist); + +	if (master->lock.hw_lock) { +		if (dev->sigdata.lock == master->lock.hw_lock) +			dev->sigdata.lock = NULL; +		master->lock.hw_lock = NULL; +		master->lock.file_priv = NULL; +		wake_up_interruptible(&master->lock.lock_queue); +	} + +	drm_free(master, sizeof(*master), DRM_MEM_DRIVER); +} + +void drm_master_put(struct drm_master **master) +{ +	kref_put(&(*master)->refcount, drm_master_destroy); +	*master = NULL; +} + +int drm_setmaster_ioctl(struct drm_device *dev, void *data, +			struct drm_file *file_priv) +{ +	if (file_priv->minor->master && file_priv->minor->master != file_priv->master) +		return -EINVAL; + +	if (!file_priv->master) +		return -EINVAL; + +	if (!file_priv->minor->master && +	    file_priv->minor->master != file_priv->master) { +		mutex_lock(&dev->struct_mutex); +		file_priv->minor->master = drm_master_get(file_priv->master); +		mutex_lock(&dev->struct_mutex); +	} + +	return 0; +} + +int drm_dropmaster_ioctl(struct drm_device *dev, void *data, +			 struct drm_file *file_priv) +{ +	if (!file_priv->master) +		return -EINVAL; +	mutex_lock(&dev->struct_mutex); +	drm_master_put(&file_priv->minor->master); +	mutex_unlock(&dev->struct_mutex); +	return 0; +} +  static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,  			   const struct pci_device_id *ent,  			   struct drm_driver *driver) @@ -92,7 +190,6 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,  	spin_lock_init(&dev->count_lock);  	spin_lock_init(&dev->drw_lock); -	spin_lock_init(&dev->lock.spinlock);  	init_timer(&dev->timer);  	mutex_init(&dev->struct_mutex);  	mutex_init(&dev->ctxlist_mutex); @@ -200,6 +297,7 @@ static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int t  	new_minor->device = MKDEV(DRM_MAJOR, minor_id);  	new_minor->dev = dev;  	new_minor->index = minor_id; +	INIT_LIST_HEAD(&new_minor->master_list);  	idr_replace(&drm_minors_idr, new_minor, minor_id); @@ -299,11 +397,6 @@ int drm_put_dev(struct drm_device * dev)  {  	DRM_DEBUG("release primary %s\n", dev->driver->pci_driver.name); -	if (dev->unique) { -		drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER); -		dev->unique = NULL; -		dev->unique_len = 0; -	}  	if (dev->devname) {  		drm_free(dev->devname, strlen(dev->devname) + 1,  			 DRM_MEM_DRIVER); diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index afa8a12cd00..dacdf3c577c 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -39,6 +39,7 @@  int i915_wait_ring(struct drm_device * dev, int n, const char *caller)  {  	drm_i915_private_t *dev_priv = dev->dev_private; +	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;  	drm_i915_ring_buffer_t *ring = &(dev_priv->ring);  	u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD;  	u32 last_acthd = I915_READ(acthd_reg); @@ -55,8 +56,8 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller)  		if (ring->space >= n)  			return 0; -		if (dev_priv->sarea_priv) -			dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; +		if (master_priv->sarea_priv) +			master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;  		if (ring->head != last_head)  			i = 0; @@ -121,6 +122,7 @@ static void i915_free_hws(struct drm_device *dev)  void i915_kernel_lost_context(struct drm_device * dev)  {  	drm_i915_private_t *dev_priv = dev->dev_private; +	struct drm_i915_master_private *master_priv;  	drm_i915_ring_buffer_t *ring = &(dev_priv->ring);  	ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR; @@ -129,8 +131,12 @@ void i915_kernel_lost_context(struct drm_device * dev)  	if (ring->space < 0)  		ring->space += ring->Size; -	if (ring->head == ring->tail && dev_priv->sarea_priv) -		dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY; +	if (!dev->primary->master) +		return; + +	master_priv = dev->primary->master->driver_priv; +	if (ring->head == ring->tail && master_priv->sarea_priv) +		master_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;  }  static int i915_dma_cleanup(struct drm_device * dev) @@ -154,25 +160,13 @@ static int i915_dma_cleanup(struct drm_device * dev)  	if (I915_NEED_GFX_HWS(dev))  		i915_free_hws(dev); -	dev_priv->sarea = NULL; -	dev_priv->sarea_priv = NULL; -  	return 0;  }  static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)  {  	drm_i915_private_t *dev_priv = dev->dev_private; - -	dev_priv->sarea = drm_getsarea(dev); -	if (!dev_priv->sarea) { -		DRM_ERROR("can not find sarea!\n"); -		i915_dma_cleanup(dev); -		return -EINVAL; -	} - -	dev_priv->sarea_priv = (drm_i915_sarea_t *) -	    ((u8 *) dev_priv->sarea->handle + init->sarea_priv_offset); +	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;  	if (init->ring_size != 0) {  		if (dev_priv->ring.ring_obj != NULL) { @@ -207,7 +201,8 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)  	dev_priv->back_offset = init->back_offset;  	dev_priv->front_offset = init->front_offset;  	dev_priv->current_page = 0; -	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page; +	if (master_priv->sarea_priv) +		master_priv->sarea_priv->pf_current_page = 0;  	/* Allow hardware batchbuffers unless told otherwise.  	 */ @@ -222,11 +217,6 @@ static int i915_dma_resume(struct drm_device * dev)  	DRM_DEBUG("%s\n", __func__); -	if (!dev_priv->sarea) { -		DRM_ERROR("can not find sarea!\n"); -		return -EINVAL; -	} -  	if (dev_priv->ring.map.handle == NULL) {  		DRM_ERROR("can not ioremap virtual address for"  			  " ring buffer\n"); @@ -435,13 +425,14 @@ i915_emit_box(struct drm_device *dev,  static void i915_emit_breadcrumb(struct drm_device *dev)  {  	drm_i915_private_t *dev_priv = dev->dev_private; +	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;  	RING_LOCALS;  	dev_priv->counter++;  	if (dev_priv->counter > 0x7FFFFFFFUL)  		dev_priv->counter = 0; -	if (dev_priv->sarea_priv) -		dev_priv->sarea_priv->last_enqueue = dev_priv->counter; +	if (master_priv->sarea_priv) +		master_priv->sarea_priv->last_enqueue = dev_priv->counter;  	BEGIN_LP_RING(4);  	OUT_RING(MI_STORE_DWORD_INDEX); @@ -537,15 +528,17 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev,  static int i915_dispatch_flip(struct drm_device * dev)  {  	drm_i915_private_t *dev_priv = dev->dev_private; +	struct drm_i915_master_private *master_priv = +		dev->primary->master->driver_priv;  	RING_LOCALS; -	if (!dev_priv->sarea_priv) +	if (!master_priv->sarea_priv)  		return -EINVAL;  	DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",  		  __func__,  		  dev_priv->current_page, -		  dev_priv->sarea_priv->pf_current_page); +		  master_priv->sarea_priv->pf_current_page);  	i915_kernel_lost_context(dev); @@ -572,7 +565,7 @@ static int i915_dispatch_flip(struct drm_device * dev)  	OUT_RING(0);  	ADVANCE_LP_RING(); -	dev_priv->sarea_priv->last_enqueue = dev_priv->counter++; +	master_priv->sarea_priv->last_enqueue = dev_priv->counter++;  	BEGIN_LP_RING(4);  	OUT_RING(MI_STORE_DWORD_INDEX); @@ -581,7 +574,7 @@ static int i915_dispatch_flip(struct drm_device * dev)  	OUT_RING(0);  	ADVANCE_LP_RING(); -	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page; +	master_priv->sarea_priv->pf_current_page = dev_priv->current_page;  	return 0;  } @@ -611,8 +604,9 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,  			    struct drm_file *file_priv)  {  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; +	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;  	drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) -	    dev_priv->sarea_priv; +	    master_priv->sarea_priv;  	drm_i915_batchbuffer_t *batch = data;  	int ret; @@ -644,8 +638,9 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,  			  struct drm_file *file_priv)  {  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; +	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;  	drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) -	    dev_priv->sarea_priv; +	    master_priv->sarea_priv;  	drm_i915_cmdbuffer_t *cmdbuf = data;  	int ret; @@ -802,6 +797,30 @@ static int i915_set_status_page(struct drm_device *dev, void *data,  	return 0;  } +int i915_master_create(struct drm_device *dev, struct drm_master *master) +{ +	struct drm_i915_master_private *master_priv; + +	master_priv = drm_calloc(1, sizeof(*master_priv), DRM_MEM_DRIVER); +	if (!master_priv) +		return -ENOMEM; + +	master->driver_priv = master_priv; +	return 0; +} + +void i915_master_destroy(struct drm_device *dev, struct drm_master *master) +{ +	struct drm_i915_master_private *master_priv = master->driver_priv; + +	if (!master_priv) +		return; + +	drm_free(master_priv, sizeof(*master_priv), DRM_MEM_DRIVER); + +	master->driver_priv = NULL; +} +  int i915_driver_load(struct drm_device *dev, unsigned long flags)  {  	struct drm_i915_private *dev_priv = dev->dev_private; diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index a80ead21528..c91648320a8 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -107,6 +107,8 @@ static struct drm_driver driver = {  	.reclaim_buffers = drm_core_reclaim_buffers,  	.get_map_ofs = drm_core_get_map_ofs,  	.get_reg_ofs = drm_core_get_reg_ofs, +	.master_create = i915_master_create, +	.master_destroy = i915_master_destroy,  	.proc_init = i915_gem_proc_init,  	.proc_cleanup = i915_gem_proc_cleanup,  	.gem_init_object = i915_gem_init_object, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b3cc4731aa7..ba096f9a764 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -103,15 +103,18 @@ struct intel_opregion {  	int enabled;  }; +struct drm_i915_master_private { +	drm_local_map_t *sarea; +	struct _drm_i915_sarea *sarea_priv; +}; +  typedef struct drm_i915_private {  	struct drm_device *dev;  	int has_gem;  	void __iomem *regs; -	drm_local_map_t *sarea; -	drm_i915_sarea_t *sarea_priv;  	drm_i915_ring_buffer_t ring;  	drm_dma_handle_t *status_page_dmah; @@ -417,6 +420,9 @@ struct drm_i915_file_private {  extern struct drm_ioctl_desc i915_ioctls[];  extern int i915_max_ioctl; +extern int i915_master_create(struct drm_device *dev, struct drm_master *master); +extern void i915_master_destroy(struct drm_device *dev, struct drm_master *master); +  				/* i915_dma.c */  extern void i915_kernel_lost_context(struct drm_device * dev);  extern int i915_driver_load(struct drm_device *, unsigned long flags); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 69b9a42da95..9b673d2f912 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -168,6 +168,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)  {  	struct drm_device *dev = (struct drm_device *) arg;  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; +	struct drm_i915_master_private *master_priv;  	u32 iir, new_iir;  	u32 pipea_stats, pipeb_stats;  	u32 vblank_status; @@ -222,9 +223,12 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)  		I915_WRITE(IIR, iir);  		new_iir = I915_READ(IIR); /* Flush posted writes */ -		if (dev_priv->sarea_priv) -			dev_priv->sarea_priv->last_dispatch = -				READ_BREADCRUMB(dev_priv); +		if (dev->primary->master) { +			master_priv = dev->primary->master->driver_priv; +			if (master_priv->sarea_priv) +				master_priv->sarea_priv->last_dispatch = +					READ_BREADCRUMB(dev_priv); +		}  		if (iir & I915_USER_INTERRUPT) {  			dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev); @@ -269,6 +273,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)  static int i915_emit_irq(struct drm_device * dev)  {  	drm_i915_private_t *dev_priv = dev->dev_private; +	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;  	RING_LOCALS;  	i915_kernel_lost_context(dev); @@ -278,8 +283,8 @@ static int i915_emit_irq(struct drm_device * dev)  	dev_priv->counter++;  	if (dev_priv->counter > 0x7FFFFFFFUL)  		dev_priv->counter = 1; -	if (dev_priv->sarea_priv) -		dev_priv->sarea_priv->last_enqueue = dev_priv->counter; +	if (master_priv->sarea_priv) +		master_priv->sarea_priv->last_enqueue = dev_priv->counter;  	BEGIN_LP_RING(4);  	OUT_RING(MI_STORE_DWORD_INDEX); @@ -317,21 +322,20 @@ void i915_user_irq_put(struct drm_device *dev)  static int i915_wait_irq(struct drm_device * dev, int irq_nr)  {  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; +	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;  	int ret = 0;  	DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr,  		  READ_BREADCRUMB(dev_priv));  	if (READ_BREADCRUMB(dev_priv) >= irq_nr) { -		if (dev_priv->sarea_priv) { -			dev_priv->sarea_priv->last_dispatch = -				READ_BREADCRUMB(dev_priv); -		} +		if (master_priv->sarea_priv) +			master_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);  		return 0;  	} -	if (dev_priv->sarea_priv) -		dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; +	if (master_priv->sarea_priv) +		master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;  	i915_user_irq_get(dev);  	DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ, @@ -343,10 +347,6 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)  			  READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);  	} -	if (dev_priv->sarea_priv) -		dev_priv->sarea_priv->last_dispatch = -			READ_BREADCRUMB(dev_priv); -  	return ret;  } diff --git a/drivers/gpu/drm/i915/i915_mem.c b/drivers/gpu/drm/i915/i915_mem.c index 6126a60dc9c..96e271986d2 100644 --- a/drivers/gpu/drm/i915/i915_mem.c +++ b/drivers/gpu/drm/i915/i915_mem.c @@ -46,7 +46,8 @@  static void mark_block(struct drm_device * dev, struct mem_block *p, int in_use)  {  	drm_i915_private_t *dev_priv = dev->dev_private; -	drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv; +	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; +	drm_i915_sarea_t *sarea_priv = master_priv->sarea_priv;  	struct drm_tex_region *list;  	unsigned shift, nr;  	unsigned start; diff --git a/drivers/gpu/drm/radeon/r300_cmdbuf.c b/drivers/gpu/drm/radeon/r300_cmdbuf.c index 4b27d9abb7b..cace3964fee 100644 --- a/drivers/gpu/drm/radeon/r300_cmdbuf.c +++ b/drivers/gpu/drm/radeon/r300_cmdbuf.c @@ -860,12 +860,12 @@ static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)   * The actual age emit is done by r300_do_cp_cmdbuf, which is why you must   * be careful about how this function is called.   */ -static void r300_discard_buffer(struct drm_device * dev, struct drm_buf * buf) +static void r300_discard_buffer(struct drm_device *dev, struct drm_master *master, struct drm_buf *buf)  { -	drm_radeon_private_t *dev_priv = dev->dev_private;  	drm_radeon_buf_priv_t *buf_priv = buf->dev_private; +	struct drm_radeon_master_private *master_priv = master->driver_priv; -	buf_priv->age = ++dev_priv->sarea_priv->last_dispatch; +	buf_priv->age = ++master_priv->sarea_priv->last_dispatch;  	buf->pending = 1;  	buf->used = 0;  } @@ -1027,6 +1027,7 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,  		      drm_radeon_kcmd_buffer_t *cmdbuf)  {  	drm_radeon_private_t *dev_priv = dev->dev_private; +	struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;  	struct drm_device_dma *dma = dev->dma;  	struct drm_buf *buf = NULL;  	int emit_dispatch_age = 0; @@ -1134,7 +1135,7 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,  			}  			emit_dispatch_age = 1; -			r300_discard_buffer(dev, buf); +			r300_discard_buffer(dev, file_priv->master, buf);  			break;  		case R300_CMD_WAIT: @@ -1189,7 +1190,7 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,  		/* Emit the vertex buffer age */  		BEGIN_RING(2); -		RADEON_DISPATCH_AGE(dev_priv->sarea_priv->last_dispatch); +		RADEON_DISPATCH_AGE(master_priv->sarea_priv->last_dispatch);  		ADVANCE_RING();  	} diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index dcebb4bee7a..7b37a490637 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c @@ -31,6 +31,7 @@  #include "drmP.h"  #include "drm.h" +#include "drm_sarea.h"  #include "radeon_drm.h"  #include "radeon_drv.h"  #include "r300_reg.h" @@ -667,15 +668,14 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,  		RADEON_WRITE(RADEON_BUS_CNTL, tmp);  	} /* PCIE cards appears to not need this */ -	dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0; -	RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame); +	dev_priv->scratch[0] = 0; +	RADEON_WRITE(RADEON_LAST_FRAME_REG, 0); -	dev_priv->sarea_priv->last_dispatch = dev_priv->scratch[1] = 0; -	RADEON_WRITE(RADEON_LAST_DISPATCH_REG, -		     dev_priv->sarea_priv->last_dispatch); +	dev_priv->scratch[1] = 0; +	RADEON_WRITE(RADEON_LAST_DISPATCH_REG, 0); -	dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0; -	RADEON_WRITE(RADEON_LAST_CLEAR_REG, dev_priv->sarea_priv->last_clear); +	dev_priv->scratch[2] = 0; +	RADEON_WRITE(RADEON_LAST_CLEAR_REG, 0);  	radeon_do_wait_for_idle(dev_priv); @@ -871,9 +871,11 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)  	}  } -static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) +static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init, +			     struct drm_file *file_priv)  {  	drm_radeon_private_t *dev_priv = dev->dev_private; +	struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;  	DRM_DEBUG("\n"); @@ -998,8 +1000,8 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)  	dev_priv->buffers_offset = init->buffers_offset;  	dev_priv->gart_textures_offset = init->gart_textures_offset; -	dev_priv->sarea = drm_getsarea(dev); -	if (!dev_priv->sarea) { +	master_priv->sarea = drm_getsarea(dev); +	if (!master_priv->sarea) {  		DRM_ERROR("could not find sarea!\n");  		radeon_do_cleanup_cp(dev);  		return -EINVAL; @@ -1035,10 +1037,6 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)  		}  	} -	dev_priv->sarea_priv = -	    (drm_radeon_sarea_t *) ((u8 *) dev_priv->sarea->handle + -				    init->sarea_priv_offset); -  #if __OS_HAS_AGP  	if (dev_priv->flags & RADEON_IS_AGP) {  		drm_core_ioremap(dev_priv->cp_ring, dev); @@ -1329,7 +1327,7 @@ int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_pri  	case RADEON_INIT_CP:  	case RADEON_INIT_R200_CP:  	case RADEON_INIT_R300_CP: -		return radeon_do_init_cp(dev, init); +		return radeon_do_init_cp(dev, init, file_priv);  	case RADEON_CLEANUP_CP:  		return radeon_do_cleanup_cp(dev);  	} @@ -1768,6 +1766,51 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)  	return ret;  } +int radeon_master_create(struct drm_device *dev, struct drm_master *master) +{ +	struct drm_radeon_master_private *master_priv; +	unsigned long sareapage; +	int ret; + +	master_priv = drm_calloc(1, sizeof(*master_priv), DRM_MEM_DRIVER); +	if (!master_priv) +		return -ENOMEM; + +	/* prebuild the SAREA */ +	sareapage = max(SAREA_MAX, PAGE_SIZE); +	ret = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK|_DRM_DRIVER, +			 &master_priv->sarea); +	if (ret) { +		DRM_ERROR("SAREA setup failed\n"); +		return ret; +	} +	master_priv->sarea_priv = master_priv->sarea->handle + sizeof(struct drm_sarea); +	master_priv->sarea_priv->pfCurrentPage = 0; + +	master->driver_priv = master_priv; +	return 0; +} + +void radeon_master_destroy(struct drm_device *dev, struct drm_master *master) +{ +	struct drm_radeon_master_private *master_priv = master->driver_priv; + +	if (!master_priv) +		return; + +	if (master_priv->sarea_priv && +	    master_priv->sarea_priv->pfCurrentPage != 0) +		radeon_cp_dispatch_flip(dev, master); + +	master_priv->sarea_priv = NULL; +	if (master_priv->sarea) +		drm_rmmap(dev, master_priv->sarea); + +	drm_free(master_priv, sizeof(*master_priv), DRM_MEM_DRIVER); + +	master->driver_priv = NULL; +} +  /* Create mappings for registers and framebuffer so userland doesn't necessarily   * have to find them.   */ diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h index 3bbb871b25d..490bc7ceef6 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.h +++ b/drivers/gpu/drm/radeon/radeon_drv.h @@ -226,9 +226,13 @@ struct radeon_virt_surface {  #define RADEON_FLUSH_EMITED	(1 < 0)  #define RADEON_PURGE_EMITED	(1 < 1) +struct drm_radeon_master_private { +	drm_local_map_t *sarea; +	drm_radeon_sarea_t *sarea_priv; +}; +  typedef struct drm_radeon_private {  	drm_radeon_ring_buffer_t ring; -	drm_radeon_sarea_t *sarea_priv;  	u32 fb_location;  	u32 fb_size; @@ -409,6 +413,9 @@ extern int radeon_driver_open(struct drm_device *dev,  extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,  				unsigned long arg); +extern int radeon_master_create(struct drm_device *dev, struct drm_master *master); +extern void radeon_master_destroy(struct drm_device *dev, struct drm_master *master); +extern void radeon_cp_dispatch_flip(struct drm_device *dev, struct drm_master *master);  /* r300_cmdbuf.c */  extern void r300_init_reg_flags(struct drm_device *dev); @@ -1335,8 +1342,9 @@ do {									\  } while (0)  #define VB_AGE_TEST_WITH_RETURN( dev_priv )				\ -do {									\ -	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;		\ +do {								\ +	struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;	\ +	drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;	\  	if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) {		\  		int __ret = radeon_do_cp_idle( dev_priv );		\  		if ( __ret ) return __ret;				\ diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c index 5d7153fcc7b..ef940a079dc 100644 --- a/drivers/gpu/drm/radeon/radeon_state.c +++ b/drivers/gpu/drm/radeon/radeon_state.c @@ -742,13 +742,14 @@ static struct {   */  static void radeon_clear_box(drm_radeon_private_t * dev_priv, +			     struct drm_radeon_master_private *master_priv,  			     int x, int y, int w, int h, int r, int g, int b)  {  	u32 color;  	RING_LOCALS; -	x += dev_priv->sarea_priv->boxes[0].x1; -	y += dev_priv->sarea_priv->boxes[0].y1; +	x += master_priv->sarea_priv->boxes[0].x1; +	y += master_priv->sarea_priv->boxes[0].y1;  	switch (dev_priv->color_fmt) {  	case RADEON_COLOR_FORMAT_RGB565: @@ -776,7 +777,7 @@ static void radeon_clear_box(drm_radeon_private_t * dev_priv,  		 RADEON_GMC_SRC_DATATYPE_COLOR |  		 RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS); -	if (dev_priv->sarea_priv->pfCurrentPage == 1) { +	if (master_priv->sarea_priv->pfCurrentPage == 1) {  		OUT_RING(dev_priv->front_pitch_offset);  	} else {  		OUT_RING(dev_priv->back_pitch_offset); @@ -790,7 +791,7 @@ static void radeon_clear_box(drm_radeon_private_t * dev_priv,  	ADVANCE_RING();  } -static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv) +static void radeon_cp_performance_boxes(drm_radeon_private_t *dev_priv, struct drm_radeon_master_private *master_priv)  {  	/* Collapse various things into a wait flag -- trying to  	 * guess if userspase slept -- better just to have them tell us. @@ -807,12 +808,12 @@ static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv)  	/* Purple box for page flipping  	 */  	if (dev_priv->stats.boxes & RADEON_BOX_FLIP) -		radeon_clear_box(dev_priv, 4, 4, 8, 8, 255, 0, 255); +		radeon_clear_box(dev_priv, master_priv, 4, 4, 8, 8, 255, 0, 255);  	/* Red box if we have to wait for idle at any point  	 */  	if (dev_priv->stats.boxes & RADEON_BOX_WAIT_IDLE) -		radeon_clear_box(dev_priv, 16, 4, 8, 8, 255, 0, 0); +		radeon_clear_box(dev_priv, master_priv, 16, 4, 8, 8, 255, 0, 0);  	/* Blue box: lost context?  	 */ @@ -820,12 +821,12 @@ static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv)  	/* Yellow box for texture swaps  	 */  	if (dev_priv->stats.boxes & RADEON_BOX_TEXTURE_LOAD) -		radeon_clear_box(dev_priv, 40, 4, 8, 8, 255, 255, 0); +		radeon_clear_box(dev_priv, master_priv, 40, 4, 8, 8, 255, 255, 0);  	/* Green box if hardware never idles (as far as we can tell)  	 */  	if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE)) -		radeon_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0); +		radeon_clear_box(dev_priv, master_priv, 64, 4, 8, 8, 0, 255, 0);  	/* Draw bars indicating number of buffers allocated  	 * (not a great measure, easily confused) @@ -834,7 +835,7 @@ static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv)  		if (dev_priv->stats.requested_bufs > 100)  			dev_priv->stats.requested_bufs = 100; -		radeon_clear_box(dev_priv, 4, 16, +		radeon_clear_box(dev_priv, master_priv, 4, 16,  				 dev_priv->stats.requested_bufs, 4,  				 196, 128, 128);  	} @@ -848,11 +849,13 @@ static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv)   */  static void radeon_cp_dispatch_clear(struct drm_device * dev, +				     struct drm_master *master,  				     drm_radeon_clear_t * clear,  				     drm_radeon_clear_rect_t * depth_boxes)  {  	drm_radeon_private_t *dev_priv = dev->dev_private; -	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; +	struct drm_radeon_master_private *master_priv = master->driver_priv; +	drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;  	drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear;  	int nbox = sarea_priv->nbox;  	struct drm_clip_rect *pbox = sarea_priv->boxes; @@ -864,7 +867,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,  	dev_priv->stats.clears++; -	if (dev_priv->sarea_priv->pfCurrentPage == 1) { +	if (sarea_priv->pfCurrentPage == 1) {  		unsigned int tmp = flags;  		flags &= ~(RADEON_FRONT | RADEON_BACK); @@ -890,7 +893,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,  		/* Make sure we restore the 3D state next time.  		 */ -		dev_priv->sarea_priv->ctx_owner = 0; +		sarea_priv->ctx_owner = 0;  		for (i = 0; i < nbox; i++) {  			int x = pbox[i].x1; @@ -967,7 +970,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,  		/* Make sure we restore the 3D state next time.  		 * we haven't touched any "normal" state - still need this?  		 */ -		dev_priv->sarea_priv->ctx_owner = 0; +		sarea_priv->ctx_owner = 0;  		if ((dev_priv->flags & RADEON_HAS_HIERZ)  		    && (flags & RADEON_USE_HIERZ)) { @@ -1214,7 +1217,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,  		/* Make sure we restore the 3D state next time.  		 */ -		dev_priv->sarea_priv->ctx_owner = 0; +		sarea_priv->ctx_owner = 0;  		for (i = 0; i < nbox; i++) { @@ -1285,7 +1288,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,  		/* Make sure we restore the 3D state next time.  		 */ -		dev_priv->sarea_priv->ctx_owner = 0; +		sarea_priv->ctx_owner = 0;  		for (i = 0; i < nbox; i++) { @@ -1328,20 +1331,21 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,  	 * wait on this value before performing the clear ioctl.  We  	 * need this because the card's so damned fast...  	 */ -	dev_priv->sarea_priv->last_clear++; +	sarea_priv->last_clear++;  	BEGIN_RING(4); -	RADEON_CLEAR_AGE(dev_priv->sarea_priv->last_clear); +	RADEON_CLEAR_AGE(sarea_priv->last_clear);  	RADEON_WAIT_UNTIL_IDLE();  	ADVANCE_RING();  } -static void radeon_cp_dispatch_swap(struct drm_device * dev) +static void radeon_cp_dispatch_swap(struct drm_device *dev, struct drm_master *master)  {  	drm_radeon_private_t *dev_priv = dev->dev_private; -	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; +	struct drm_radeon_master_private *master_priv = master->driver_priv; +	drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;  	int nbox = sarea_priv->nbox;  	struct drm_clip_rect *pbox = sarea_priv->boxes;  	int i; @@ -1351,7 +1355,7 @@ static void radeon_cp_dispatch_swap(struct drm_device * dev)  	/* Do some trivial performance monitoring...  	 */  	if (dev_priv->do_boxes) -		radeon_cp_performance_boxes(dev_priv); +		radeon_cp_performance_boxes(dev_priv, master_priv);  	/* Wait for the 3D stream to idle before dispatching the bitblt.  	 * This will prevent data corruption between the two streams. @@ -1385,7 +1389,7 @@ static void radeon_cp_dispatch_swap(struct drm_device * dev)  		/* Make this work even if front & back are flipped:  		 */  		OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1)); -		if (dev_priv->sarea_priv->pfCurrentPage == 0) { +		if (sarea_priv->pfCurrentPage == 0) {  			OUT_RING(dev_priv->back_pitch_offset);  			OUT_RING(dev_priv->front_pitch_offset);  		} else { @@ -1405,31 +1409,32 @@ static void radeon_cp_dispatch_swap(struct drm_device * dev)  	 * throttle the framerate by waiting for this value before  	 * performing the swapbuffer ioctl.  	 */ -	dev_priv->sarea_priv->last_frame++; +	sarea_priv->last_frame++;  	BEGIN_RING(4); -	RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame); +	RADEON_FRAME_AGE(sarea_priv->last_frame);  	RADEON_WAIT_UNTIL_2D_IDLE();  	ADVANCE_RING();  } -static void radeon_cp_dispatch_flip(struct drm_device * dev) +void radeon_cp_dispatch_flip(struct drm_device *dev, struct drm_master *master)  {  	drm_radeon_private_t *dev_priv = dev->dev_private; -	struct drm_sarea *sarea = (struct drm_sarea *) dev_priv->sarea->handle; -	int offset = (dev_priv->sarea_priv->pfCurrentPage == 1) +	struct drm_radeon_master_private *master_priv = master->driver_priv; +	struct drm_sarea *sarea = (struct drm_sarea *)master_priv->sarea->handle; +	int offset = (master_priv->sarea_priv->pfCurrentPage == 1)  	    ? dev_priv->front_offset : dev_priv->back_offset;  	RING_LOCALS;  	DRM_DEBUG("pfCurrentPage=%d\n", -		  dev_priv->sarea_priv->pfCurrentPage); +		  master_priv->sarea_priv->pfCurrentPage);  	/* Do some trivial performance monitoring...  	 */  	if (dev_priv->do_boxes) {  		dev_priv->stats.boxes |= RADEON_BOX_FLIP; -		radeon_cp_performance_boxes(dev_priv); +		radeon_cp_performance_boxes(dev_priv, master_priv);  	}  	/* Update the frame offsets for both CRTCs @@ -1441,7 +1446,7 @@ static void radeon_cp_dispatch_flip(struct drm_device * dev)  		     ((sarea->frame.y * dev_priv->front_pitch +  		       sarea->frame.x * (dev_priv->color_fmt - 2)) & ~7)  		     + offset); -	OUT_RING_REG(RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base +	OUT_RING_REG(RADEON_CRTC2_OFFSET, master_priv->sarea_priv->crtc2_base  		     + offset);  	ADVANCE_RING(); @@ -1450,13 +1455,13 @@ static void radeon_cp_dispatch_flip(struct drm_device * dev)  	 * throttle the framerate by waiting for this value before  	 * performing the swapbuffer ioctl.  	 */ -	dev_priv->sarea_priv->last_frame++; -	dev_priv->sarea_priv->pfCurrentPage = -		1 - dev_priv->sarea_priv->pfCurrentPage; +	master_priv->sarea_priv->last_frame++; +	master_priv->sarea_priv->pfCurrentPage = +		1 - master_priv->sarea_priv->pfCurrentPage;  	BEGIN_RING(2); -	RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame); +	RADEON_FRAME_AGE(master_priv->sarea_priv->last_frame);  	ADVANCE_RING();  } @@ -1494,11 +1499,13 @@ typedef struct {  } drm_radeon_tcl_prim_t;  static void radeon_cp_dispatch_vertex(struct drm_device * dev, +				      struct drm_file *file_priv,  				      struct drm_buf * buf,  				      drm_radeon_tcl_prim_t * prim)  {  	drm_radeon_private_t *dev_priv = dev->dev_private; -	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; +	struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; +	drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;  	int offset = dev_priv->gart_buffers_offset + buf->offset + prim->start;  	int numverts = (int)prim->numverts;  	int nbox = sarea_priv->nbox; @@ -1539,13 +1546,14 @@ static void radeon_cp_dispatch_vertex(struct drm_device * dev,  	} while (i < nbox);  } -static void radeon_cp_discard_buffer(struct drm_device * dev, struct drm_buf * buf) +static void radeon_cp_discard_buffer(struct drm_device *dev, struct drm_master *master, struct drm_buf *buf)  {  	drm_radeon_private_t *dev_priv = dev->dev_private; +	struct drm_radeon_master_private *master_priv = master->driver_priv;  	drm_radeon_buf_priv_t *buf_priv = buf->dev_private;  	RING_LOCALS; -	buf_priv->age = ++dev_priv->sarea_priv->last_dispatch; +	buf_priv->age = ++master_priv->sarea_priv->last_dispatch;  	/* Emit the vertex buffer age */  	BEGIN_RING(2); @@ -1590,12 +1598,14 @@ static void radeon_cp_dispatch_indirect(struct drm_device * dev,  	}  } -static void radeon_cp_dispatch_indices(struct drm_device * dev, +static void radeon_cp_dispatch_indices(struct drm_device *dev, +				       struct drm_master *master,  				       struct drm_buf * elt_buf,  				       drm_radeon_tcl_prim_t * prim)  {  	drm_radeon_private_t *dev_priv = dev->dev_private; -	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; +	struct drm_radeon_master_private *master_priv = master->driver_priv; +	drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;  	int offset = dev_priv->gart_buffers_offset + prim->offset;  	u32 *data;  	int dwords; @@ -1870,7 +1880,7 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev,  		ADVANCE_RING();  		COMMIT_RING(); -		radeon_cp_discard_buffer(dev, buf); +		radeon_cp_discard_buffer(dev, file_priv->master, buf);  		/* Update the input parameters for next time */  		image->y += height; @@ -2110,7 +2120,8 @@ static int radeon_surface_free(struct drm_device *dev, void *data, struct drm_fi  static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *file_priv)  {  	drm_radeon_private_t *dev_priv = dev->dev_private; -	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; +	struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; +	drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;  	drm_radeon_clear_t *clear = data;  	drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];  	DRM_DEBUG("\n"); @@ -2126,7 +2137,7 @@ static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *  			       sarea_priv->nbox * sizeof(depth_boxes[0])))  		return -EFAULT; -	radeon_cp_dispatch_clear(dev, clear, depth_boxes); +	radeon_cp_dispatch_clear(dev, file_priv->master, clear, depth_boxes);  	COMMIT_RING();  	return 0; @@ -2134,9 +2145,10 @@ static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *  /* Not sure why this isn't set all the time:   */ -static int radeon_do_init_pageflip(struct drm_device * dev) +static int radeon_do_init_pageflip(struct drm_device *dev, struct drm_master *master)  {  	drm_radeon_private_t *dev_priv = dev->dev_private; +	struct drm_radeon_master_private *master_priv = master->driver_priv;  	RING_LOCALS;  	DRM_DEBUG("\n"); @@ -2153,8 +2165,8 @@ static int radeon_do_init_pageflip(struct drm_device * dev)  	dev_priv->page_flipping = 1; -	if (dev_priv->sarea_priv->pfCurrentPage != 1) -		dev_priv->sarea_priv->pfCurrentPage = 0; +	if (master_priv->sarea_priv->pfCurrentPage != 1) +		master_priv->sarea_priv->pfCurrentPage = 0;  	return 0;  } @@ -2172,9 +2184,9 @@ static int radeon_cp_flip(struct drm_device *dev, void *data, struct drm_file *f  	RING_SPACE_TEST_WITH_RETURN(dev_priv);  	if (!dev_priv->page_flipping) -		radeon_do_init_pageflip(dev); +		radeon_do_init_pageflip(dev, file_priv->master); -	radeon_cp_dispatch_flip(dev); +	radeon_cp_dispatch_flip(dev, file_priv->master);  	COMMIT_RING();  	return 0; @@ -2183,7 +2195,9 @@ static int radeon_cp_flip(struct drm_device *dev, void *data, struct drm_file *f  static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *file_priv)  {  	drm_radeon_private_t *dev_priv = dev->dev_private; -	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; +	struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; +	drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; +  	DRM_DEBUG("\n");  	LOCK_TEST_WITH_RETURN(dev, file_priv); @@ -2193,8 +2207,8 @@ static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *f  	if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)  		sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS; -	radeon_cp_dispatch_swap(dev); -	dev_priv->sarea_priv->ctx_owner = 0; +	radeon_cp_dispatch_swap(dev, file_priv->master); +	sarea_priv->ctx_owner = 0;  	COMMIT_RING();  	return 0; @@ -2203,7 +2217,8 @@ static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *f  static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv)  {  	drm_radeon_private_t *dev_priv = dev->dev_private; -	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; +	struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; +	drm_radeon_sarea_t *sarea_priv;  	struct drm_device_dma *dma = dev->dma;  	struct drm_buf *buf;  	drm_radeon_vertex_t *vertex = data; @@ -2211,6 +2226,8 @@ static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file  	LOCK_TEST_WITH_RETURN(dev, file_priv); +	sarea_priv = master_priv->sarea_priv; +  	DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",  		  DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard); @@ -2263,13 +2280,13 @@ static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file  		prim.finish = vertex->count;	/* unused */  		prim.prim = vertex->prim;  		prim.numverts = vertex->count; -		prim.vc_format = dev_priv->sarea_priv->vc_format; +		prim.vc_format = sarea_priv->vc_format; -		radeon_cp_dispatch_vertex(dev, buf, &prim); +		radeon_cp_dispatch_vertex(dev, file_priv, buf, &prim);  	}  	if (vertex->discard) { -		radeon_cp_discard_buffer(dev, buf); +		radeon_cp_discard_buffer(dev, file_priv->master, buf);  	}  	COMMIT_RING(); @@ -2279,7 +2296,8 @@ static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file  static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file *file_priv)  {  	drm_radeon_private_t *dev_priv = dev->dev_private; -	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; +	struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; +	drm_radeon_sarea_t *sarea_priv;  	struct drm_device_dma *dma = dev->dma;  	struct drm_buf *buf;  	drm_radeon_indices_t *elts = data; @@ -2288,6 +2306,8 @@ static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file  	LOCK_TEST_WITH_RETURN(dev, file_priv); +	sarea_priv = master_priv->sarea_priv; +  	DRM_DEBUG("pid=%d index=%d start=%d end=%d discard=%d\n",  		  DRM_CURRENTPID, elts->idx, elts->start, elts->end,  		  elts->discard); @@ -2353,11 +2373,11 @@ static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file  	prim.prim = elts->prim;  	prim.offset = 0;	/* offset from start of dma buffers */  	prim.numverts = RADEON_MAX_VB_VERTS;	/* duh */ -	prim.vc_format = dev_priv->sarea_priv->vc_format; +	prim.vc_format = sarea_priv->vc_format; -	radeon_cp_dispatch_indices(dev, buf, &prim); +	radeon_cp_dispatch_indices(dev, file_priv->master, buf, &prim);  	if (elts->discard) { -		radeon_cp_discard_buffer(dev, buf); +		radeon_cp_discard_buffer(dev, file_priv->master, buf);  	}  	COMMIT_RING(); @@ -2468,7 +2488,7 @@ static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_fil  	 */  	radeon_cp_dispatch_indirect(dev, buf, indirect->start, indirect->end);  	if (indirect->discard) { -		radeon_cp_discard_buffer(dev, buf); +		radeon_cp_discard_buffer(dev, file_priv->master, buf);  	}  	COMMIT_RING(); @@ -2478,7 +2498,8 @@ static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_fil  static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file *file_priv)  {  	drm_radeon_private_t *dev_priv = dev->dev_private; -	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; +	struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; +	drm_radeon_sarea_t *sarea_priv;  	struct drm_device_dma *dma = dev->dma;  	struct drm_buf *buf;  	drm_radeon_vertex2_t *vertex = data; @@ -2487,6 +2508,8 @@ static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file  	LOCK_TEST_WITH_RETURN(dev, file_priv); +	sarea_priv = master_priv->sarea_priv; +  	DRM_DEBUG("pid=%d index=%d discard=%d\n",  		  DRM_CURRENTPID, vertex->idx, vertex->discard); @@ -2547,12 +2570,12 @@ static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file  			tclprim.offset = prim.numverts * 64;  			tclprim.numverts = RADEON_MAX_VB_VERTS;	/* duh */ -			radeon_cp_dispatch_indices(dev, buf, &tclprim); +			radeon_cp_dispatch_indices(dev, file_priv->master, buf, &tclprim);  		} else {  			tclprim.numverts = prim.numverts;  			tclprim.offset = 0;	/* not used */ -			radeon_cp_dispatch_vertex(dev, buf, &tclprim); +			radeon_cp_dispatch_vertex(dev, file_priv, buf, &tclprim);  		}  		if (sarea_priv->nbox == 1) @@ -2560,7 +2583,7 @@ static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file  	}  	if (vertex->discard) { -		radeon_cp_discard_buffer(dev, buf); +		radeon_cp_discard_buffer(dev, file_priv->master, buf);  	}  	COMMIT_RING(); @@ -2909,7 +2932,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file  				goto err;  			} -			radeon_cp_discard_buffer(dev, buf); +			radeon_cp_discard_buffer(dev, file_priv->master, buf);  			break;  		case RADEON_CMD_PACKET3: @@ -3020,7 +3043,7 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil  		 */  	case RADEON_PARAM_SAREA_HANDLE:  		/* The lock is the first dword in the sarea. */ -		value = (long)dev->lock.hw_lock; +		/* no users of this parameter */  		break;  #endif  	case RADEON_PARAM_GART_TEX_HANDLE: @@ -3064,6 +3087,7 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil  static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_file *file_priv)  {  	drm_radeon_private_t *dev_priv = dev->dev_private; +	struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;  	drm_radeon_setparam_t *sp = data;  	struct drm_radeon_driver_file_fields *radeon_priv; @@ -3078,12 +3102,14 @@ static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_fil  			DRM_DEBUG("color tiling disabled\n");  			dev_priv->front_pitch_offset &= ~RADEON_DST_TILE_MACRO;  			dev_priv->back_pitch_offset &= ~RADEON_DST_TILE_MACRO; -			dev_priv->sarea_priv->tiling_enabled = 0; +			if (master_priv->sarea_priv) +				master_priv->sarea_priv->tiling_enabled = 0;  		} else if (sp->value == 1) {  			DRM_DEBUG("color tiling enabled\n");  			dev_priv->front_pitch_offset |= RADEON_DST_TILE_MACRO;  			dev_priv->back_pitch_offset |= RADEON_DST_TILE_MACRO; -			dev_priv->sarea_priv->tiling_enabled = 1; +			if (master_priv->sarea_priv) +				master_priv->sarea_priv->tiling_enabled = 1;  		}  		break;  	case RADEON_SETPARAM_PCIGART_LOCATION: @@ -3129,14 +3155,6 @@ void radeon_driver_preclose(struct drm_device *dev, struct drm_file *file_priv)  void radeon_driver_lastclose(struct drm_device *dev)  { -	if (dev->dev_private) { -		drm_radeon_private_t *dev_priv = dev->dev_private; - -		if (dev_priv->sarea_priv && -		    dev_priv->sarea_priv->pfCurrentPage != 0) -			radeon_cp_dispatch_flip(dev); -	} -  	radeon_do_release(dev);  }  |