diff options
| -rw-r--r-- | linux-core/drmP.h | 59 | ||||
| -rw-r--r-- | linux-core/drm_auth.c | 28 | ||||
| -rw-r--r-- | linux-core/drm_bufs.c | 12 | ||||
| -rw-r--r-- | linux-core/drm_context.c | 2 | ||||
| -rw-r--r-- | linux-core/drm_drv.c | 26 | ||||
| -rw-r--r-- | linux-core/drm_fops.c | 67 | ||||
| -rw-r--r-- | linux-core/drm_ioctl.c | 46 | ||||
| -rw-r--r-- | linux-core/drm_irq.c | 6 | ||||
| -rw-r--r-- | linux-core/drm_lock.c | 40 | ||||
| -rw-r--r-- | linux-core/drm_proc.c | 5 | ||||
| -rw-r--r-- | linux-core/drm_stub.c | 70 | ||||
| -rw-r--r-- | linux-core/i915_drv.c | 2 | ||||
| -rw-r--r-- | linux-core/intel_display.c | 31 | ||||
| -rw-r--r-- | linux-core/via_fence.c | 4 | 
14 files changed, 246 insertions, 152 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h index afc16f5f..d01bf09d 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -262,11 +262,11 @@ struct drm_file;   */  #define LOCK_TEST_WITH_RETURN( dev, file_priv )				\  do {									\ -	if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||		\ -	     dev->lock.file_priv != file_priv )	{			\ +	if ( !_DRM_LOCK_IS_HELD( dev->primary->master->lock.hw_lock->lock ) ||		\ +	     dev->primary->master->lock.file_priv != file_priv )	{			\  		DRM_ERROR( "%s called without lock held, held  %d owner %p %p\n",\ -			   __FUNCTION__, _DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ),\ -			   dev->lock.file_priv, file_priv );		\ +			   __FUNCTION__, _DRM_LOCK_IS_HELD( dev->primary->master->lock.hw_lock->lock ),\ +			   dev->primary->master->lock.file_priv, file_priv );		\  		return -EINVAL;						\  	}								\  } while (0) @@ -410,7 +410,6 @@ enum drm_ref_type {  /** File private data */  struct drm_file {  	int authenticated; -	int master;  	pid_t pid;  	uid_t uid;  	drm_magic_t magic; @@ -431,6 +430,7 @@ struct drm_file {  	struct drm_open_hash refd_object_hash[_DRM_NO_REF_TYPES];  	struct file *filp; +	struct drm_master *master; /* this private has a master associated with it */  	void *driver_priv;  	struct list_head fbs; @@ -568,6 +568,8 @@ struct drm_map_list {  	struct drm_map *map;			/**< mapping */  	uint64_t user_token;  	struct drm_mm_node *file_offset_node; +	struct drm_master *master; /** if this map is associated with a specific +				       master */  };  typedef struct drm_map drm_local_map_t; @@ -607,6 +609,27 @@ struct drm_ati_pcigart_info {  #include "drm_objects.h" +/* per-master structure */ +struct drm_master { +	 +	struct drm_device *dev; + +	char *unique;			/**< Unique identifier: e.g., busid */ +	int unique_len;			/**< Length of unique field */ + +	int blocked;			/**< Blocked due to VC switch? */ + +	/** \name Authentication */ +	/*@{ */ +	struct drm_open_hash magiclist; +	struct list_head magicfree; +	/*@} */ + +	struct drm_lock_data lock;		/**< Information on hardware lock */ + +	void *driver_priv; /**< Private structure for driver to use */ +}; +  /**   * DRM driver structure. This structure represent the common code for   * a family of cards. There will one drm_device for each card present @@ -711,6 +734,10 @@ struct drm_driver {  	int (*fb_remove)(struct drm_device *dev, struct drm_crtc *crtc);  	int (*fb_resize)(struct drm_device *dev, struct drm_crtc *crtc); +	/* Master routines */ +	int (*master_create)(struct drm_device *dev, struct drm_master *master); +	void (*master_destroy)(struct drm_device *dev, struct drm_master *master); +  	struct drm_fence_driver *fence_driver;  	struct drm_bo_driver *bo_driver; @@ -746,6 +773,9 @@ struct drm_minor {  	/* for render nodes */  	struct proc_dir_entry *dev_root;  /**< proc directory entry */  	struct class_device *dev_class; + +	/* for control nodes - a pointer to the current master for this control node */ +	struct drm_master *master;  }; @@ -754,13 +784,9 @@ struct drm_minor {   * may contain multiple heads.   */  struct drm_device { -	char *unique;			/**< Unique identifier: e.g., busid */ -	int unique_len;			/**< Length of unique field */  	char *devname;			/**< For /proc/interrupts */  	int if_version;			/**< Highest interface version set */ -	int blocked;			/**< Blocked due to VC switch? */ -  	/** \name Locks */  	/*@{ */  	spinlock_t count_lock;		/**< For inuse, drm_device::open_count, drm_device::buf_use */ @@ -783,12 +809,6 @@ struct drm_device {  	atomic_t counts[15];  	/*@} */ -	/** \name Authentication */ -	/*@{ */ -	struct list_head filelist; -	struct drm_open_hash magiclist; -	struct list_head magicfree; -	/*@} */  	/** \name Memory management */  	/*@{ */ @@ -809,7 +829,9 @@ struct drm_device {  	struct idr ctx_idr;  	struct list_head vmalist;	/**< List of vmas (for debugging) */ -	struct drm_lock_data lock;		/**< Information on hardware lock */ + +	struct list_head filelist; +//	struct drm_master *master;  	/*@} */  	/** \name DMA queues (contexts) */ @@ -821,6 +843,7 @@ struct drm_device {  	struct drm_device_dma *dma;		/**< Optional pointer for DMA support */  	/*@} */ +  	/** \name Context support */  	/*@{ */  	int irq;			/**< Interrupt used by board */ @@ -884,7 +907,7 @@ struct drm_device {  	/* minor number for control node */  	struct drm_minor *control; -	struct drm_minor *primary;		/**< primary screen head */ +	struct drm_minor *primary;		/**< render type primary screen head */  	struct drm_fence_manager fm;  	struct drm_buffer_manager bm; @@ -1212,6 +1235,8 @@ extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle);  extern struct drm_ttm_backend *drm_agp_init_ttm(struct drm_device *dev);  extern void drm_agp_chipset_flush(struct drm_device *dev);  				/* Stub support (drm_stub.h) */ +extern struct drm_master *drm_get_master(struct drm_device *dev); +extern void drm_put_master(struct drm_master *master);  extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,  		     struct drm_driver *driver);  extern int drm_put_dev(struct drm_device *dev); diff --git a/linux-core/drm_auth.c b/linux-core/drm_auth.c index c904a91d..8e85a761 100644 --- a/linux-core/drm_auth.c +++ b/linux-core/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->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->dev;  	DRM_DEBUG("%d\n", magic);  	entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC); @@ -85,8 +86,8 @@ static int drm_add_magic(struct drm_device * dev, struct drm_file * priv,  	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; @@ -101,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->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); @@ -152,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(dev->primary->master, auth->magic));  		file_priv->magic = auth->magic; -		drm_add_magic(dev, file_priv, auth->magic); +		drm_add_magic(dev->primary->master, file_priv, auth->magic);  	}  	DRM_DEBUG("%u\n", auth->magic); @@ -180,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(dev->primary->master, auth->magic))) {  		file->authenticated = 1; -		drm_remove_magic(dev, auth->magic); +		drm_remove_magic(dev->primary->master, auth->magic);  		return 0;  	}  	return -EINVAL; diff --git a/linux-core/drm_bufs.c b/linux-core/drm_bufs.c index 967e9a2d..3e1767c0 100644 --- a/linux-core/drm_bufs.c +++ b/linux-core/drm_bufs.c @@ -52,7 +52,7 @@ struct drm_map_list *drm_find_matching_map(struct drm_device *dev, drm_local_map  {  	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)))) {  			return entry; @@ -209,12 +209,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: { @@ -412,9 +412,9 @@ int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map)  		break;  	case _DRM_SHM:  		vfree(map->handle); -		dev->sigdata.lock = dev->lock.hw_lock = NULL;   /* SHM removed */ -		dev->lock.file_priv = NULL; -		wake_up_interruptible(&dev->lock.lock_queue); +		dev->sigdata.lock = dev->primary->master->lock.hw_lock = NULL;   /* SHM removed */ +		dev->primary->master->lock.file_priv = NULL; +		wake_up_interruptible(&dev->primary->master->lock.lock_queue);  		break;  	case _DRM_AGP:  	case _DRM_SCATTER_GATHER: diff --git a/linux-core/drm_context.c b/linux-core/drm_context.c index 83ad291e..63a38253 100644 --- a/linux-core/drm_context.c +++ b/linux-core/drm_context.c @@ -262,7 +262,7 @@ static int drm_context_switch_complete(struct drm_device *dev, 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(dev->primary->master->lock.hw_lock->lock)) {  		DRM_ERROR("Lock isn't held after context switch\n");  	} diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index e9955239..4f5b364e 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -180,8 +180,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; @@ -196,11 +194,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); */ @@ -211,22 +204,11 @@ int drm_lastclose(struct drm_device * dev)  	drm_drawable_free_all(dev);  	del_timer(&dev->timer); -	if (dev->unique) { -		drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER); -		dev->unique = NULL; -		dev->unique_len = 0; -	} - -	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); +	if (dev->primary->master) { +		drm_put_master(dev->primary->master); +		dev->primary->master = NULL;  	} - - +	  	/* Clear AGP information */  	if (drm_core_has_AGP(dev) && dev->agp) {  		struct drm_agp_mem *entry, *tempe; diff --git a/linux-core/drm_fops.c b/linux-core/drm_fops.c index 344d90e1..c699e967 100644 --- a/linux-core/drm_fops.c +++ b/linux-core/drm_fops.c @@ -54,8 +54,6 @@ static int drm_setup(struct drm_device * dev)  			return ret;  	} -	dev->magicfree.next = NULL; -  	/* prebuild the SAREA */  	sareapage = max(SAREA_MAX, PAGE_SIZE);  	i = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK, &map); @@ -76,11 +74,8 @@ 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; @@ -282,8 +277,26 @@ static int drm_open_helper(struct inode *inode, struct file *filp,  	}  	mutex_lock(&dev->struct_mutex); -	if (list_empty(&dev->filelist)) -		priv->master = 1; + +	/* if there is no current master make this fd it */ +	if (!dev->primary->master) { +		priv->master = drm_get_master(dev); +		if (!priv->master) { +			ret = -ENOMEM; +			goto out_free; +		} +		dev->primary->master = priv->master; + +		if (dev->driver->master_create) { +			ret = dev->driver->master_create(dev, dev->primary->master); +			if (ret) { +				drm_put_master(dev->primary->master); +				dev->primary->master = priv->master = NULL; +				goto out_free; +			} +		} +	} else +		priv->master = NULL;  	list_add(&priv->lhead, &dev->filelist);  	mutex_unlock(&dev->struct_mutex); @@ -390,23 +403,23 @@ int drm_release(struct inode *inode, struct file *filp)  		  current->pid, (long)old_encode_dev(file_priv->minor->device),  		  dev->open_count); -	if (dev->driver->reclaim_buffers_locked && dev->lock.hw_lock) { +	if (dev->driver->reclaim_buffers_locked && dev->primary->master->lock.hw_lock) {  		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(&dev->lock); +			drm_idlelock_take(&dev->primary->master->lock);  			/*  			 * Wait for a while.  			 */  			do{ -				spin_lock(&dev->lock.spinlock); -				locked = dev->lock.idle_has_lock; -				spin_unlock(&dev->lock.spinlock); +				spin_lock(&dev->primary->master->lock.spinlock); +				locked = dev->primary->master->lock.idle_has_lock; +				spin_unlock(&dev->primary->master->lock.spinlock);  				if (locked)  					break;  				schedule(); @@ -419,24 +432,24 @@ int drm_release(struct inode *inode, struct file *filp)  			}  			dev->driver->reclaim_buffers_locked(dev, file_priv); -			drm_idlelock_release(&dev->lock); +			drm_idlelock_release(&dev->primary->master->lock);  		}  	} -	if (dev->driver->reclaim_buffers_idlelocked && dev->lock.hw_lock) { +	if (dev->driver->reclaim_buffers_idlelocked && dev->primary->master->lock.hw_lock) { -		drm_idlelock_take(&dev->lock); +		drm_idlelock_take(&dev->primary->master->lock);  		dev->driver->reclaim_buffers_idlelocked(dev, file_priv); -		drm_idlelock_release(&dev->lock); +		drm_idlelock_release(&dev->primary->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(dev->lock.hw_lock->lock)); +			  filp, _DRM_LOCKING_CONTEXT(dev->primary->master->lock.hw_lock->lock)); -		drm_lock_free(&dev->lock, -			      _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); +		drm_lock_free(&dev->primary->master->lock, +			      _DRM_LOCKING_CONTEXT(dev->primary->master->lock.hw_lock->lock));  	} @@ -479,6 +492,14 @@ int drm_release(struct inode *inode, struct file *filp)  			temp->authenticated = 0;  	}  	list_del(&file_priv->lhead); + +	if (file_priv->master) { +		if (file_priv->master == dev->primary->master) +		       dev->primary->master = NULL; +	       drm_put_master(file_priv->master); +	       file_priv->master = NULL; +	} +  	mutex_unlock(&dev->struct_mutex);  	if (dev->driver->postclose) @@ -492,9 +513,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/linux-core/drm_ioctl.c b/linux-core/drm_ioctl.c index 3df163db..c15923ef 100644 --- a/linux-core/drm_ioctl.c +++ b/linux-core/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 = dev->primary->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 = dev->primary->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; @@ -127,31 +129,33 @@ int drm_setunique(struct drm_device *dev, void *data,  static int drm_set_busid(struct drm_device * dev)  { +	struct drm_master *master = dev->primary->master;  	int len; -	if (dev->unique != NULL) + +	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", +	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) +	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;  } @@ -275,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); +			    (dev->primary->master->lock.hw_lock ? dev->primary->master->lock.hw_lock->lock : 0);  		else  			stats->data[i].value = atomic_read(&dev->counts[i]);  		stats->data[i].type = dev->types[i]; diff --git a/linux-core/drm_irq.c b/linux-core/drm_irq.c index c75f20b2..d88269a4 100644 --- a/linux-core/drm_irq.c +++ b/linux-core/drm_irq.c @@ -636,18 +636,18 @@ static void drm_locked_tasklet_func(unsigned long data)  	spin_lock_irqsave(&dev->tasklet_lock, irqflags);  	if (!dev->locked_tasklet_func || -	    !drm_lock_take(&dev->lock, +	    !drm_lock_take(&dev->primary->master->lock,  			   DRM_KERNEL_CONTEXT)) {  		spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);  		return;  	} -	dev->lock.lock_time = jiffies; +	dev->primary->master->lock.lock_time = jiffies;  	atomic_inc(&dev->counts[_DRM_STAT_LOCKS]);  	dev->locked_tasklet_func(dev); -	drm_lock_free(&dev->lock, +	drm_lock_free(&dev->primary->master->lock,  		      DRM_KERNEL_CONTEXT);  	dev->locked_tasklet_func = NULL; diff --git a/linux-core/drm_lock.c b/linux-core/drm_lock.c index b8e4a5d9..7404856e 100644 --- a/linux-core/drm_lock.c +++ b/linux-core/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 = dev->primary->master;  	int ret = 0;  	++file_priv->lock_count; @@ -64,26 +65,26 @@ 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, current->pid, -		  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(&dev->lock.spinlock); -	dev->lock.user_waiters++; -	spin_unlock(&dev->lock.spinlock); +	add_wait_queue(&master->lock.lock_queue, &entry); +	spin_lock(&master->lock.spinlock); +	master->lock.user_waiters++; +	spin_unlock(&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 +96,11 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)  			break;  		}  	} -	spin_lock(&dev->lock.spinlock); -	dev->lock.user_waiters--; -	spin_unlock(&dev->lock.spinlock); +	spin_lock(&master->lock.spinlock); +	master->lock.user_waiters--; +	spin_unlock(&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"); @@ -111,7 +112,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)  	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);  	if (dev->driver->dma_ready && (lock->flags & _DRM_LOCK_READY)) @@ -149,6 +150,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 = dev->primary->master;  	unsigned long irqflags;  	if (lock->context == DRM_KERNEL_CONTEXT) { @@ -175,7 +177,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. */  		}  	} @@ -384,10 +386,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 = dev->primary->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/linux-core/drm_proc.c b/linux-core/drm_proc.c index b28d8238..12c08c86 100644 --- a/linux-core/drm_proc.c +++ b/linux-core/drm_proc.c @@ -166,6 +166,7 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request,  			 int *eof, void *data)  {  	struct drm_device *dev = (struct drm_device *) data; +	struct drm_master *master = dev->primary->master;  	int len = 0;  	if (offset > DRM_PROC_LIMIT) { @@ -176,10 +177,10 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request,  	*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/linux-core/drm_stub.c b/linux-core/drm_stub.c index 5a39afb3..66a7b8b5 100644 --- a/linux-core/drm_stub.c +++ b/linux-core/drm_stub.c @@ -91,13 +91,63 @@ again:  	return new_id;  } +struct drm_master *drm_get_master(struct drm_device *dev) +{ +	struct drm_master *master; + +	master = drm_calloc(1, sizeof(*master), DRM_MEM_DRIVER); +	if (!master) +		return NULL; + +//	INIT_LIST_HEAD(&master->filelist); +	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->dev = dev; + +	return master; +} + +void drm_put_master(struct drm_master *master) +{ +	struct drm_magic_entry *pt, *next; +	struct drm_device *dev = master->dev; + +	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;	/* SHM removed */ +		master->lock.file_priv = NULL; +		wake_up_interruptible(&master->lock.lock_queue); +	} + +	drm_free(master, sizeof(*master), DRM_MEM_DRIVER); +} +  static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,  			   const struct pci_device_id *ent,  			   struct drm_driver *driver)  {  	int retcode; -	INIT_LIST_HEAD(&dev->filelist);  	INIT_LIST_HEAD(&dev->ctxlist);  	INIT_LIST_HEAD(&dev->vmalist);  	INIT_LIST_HEAD(&dev->maplist); @@ -105,7 +155,7 @@ 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->tasklet_lock); -	spin_lock_init(&dev->lock.spinlock); +//	spin_lock_init(&dev->lock.spinlock);  	init_timer(&dev->timer);  	mutex_init(&dev->struct_mutex);  	mutex_init(&dev->ctxlist_mutex); @@ -168,10 +218,6 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,  		}  	} -	if (dev->driver->load) -		if ((retcode = dev->driver->load(dev, ent->driver_data))) -			goto error_out_unreg; -  	retcode = drm_ctxbitmap_init(dev);  	if (retcode) {  		DRM_ERROR("Cannot allocate memory for context bitmap.\n"); @@ -301,12 +347,17 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,  	if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_RENDER)))  		goto err_g4; +	if (dev->driver->load) +		if ((ret = dev->driver->load(dev, ent->driver_data))) +			goto err_g5; +  	DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",  		 driver->name, driver->major, driver->minor, driver->patchlevel,  		 driver->date, dev->primary->index);  	return 0; - +err_g5: +	drm_put_minor(&dev->primary);  err_g4:  	drm_put_minor(&dev->control);  err_g3: @@ -340,11 +391,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/linux-core/i915_drv.c b/linux-core/i915_drv.c index 629a39be..1f841642 100644 --- a/linux-core/i915_drv.c +++ b/linux-core/i915_drv.c @@ -558,6 +558,8 @@ static struct drm_driver driver = {  	.fb_probe = intelfb_probe,  	.fb_remove = intelfb_remove,  	.fb_resize = intelfb_resize, +	.master_create = i915_master_create, +	.master_destroy = i915_master_destroy,  	.ioctls = i915_ioctls,  	.fops = {  		.owner = THIS_MODULE, diff --git a/linux-core/intel_display.c b/linux-core/intel_display.c index 5b7a510b..db3aee83 100644 --- a/linux-core/intel_display.c +++ b/linux-core/intel_display.c @@ -363,6 +363,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y)  {  	struct drm_device *dev = crtc->dev;  	struct drm_i915_private *dev_priv = dev->dev_private; +	struct drm_i915_master_private *master_priv;  	struct intel_crtc *intel_crtc = crtc->driver_private;  	int pipe = intel_crtc->pipe;  	unsigned long Start, Offset; @@ -384,17 +385,21 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y)  	} -	if (!dev_priv->sarea_priv)  +	if (!dev->primary->master) +		return; + +	master_priv = dev->primary->master->driver_priv; +	if (!master_priv->sarea_priv)   		return;  	switch (pipe) {  	case 0: -		dev_priv->sarea_priv->planeA_x = x; -		dev_priv->sarea_priv->planeA_y = y; +		master_priv->sarea_priv->planeA_x = x; +		master_priv->sarea_priv->planeA_y = y;  		break;  	case 1: -		dev_priv->sarea_priv->planeB_x = x; -		dev_priv->sarea_priv->planeB_y = y; +		master_priv->sarea_priv->planeB_x = x; +		master_priv->sarea_priv->planeB_y = y;  		break;  	default:  		DRM_ERROR("Can't update pipe %d in SAREA\n", pipe); @@ -413,6 +418,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y)  static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)  {  	struct drm_device *dev = crtc->dev; +	struct drm_i915_master_private *master_priv;  	struct drm_i915_private *dev_priv = dev->dev_private;  	struct intel_crtc *intel_crtc = crtc->driver_private;  	int pipe = intel_crtc->pipe; @@ -506,21 +512,24 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)  		udelay(150);  		break;  	} -	 -	if (!dev_priv->sarea_priv) +	if (!dev->primary->master) +		return;	 + +	master_priv = dev->primary->master->driver_priv; +	if (!master_priv->sarea_priv)  		return;  	enabled = crtc->enabled && mode != DPMSModeOff;  	switch (pipe) {  	case 0: -		dev_priv->sarea_priv->planeA_w = enabled ? crtc->mode.hdisplay : 0; -		dev_priv->sarea_priv->planeA_h = enabled ? crtc->mode.vdisplay : 0; +		master_priv->sarea_priv->planeA_w = enabled ? crtc->mode.hdisplay : 0; +		master_priv->sarea_priv->planeA_h = enabled ? crtc->mode.vdisplay : 0;  		break;  	case 1: -		dev_priv->sarea_priv->planeB_w = enabled ? crtc->mode.hdisplay : 0; -		dev_priv->sarea_priv->planeB_h = enabled ? crtc->mode.vdisplay : 0; +		master_priv->sarea_priv->planeB_w = enabled ? crtc->mode.hdisplay : 0; +		master_priv->sarea_priv->planeB_h = enabled ? crtc->mode.vdisplay : 0;  		break;  	default:  		DRM_ERROR("Can't update pipe %d in SAREA\n", pipe); diff --git a/linux-core/via_fence.c b/linux-core/via_fence.c index 9af1bf3b..b853df5c 100644 --- a/linux-core/via_fence.c +++ b/linux-core/via_fence.c @@ -69,7 +69,7 @@ static uint32_t via_perform_flush(struct drm_device *dev, uint32_t class)  		if (!dev_priv->have_idlelock) { -			drm_idlelock_take(&dev->lock); +			drm_idlelock_take(&dev->primary->master->lock);  			dev_priv->have_idlelock = 1;  		} @@ -95,7 +95,7 @@ static uint32_t via_perform_flush(struct drm_device *dev, uint32_t class)  		if (signaled_flush_types) {  			pending_flush_types &= ~signaled_flush_types;  			if (!pending_flush_types && dev_priv->have_idlelock) { -				drm_idlelock_release(&dev->lock); +				drm_idlelock_release(&dev->primary->master->lock);  				dev_priv->have_idlelock = 0;  			}  			drm_fence_handler(dev, 0, dev_priv->emit_0_sequence,  | 
