The DRM has never been able to support multiple X servers for DRI that 
could be chvt'ed between (fast-user-switching...)

This is my first attempt at a patch to provide this support. With it and a 
slightly hacked up intel driver I can run two servers with gears on each 
and chvt between them (it eventually breaks but I think that is probably a 
memory management collision).

The current master switch protocol is simple as, there is set and drop 
master, which the driver calls on VT switch. The set blocks ugly waiting 
for the master to become available, it may be safe to remove the while or 
to change the block to userspace polling on the master. I'm thinking a 
nice solution includes some sort of request/notification scheme.

Interrupt handler - userspace plays with the irq lines, I think we could 
have issues getting interrupts when we have no master.

Shutdown - if you close server 1 while server 2 is the master, you run 
into the biggest wall. As server 1 cannot demand master status until 
server 2 gives it up. I'm thinking the nicest way is to just block server 
1 until it can be master again, but there may be a way to let it exit 
gracefully by switching master on some of its ioctls, but then we'd need 
to figure out what to do with any interrupts that arrive while the masters 
are switched etc... 

Please let me know of any ideas you are having in this area, and whether 
I've missed anything obvious.... I'm just throwing this out there for 
discussion, as per usual I've no idea if/when I can get back to finishing 
this properly...

also in http://cgit.freedesktop.org/~airlied/drm/log/?h=multi-master

Dave.
diff --git a/libdrm/xf86drm.c b/libdrm/xf86drm.c
index 4265c32..eb7cc0f 100644
--- a/libdrm/xf86drm.c
+++ b/libdrm/xf86drm.c
@@ -2960,3 +2960,20 @@ void drmCloseOnce(int fd)
 	}
     }
 }
+
+int drmSetMaster(int fd)
+{
+	int ret;
+
+	fprintf(stderr,"Setting master \n");
+	ret = ioctl(fd, DRM_IOCTL_SET_MASTER, 0);
+	return ret;
+}
+
+int drmDropMaster(int fd)
+{
+	int ret;
+	fprintf(stderr,"Dropping master \n");
+	ret = ioctl(fd, DRM_IOCTL_DROP_MASTER, 0);
+	return ret;
+}
diff --git a/libdrm/xf86drm.h b/libdrm/xf86drm.h
index 230f54c..e97c968 100644
--- a/libdrm/xf86drm.h
+++ b/libdrm/xf86drm.h
@@ -658,6 +658,9 @@ extern int  drmSLLookupNeighbors(void *l, unsigned long key,
 extern int drmOpenOnce(void *unused, const char *BusID, int *newlyopened);
 extern void drmCloseOnce(int fd);
 
+extern int drmSetMaster(int fd);
+extern int drmDropMaster(int fd);
+
 #include "xf86mm.h"
 
 #endif
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index dbf2a92..23bfeaf 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->master->lock.hw_lock->lock ) ||		\
+	     dev->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->master->lock.hw_lock->lock ),\
+			   dev->master->lock.file_priv, file_priv );		\
 		return -EINVAL;						\
 	}								\
 } while (0)
@@ -409,7 +409,6 @@ enum drm_ref_type {
 /** File private data */
 struct drm_file {
 	int authenticated;
-	int master;
 	int minor;
 	pid_t pid;
 	uid_t uid;
@@ -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;
 };
 
@@ -566,6 +566,7 @@ 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;
@@ -605,6 +606,25 @@ 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 */
+	/[EMAIL PROTECTED] */
+	struct drm_open_hash magiclist;
+	struct list_head magicfree;
+	/[EMAIL PROTECTED] */
+
+	struct drm_lock_data lock;		/**< Information on hardware lock */
+};
+
 /**
  * DRM driver structure. This structure represent the common code for
  * a family of cards. There will one drm_device for each card present
@@ -701,13 +721,9 @@ struct drm_head {
  */
 struct drm_device {
 	struct device dev;		/**< Linux 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 */
 	/[EMAIL PROTECTED] */
 	spinlock_t count_lock;		/**< For inuse, drm_device::open_count, drm_device::buf_use */
@@ -730,12 +746,6 @@ struct drm_device {
 	atomic_t counts[15];
 	/[EMAIL PROTECTED] */
 
-	/** \name Authentication */
-	/[EMAIL PROTECTED] */
-	struct list_head filelist;
-	struct drm_open_hash magiclist;
-	struct list_head magicfree;
-	/[EMAIL PROTECTED] */
 
 	/** \name Memory management */
 	/[EMAIL PROTECTED] */
@@ -756,7 +766,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;
 	/[EMAIL PROTECTED] */
 
 	/** \name DMA queues (contexts) */
@@ -768,6 +780,7 @@ struct drm_device {
 	struct drm_device_dma *dma;		/**< Optional pointer for DMA support */
 	/[EMAIL PROTECTED] */
 
+
 	/** \name Context support */
 	/[EMAIL PROTECTED] */
 	int irq;			/**< Interrupt used by board */
@@ -1126,7 +1139,15 @@ extern int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start);
 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 int drm_setmaster_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file_priv);
+extern int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file_priv);
+
+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 c904a91..8ccb199 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->master, auth->magic));
 		file_priv->magic = auth->magic;
-		drm_add_magic(dev, file_priv, auth->magic);
+		drm_add_magic(dev->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->master, auth->magic))) {
 		file->authenticated = 1;
-		drm_remove_magic(dev, auth->magic);
+		drm_remove_magic(dev->master, auth->magic);
 		return 0;
 	}
 	return -EINVAL;
diff --git a/linux-core/drm_bufs.c b/linux-core/drm_bufs.c
index 75c75c2..8106736 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->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->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->master->lock.hw_lock = map->handle;	/* Pointer to lock */
 		}
 		break;
 	case _DRM_AGP: {
@@ -318,6 +318,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->master;
 	*maplist = list;
 	return 0;
 }
diff --git a/linux-core/drm_context.c b/linux-core/drm_context.c
index 83ad291..175035d 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->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 343d5f3..166ffd7 100644
--- a/linux-core/drm_drv.c
+++ b/linux-core/drm_drv.c
@@ -76,6 +76,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),
@@ -166,7 +169,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;
@@ -183,12 +185,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);
 
@@ -198,22 +194,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->master) {
+		drm_put_master(dev->master);
+		dev->master = NULL;
 	}
-
-
+	
 	/* Clear AGP information */
 	if (drm_core_has_AGP(dev) && dev->agp) {
 		struct drm_agp_mem *entry, *tempe;
@@ -272,11 +257,13 @@ int drm_lastclose(struct drm_device * dev)
 	if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
 		drm_dma_takedown(dev);
 
+#if 0
 	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);
 	}
+#endif
 	dev->dev_mapping = NULL;
 	mutex_unlock(&dev->struct_mutex);
 
diff --git a/linux-core/drm_fops.c b/linux-core/drm_fops.c
index 0e1c486..0fb82ff 100644
--- a/linux-core/drm_fops.c
+++ b/linux-core/drm_fops.c
@@ -54,14 +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);
-	if (i != 0)
-		return i;
-
 	atomic_set(&dev->ioctl_count, 0);
 	atomic_set(&dev->vma_count, 0);
 	dev->buf_use = 0;
@@ -76,11 +68,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;
@@ -284,8 +273,17 @@ 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->master) {
+		priv->master = drm_get_master(dev);
+		if (!priv->master) {
+			ret = -ENOMEM;
+			goto out_free;
+		}
+		dev->master = priv->master;
+	} else
+		priv->master = NULL;
 
 	list_add(&priv->lhead, &dev->filelist);
 	mutex_unlock(&dev->struct_mutex);
@@ -392,23 +390,23 @@ int drm_release(struct inode *inode, struct file *filp)
 		  current->pid, (long)old_encode_dev(file_priv->head->device),
 		  dev->open_count);
 
-	if (dev->driver->reclaim_buffers_locked && dev->lock.hw_lock) {
+	if (dev->driver->reclaim_buffers_locked && dev->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->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->master->lock.spinlock);
+				locked = dev->master->lock.idle_has_lock;
+				spin_unlock(&dev->master->lock.spinlock);
 				if (locked)
 					break;
 				schedule();
@@ -421,24 +419,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->master->lock);
 		}
 	}
 
-	if (dev->driver->reclaim_buffers_idlelocked && dev->lock.hw_lock) {
+	if (dev->driver->reclaim_buffers_idlelocked && dev->master->lock.hw_lock) {
 
-		drm_idlelock_take(&dev->lock);
+		drm_idlelock_take(&dev->master->lock);
 		dev->driver->reclaim_buffers_idlelocked(dev, file_priv);
-		drm_idlelock_release(&dev->lock);
+		drm_idlelock_release(&dev->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->master->lock.hw_lock->lock));
 
-		drm_lock_free(&dev->lock,
-			      _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
+		drm_lock_free(&dev->master->lock,
+			      _DRM_LOCKING_CONTEXT(dev->master->lock.hw_lock->lock));
 	}
 
 
@@ -480,6 +478,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->master)
+			dev->master = NULL;
+		drm_put_master(file_priv->master);
+		file_priv->master = NULL;
+	}
+
 	mutex_unlock(&dev->struct_mutex);
 
 	if (dev->driver->postclose)
@@ -493,9 +499,8 @@ 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 3df163d..c575aff 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->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;
 }
@@ -82,35 +83,36 @@ int drm_setunique(struct drm_device *dev, void *data,
 {
 	struct drm_unique *u = data;
 	int domain, bus, slot, func, ret;
+	struct drm_master *master = dev->master;
 
-	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, "[EMAIL PROTECTED]", 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;
@@ -128,30 +130,31 @@ int drm_setunique(struct drm_device *dev, void *data,
 static int drm_set_busid(struct drm_device * dev)
 {
 	int len;
-	if (dev->unique != NULL)
+	struct drm_master *master = dev->master;
+	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, "[EMAIL PROTECTED]", dev->driver->pci_driver.name,
-		dev->unique);
+		master->unique);
 
 	return 0;
 }
@@ -275,7 +278,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->master->lock.hw_lock ? dev->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 314c232..faff89d 100644
--- a/linux-core/drm_irq.c
+++ b/linux-core/drm_irq.c
@@ -402,18 +402,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->master->lock,
 			   DRM_KERNEL_CONTEXT)) {
 		spin_unlock_irqrestore(&dev->tasklet_lock, irqflags);
 		return;
 	}
 
-	dev->lock.lock_time = jiffies;
+	dev->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->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 b8e4a5d..1b8c71a 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->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->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->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 3012c5b..61af9e5 100644
--- a/linux-core/drm_proc.c
+++ b/linux-core/drm_proc.c
@@ -176,10 +176,10 @@ static int drm_name_info(char *buf, char **start, off_t offset, int request,
 	*start = &buf[offset];
 	*eof = 0;
 
-	if (dev->unique) {
+	if (dev->master && dev->master->unique) {
 		DRM_PROC_PRINT("%s %s %s\n",
 			       dev->driver->pci_driver.name,
-			       pci_name(dev->pdev), dev->unique);
+			       pci_name(dev->pdev), dev->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 00a2452..2275076 100644
--- a/linux-core/drm_stub.c
+++ b/linux-core/drm_stub.c
@@ -54,6 +54,87 @@ struct drm_head **drm_heads;
 struct class *drm_class;
 struct proc_dir_entry *drm_proc_root;
 
+int drm_setmaster_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file_priv)
+{
+
+	if (!file_priv->master)
+		return -EINVAL;
+
+	if (dev->master == file_priv->master)
+		return 0;
+
+	DRM_DEBUG("%p %p\n", dev->master, file_priv->master);
+
+	/* TODO - busy wait until someone releases the master - bad plan
+ 	 * need a wait queue or a better plan */
+	while(dev->master)
+		schedule();
+
+	if (!dev->master && dev->master != file_priv->master)
+		dev->master = file_priv->master;
+	return 0;
+}
+
+int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv)
+{
+	if (!file_priv->master)
+		return -EINVAL;
+	DRM_DEBUG("%p\n", dev->master);
+	dev->master = NULL;
+	return 0;
+}
+
+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;
+
+	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;
+
+	DRM_DEBUG("%p\n", master);
+	return master;
+}
+
+void drm_put_master(struct drm_master *master)
+{
+	struct drm_magic_entry *pt, *next;
+	struct drm_device *dev = master->dev;
+
+	DRM_DEBUG("%p\n", 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)
@@ -68,7 +149,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);
@@ -286,11 +367,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/via_fence.c b/linux-core/via_fence.c
index 9af1bf3..e7f2fd0 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->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->master->lock);
 				dev_priv->have_idlelock = 0;
 			}
 			drm_fence_handler(dev, 0, dev_priv->emit_0_sequence,
diff --git a/shared-core/drm.h b/shared-core/drm.h
index 6f6f238..faf38dc 100644
--- a/shared-core/drm.h
+++ b/shared-core/drm.h
@@ -950,6 +950,9 @@ struct drm_mm_init_arg {
 #define DRM_IOCTL_SET_SAREA_CTX		DRM_IOW( 0x1c, struct drm_ctx_priv_map)
 #define DRM_IOCTL_GET_SAREA_CTX		DRM_IOWR(0x1d, struct drm_ctx_priv_map)
 
+#define DRM_IOCTL_SET_MASTER            DRM_IO(0x1e)
+#define DRM_IOCTL_DROP_MASTER           DRM_IO(0x1f)
+
 #define DRM_IOCTL_ADD_CTX		DRM_IOWR(0x20, struct drm_ctx)
 #define DRM_IOCTL_RM_CTX		DRM_IOWR(0x21, struct drm_ctx)
 #define DRM_IOCTL_MOD_CTX		DRM_IOW( 0x22, struct drm_ctx)
diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c
index 623576a..06ae975 100644
--- a/shared-core/radeon_state.c
+++ b/shared-core/radeon_state.c
@@ -3058,7 +3058,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;
+		value = (long)dev->master->lock.hw_lock;
 		break;
 #endif
 	case RADEON_PARAM_GART_TEX_HANDLE:
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
--
_______________________________________________
Dri-devel mailing list
Dri-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dri-devel

Reply via email to