Re: initial multi-master support for the drm..

2008-01-02 Thread Alan Cox
> Interrupt handler - userspace plays with the irq lines, I think we could 
> have issues getting interrupts when we have no master.

Undoubtedly - PCI interrupts are asynchronous to the other busses and can
turn up suprisingly late. It ought to be sufficient to clear the IRQ
cause kernel side and provide a way to pass it (or fake it ;)) to the new
master the moment it attaches.


-
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse012070mrt/direct/01/
--
___
Dri-devel mailing list
Dri-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dri-devel


initial multi-master support for the drm..

2008-01-01 Thread Dave Airlie

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