xserver: Branch 'master'

Thomas Hellstrom thomash at kemper.freedesktop.org
Mon Apr 16 18:32:55 EEST 2007


 hw/xfree86/dri/dri.c       |  504 +++++++++++++++++++++++++++++----------------
 hw/xfree86/dri/dri.h       |   18 +
 hw/xfree86/dri/dristruct.h |   24 ++
 hw/xfree86/dri/sarea.h     |    5 
 4 files changed, 380 insertions(+), 171 deletions(-)

New commits:
diff-tree 02d42f344ce020c9b84723671cb9c68d5c064933 (from b5823ea3e1ed5a0449d44da05165a46719dcf287)
Author: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
Date:   Mon Apr 16 17:24:53 2007 +0200

    Changes for single-entity multi-screen DRI.
    
    The entity (device) has a locking SAREA and a master file descriptor
    that optionally isn't closed between server generation.
    
    The locking SAREA contains the device hardware lock.
    Each DRI screen creates an new SAREA containing the drawable lock,
    drawable-and private info, the drawable SAREA.
    
    The first screen optionally shares its drawable SAREA with the
    device SAREA.
    
    Default is to close the master descriptor between server generations,
    and to share the drawable SAREA of the first screen with the device locking
    SAREA. Thus we should (hopefully) have full backwards compatibility.
    
    Mesa changes to support single-device multiple screens are pending.

diff --git a/hw/xfree86/dri/dri.c b/hw/xfree86/dri/dri.c
index 7bd07c0..35da8a6 100644
--- a/hw/xfree86/dri/dri.c
+++ b/hw/xfree86/dri/dri.c
@@ -43,6 +43,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include <string.h>
 #include <stdio.h>
 #include <sys/ioctl.h>
+#include <errno.h>
 
 #define NEED_REPLIES
 #define NEED_EVENTS
@@ -77,6 +78,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 extern Bool noPanoramiXExtension;
 #endif
 
+static int DRIEntPrivIndex = -1;
 static int DRIScreenPrivIndex = -1;
 static int DRIWindowPrivIndex = -1;
 static unsigned long DRIGeneration = 0;
@@ -112,18 +114,203 @@ DRIDrvMsg(int scrnIndex, MessageType typ
 }
 
 
+static void
+DRIOpenDRMCleanup(DRIEntPrivPtr pDRIEntPriv)
+{
+    if (pDRIEntPriv->pLSAREA != NULL) {
+	drmUnmap(pDRIEntPriv->pLSAREA, pDRIEntPriv->sAreaSize);
+	pDRIEntPriv->pLSAREA = NULL;
+    }
+    if (pDRIEntPriv->hLSAREA != 0) {
+	drmRmMap(pDRIEntPriv->drmFD, pDRIEntPriv->hLSAREA);
+    }
+    if (pDRIEntPriv->drmFD >= 0) {
+	drmClose(pDRIEntPriv->drmFD);
+	pDRIEntPriv->drmFD = 0;
+    }
+}
+
+int
+DRIMasterFD(ScrnInfoPtr pScrn)
+{
+    return DRI_ENT_PRIV(pScrn)->drmFD;
+}
+
+void *
+DRIMasterSareaPointer(ScrnInfoPtr pScrn)
+{
+    return DRI_ENT_PRIV(pScrn)->pLSAREA;
+}
+
+drm_handle_t
+DRIMasterSareaHandle(ScrnInfoPtr pScrn)
+{
+    return DRI_ENT_PRIV(pScrn)->hLSAREA;
+}
+
+
+Bool
+DRIOpenDRMMaster(ScrnInfoPtr pScrn,
+		 unsigned long sAreaSize,
+		 const char *busID,
+		 const char *drmDriverName)
+{
+    drmSetVersion saveSv, sv;
+    Bool drmWasAvailable;
+    DRIEntPrivPtr pDRIEntPriv;
+    DRIEntPrivRec tmp;
+    drmVersionPtr drmlibv;
+    int drmlibmajor, drmlibminor;
+    const char *openBusID;
+    int count;
+    int err;
+
+    if (DRIEntPrivIndex == -1)
+	DRIEntPrivIndex = xf86AllocateEntityPrivateIndex();
+
+    pDRIEntPriv = DRI_ENT_PRIV(pScrn);
+
+    if (pDRIEntPriv && pDRIEntPriv->drmFD != -1)
+	return TRUE;
+
+    drmWasAvailable = drmAvailable();
+
+    memset(&tmp, 0, sizeof(tmp));
+
+    /* Check the DRM lib version.
+     * drmGetLibVersion was not supported in version 1.0, so check for
+     * symbol first to avoid possible crash or hang.
+     */
+
+    drmlibmajor = 1;
+    drmlibminor = 0;
+    if (xf86LoaderCheckSymbol("drmGetLibVersion")) {
+	drmlibv = drmGetLibVersion(-1);
+	if (drmlibv != NULL) {
+	    drmlibmajor = drmlibv->version_major;
+	    drmlibminor = drmlibv->version_minor;
+	    drmFreeVersion(drmlibv);
+	}
+    }
+
+    /* Check if the libdrm can handle falling back to loading based on name
+     * if a busid string is passed.
+     */
+    openBusID = (drmlibmajor == 1 && drmlibminor >= 2) ? busID : NULL;
+
+    tmp.drmFD = -1;
+    sv.drm_di_major = 1;
+    sv.drm_di_minor = 1;
+    sv.drm_dd_major = -1;
+
+    saveSv = sv;
+    count = 10;
+    while (count--) {
+	tmp.drmFD = drmOpen(drmDriverName, openBusID);
+
+	if (tmp.drmFD < 0) {
+	    DRIDrvMsg(-1, X_ERROR, "[drm] drmOpen failed.\n");
+	    goto out_err;
+	}
+
+	err = drmSetInterfaceVersion(tmp.drmFD, &sv);
+
+	if (err != -EPERM)
+	    break;
+
+	sv = saveSv;
+	drmClose(tmp.drmFD);
+	tmp.drmFD = -1;
+	usleep(100000);
+    }
+
+    if (tmp.drmFD <= 0) {
+	DRIDrvMsg(-1, X_ERROR, "[drm] DRM was busy with another master.\n");
+	goto out_err;
+    }
+
+    if (!drmWasAvailable) {
+	DRIDrvMsg(-1, X_INFO,
+		  "[drm] loaded kernel module for \"%s\" driver.\n",
+		  drmDriverName);
+    }
+
+    if (err != 0) {
+	sv.drm_di_major = 1;
+	sv.drm_di_minor = 0;
+    }
+
+    DRIDrvMsg(-1, X_INFO, "[drm] DRM interface version %d.%d\n",
+	      sv.drm_di_major, sv.drm_di_minor);
+
+    if (sv.drm_di_major == 1 && sv.drm_di_minor >= 1)
+	err = 0;
+    else
+	err = drmSetBusid(tmp.drmFD, busID);
+
+    if (err) {
+	DRIDrvMsg(-1, X_ERROR, "[drm] Could not set DRM device bus ID.\n");
+	goto out_err;
+    }
+
+    /*
+     * Create a lock-containing sarea.
+     */
+
+    if (drmAddMap( tmp.drmFD, 0, sAreaSize, DRM_SHM,
+		   DRM_CONTAINS_LOCK, &tmp.hLSAREA) < 0) {
+        DRIDrvMsg(-1, X_INFO, "[drm] Could not create SAREA for DRM lock.\n");
+	tmp.hLSAREA = 0;
+	goto out_err;
+    }
+
+    if (drmMap( tmp.drmFD, tmp.hLSAREA, sAreaSize,
+		(drmAddressPtr)(&tmp.pLSAREA)) < 0) {
+        DRIDrvMsg(-1, X_INFO, "[drm] Mapping SAREA for DRM lock failed.\n");
+	tmp.pLSAREA = NULL;
+	goto out_err;
+    }
+
+    memset(tmp.pLSAREA, 0, sAreaSize);
+
+    /*
+     * Reserved contexts are handled by the first opened screen.
+     */
+
+    tmp.resOwner = NULL;
+
+    if (!pDRIEntPriv)
+	pDRIEntPriv = xnfcalloc(sizeof(*pDRIEntPriv), 1);
+
+    if (!pDRIEntPriv) {
+        DRIDrvMsg(-1, X_INFO, "[drm] Failed to allocate memory for "
+		  "DRM device.\n");
+	goto out_err;
+    }
+    *pDRIEntPriv = tmp;
+    xf86GetEntityPrivate((pScrn)->entityList[0],DRIEntPrivIndex)->ptr =
+	pDRIEntPriv;
+
+    DRIDrvMsg(-1, X_INFO, "[drm] DRM open master succeeded.\n");
+    return TRUE;
+
+  out_err:
+
+    DRIOpenDRMCleanup(&tmp);
+    return FALSE;
+}
+
+
 Bool
 DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD)
 {
     DRIScreenPrivPtr    pDRIPriv;
     drm_context_t *       reserved;
     int                 reserved_count;
-    int                 i, fd, drmWasAvailable;
+    int                 i;
     Bool                xineramaInCore = FALSE;
-    int                 err = 0;
-    char                *openbusid;
-    drmVersionPtr       drmlibv;
-    int                 drmlibmajor, drmlibminor, drmdimajor, drmdiminor;
+    DRIEntPrivPtr       pDRIEntPriv;
+    ScrnInfoPtr         pScrn = xf86Screens[pScreen->myNum];
 
     if (DRIGeneration != serverGeneration) {
 	if ((DRIScreenPrivIndex = AllocateScreenPrivateIndex()) < 0)
@@ -153,47 +340,12 @@ DRIScreenInit(ScreenPtr pScreen, DRIInfo
 	}
     }
 
-    drmWasAvailable = drmAvailable();
-
-    /* Check the DRM lib version.
-     * drmGetLibVersion was not supported in version 1.0, so check for
-     * symbol first to avoid possible crash or hang.
-     */
-    drmlibmajor = 1;
-    drmlibminor = 0;
-    if (xf86LoaderCheckSymbol("drmGetLibVersion")) {
-	drmlibv = drmGetLibVersion(-1);
-	if (drmlibv != NULL) {
-	    drmlibmajor = drmlibv->version_major;
-	    drmlibminor = drmlibv->version_minor;
-	    drmFreeVersion(drmlibv);
-	}
-    }
-
-    /* Check if the libdrm can handle falling back to loading based on name
-     * if a busid string is passed.
-     */
-    if (drmlibmajor == 1 && drmlibminor >= 2)
-	openbusid = pDRIInfo->busIdString;
-    else
-	openbusid = NULL;
-
-    /* Note that drmOpen will try to load the kernel module, if needed. */
-    fd = drmOpen(pDRIInfo->drmDriverName, openbusid);
-    if (fd < 0) {
-        /* failed to open DRM */
-        pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
-        DRIDrvMsg(pScreen->myNum, X_INFO,
-                  "[drm] drmOpen failed\n");
-        return FALSE;
-    }
+    if (!DRIOpenDRMMaster(pScrn, pDRIInfo->SAREASize,
+			  pDRIInfo->busIdString,
+			  pDRIInfo->drmDriverName))
+	return FALSE;
 
-    if (!drmWasAvailable) {
-       /* drmOpen loaded the kernel module, print a message to say so */
-       DRIDrvMsg(pScreen->myNum, X_INFO,
-                 "[drm] loaded kernel module for \"%s\" driver\n",
-                 pDRIInfo->drmDriverName);
-    }
+    pDRIEntPriv = DRI_ENT_PRIV(pScrn);
 
     pDRIPriv = (DRIScreenPrivPtr) xcalloc(1, sizeof(DRIScreenPrivRec));
     if (!pDRIPriv) {
@@ -202,7 +354,7 @@ DRIScreenInit(ScreenPtr pScreen, DRIInfo
     }
 
     pScreen->devPrivates[DRIScreenPrivIndex].ptr = (pointer) pDRIPriv;
-    pDRIPriv->drmFD = fd;
+    pDRIPriv->drmFD = pDRIEntPriv->drmFD;
     pDRIPriv->directRenderingSupport = TRUE;
     pDRIPriv->pDriverInfo = pDRIInfo;
     pDRIPriv->nrWindows = 0;
@@ -214,89 +366,54 @@ DRIScreenInit(ScreenPtr pScreen, DRIInfo
 
     pDRIPriv->grabbedDRILock = FALSE;
     pDRIPriv->drmSIGIOHandlerInstalled = FALSE;
+    *pDRMFD = pDRIPriv->drmFD;
 
-    if (drmlibmajor == 1 && drmlibminor >= 2) {
-	drmSetVersion sv;
+    if (pDRIEntPriv->sAreaGrabbed || pDRIInfo->allocSarea) {
 
-	/* Get the interface version, asking for 1.1. */
-	sv.drm_di_major = 1;
-	sv.drm_di_minor = 1;
-	sv.drm_dd_major = -1;
-	err = drmSetInterfaceVersion(pDRIPriv->drmFD, &sv);
-	if (err == 0) {
-	    drmdimajor = sv.drm_di_major;
-	    drmdiminor = sv.drm_di_minor;
-	} else {
-	    /* failure, so set it to 1.0.0. */
-	    drmdimajor = 1;
-	    drmdiminor = 0;
+	if (drmAddMap( pDRIPriv->drmFD,
+		       0,
+		       pDRIPriv->pDriverInfo->SAREASize,
+		       DRM_SHM,
+		       0,
+		       &pDRIPriv->hSAREA) < 0)
+	{
+	    pDRIPriv->directRenderingSupport = FALSE;
+	    pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
+	    drmClose(pDRIPriv->drmFD);
+	    DRIDrvMsg(pScreen->myNum, X_INFO,
+		      "[drm] drmAddMap failed\n");
+	    return FALSE;
 	}
-    }
-    else {
-	/* We can't check the DI DRM interface version, so set it to 1.0.0. */
-	drmdimajor = 1;
-	drmdiminor = 0;
-    }
-    DRIDrvMsg(pScreen->myNum, X_INFO,
-              "[drm] DRM interface version %d.%d\n", drmdimajor, drmdiminor);
-
-    /* If the interface minor number is 1.1, then we've opened a DRM device
-     * that already had the busid set through drmOpen.
-     */
-    if (drmdimajor == 1 && drmdiminor >= 1)
-	err = 0;
-    else
-	err = drmSetBusid(pDRIPriv->drmFD, pDRIPriv->pDriverInfo->busIdString);
-
-    if (err < 0) {
-	pDRIPriv->directRenderingSupport = FALSE;
-	pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
-	drmClose(pDRIPriv->drmFD);
-        DRIDrvMsg(pScreen->myNum, X_INFO,
-                  "[drm] drmSetBusid failed (%d, %s), %s\n",
-                  pDRIPriv->drmFD, pDRIPriv->pDriverInfo->busIdString, strerror(-err));
-	return FALSE;
-    }
-
-    *pDRMFD = pDRIPriv->drmFD;
-    DRIDrvMsg(pScreen->myNum, X_INFO,
-	      "[drm] created \"%s\" driver at busid \"%s\"\n",
-	      pDRIPriv->pDriverInfo->drmDriverName,
-	      pDRIPriv->pDriverInfo->busIdString);
+	DRIDrvMsg(pScreen->myNum, X_INFO,
+		  "[drm] added %d byte SAREA at %p\n",
+		  pDRIPriv->pDriverInfo->SAREASize, pDRIPriv->hSAREA);
 
-    if (drmAddMap( pDRIPriv->drmFD,
-		   0,
-		   pDRIPriv->pDriverInfo->SAREASize,
-		   DRM_SHM,
-		   DRM_CONTAINS_LOCK,
-		   &pDRIPriv->hSAREA) < 0)
-    {
-	pDRIPriv->directRenderingSupport = FALSE;
-	pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
-	drmClose(pDRIPriv->drmFD);
-        DRIDrvMsg(pScreen->myNum, X_INFO,
-                  "[drm] drmAddMap failed\n");
-	return FALSE;
+	/* Backwards compat. */
+	if (drmMap( pDRIPriv->drmFD,
+		    pDRIPriv->hSAREA,
+		    pDRIPriv->pDriverInfo->SAREASize,
+		    (drmAddressPtr)(&pDRIPriv->pSAREA)) < 0)
+	{
+	    pDRIPriv->directRenderingSupport = FALSE;
+	    pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
+	    drmClose(pDRIPriv->drmFD);
+	    DRIDrvMsg(pScreen->myNum, X_INFO,
+		      "[drm] drmMap failed\n");
+	    return FALSE;
+	}
+	DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] mapped SAREA %p to %p\n",
+		  pDRIPriv->hSAREA, pDRIPriv->pSAREA);
+	memset(pDRIPriv->pSAREA, 0, pDRIPriv->pDriverInfo->SAREASize);
+    } else {
+	DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] Using the DRM lock "
+		  "SAREA also for drawables.\n");
+	pDRIPriv->hSAREA = pDRIEntPriv->hLSAREA;
+	pDRIPriv->pSAREA = (XF86DRISAREAPtr) pDRIEntPriv->pLSAREA;
+	pDRIEntPriv->sAreaGrabbed = TRUE;
     }
-    DRIDrvMsg(pScreen->myNum, X_INFO,
-	      "[drm] added %d byte SAREA at %p\n",
-	      pDRIPriv->pDriverInfo->SAREASize, pDRIPriv->hSAREA);
 
-    if (drmMap( pDRIPriv->drmFD,
-		pDRIPriv->hSAREA,
-		pDRIPriv->pDriverInfo->SAREASize,
-		(drmAddressPtr)(&pDRIPriv->pSAREA)) < 0)
-    {
-	pDRIPriv->directRenderingSupport = FALSE;
-	pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
-	drmClose(pDRIPriv->drmFD);
-        DRIDrvMsg(pScreen->myNum, X_INFO,
-                  "[drm] drmMap failed\n");
-	return FALSE;
-    }
-    memset(pDRIPriv->pSAREA, 0, pDRIPriv->pDriverInfo->SAREASize);
-    DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] mapped SAREA %p to %p\n",
-	      pDRIPriv->hSAREA, pDRIPriv->pSAREA);
+    pDRIPriv->hLSAREA = pDRIEntPriv->hLSAREA;
+    pDRIPriv->pLSAREA = pDRIEntPriv->pLSAREA;
 
     if (drmAddMap( pDRIPriv->drmFD,
 		   (drm_handle_t)pDRIPriv->pDriverInfo->frameBufferPhysicalAddress,
@@ -316,22 +433,26 @@ DRIScreenInit(ScreenPtr pScreen, DRIInfo
     DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] framebuffer handle = %p\n",
 	      pDRIPriv->hFrameBuffer);
 
-				/* Add tags for reserved contexts */
-    if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD,
-					      &reserved_count))) {
-	int  i;
-	void *tag;
-
-	for (i = 0; i < reserved_count; i++) {
-	    tag = DRICreateContextPrivFromHandle(pScreen,
-						 reserved[i],
-						 DRI_CONTEXT_RESERVED);
-	    drmAddContextTag(pDRIPriv->drmFD, reserved[i], tag);
+    if (pDRIEntPriv->resOwner == NULL) {
+	pDRIEntPriv->resOwner = pScreen;
+
+	/* Add tags for reserved contexts */
+	if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD,
+						  &reserved_count))) {
+	    int  i;
+	    void *tag;
+
+	    for (i = 0; i < reserved_count; i++) {
+		tag = DRICreateContextPrivFromHandle(pScreen,
+						     reserved[i],
+						     DRI_CONTEXT_RESERVED);
+		drmAddContextTag(pDRIPriv->drmFD, reserved[i], tag);
+	    }
+	    drmFreeReservedContextList(reserved);
+	    DRIDrvMsg(pScreen->myNum, X_INFO,
+		      "[drm] added %d reserved context%s for kernel\n",
+		      reserved_count, reserved_count > 1 ? "s" : "");
 	}
-	drmFreeReservedContextList(reserved);
-	DRIDrvMsg(pScreen->myNum, X_INFO,
-		  "[drm] added %d reserved context%s for kernel\n",
-		  reserved_count, reserved_count > 1 ? "s" : "");
     }
 
     /* validate max drawable table entry set by driver */
@@ -349,6 +470,11 @@ DRIScreenInit(ScreenPtr pScreen, DRIInfo
 	pDRIPriv->pSAREA->drawableTable[i].flags = 0;
     }
 
+    pDRIPriv->pLockRefCount = &pDRIEntPriv->lockRefCount;
+    pDRIPriv->pLockingContext = &pDRIEntPriv->lockingContext;
+
+    pDRIEntPriv->refCount++;
+
     return TRUE;
 }
 
@@ -490,6 +616,9 @@ DRICloseScreen(ScreenPtr pScreen)
     DRIInfoPtr       pDRIInfo;
     drm_context_t *    reserved;
     int              reserved_count;
+    ScrnInfoPtr      pScrn = xf86Screens[pScreen->myNum];
+    DRIEntPrivPtr    pDRIEntPriv = DRI_ENT_PRIV(pScrn);
+    Bool closeMaster;
 
     if (pDRIPriv && pDRIPriv->directRenderingSupport) {
 
@@ -542,38 +671,55 @@ DRICloseScreen(ScreenPtr pScreen)
 	}
 
 				/* Remove tags for reserved contexts */
-	if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD,
+	if (pDRIEntPriv->resOwner == pScreen) {
+	    pDRIEntPriv->resOwner = NULL;
+
+	    if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD,
 						  &reserved_count))) {
-	    int  i;
+		int  i;
 
-	    for (i = 0; i < reserved_count; i++) {
-		DRIDestroyContextPriv(drmGetContextTag(pDRIPriv->drmFD,
-						       reserved[i]));
+		for (i = 0; i < reserved_count; i++) {
+		    DRIDestroyContextPriv(drmGetContextTag(pDRIPriv->drmFD,
+							   reserved[i]));
+		}
+		drmFreeReservedContextList(reserved);
+		DRIDrvMsg(pScreen->myNum, X_INFO,
+			  "[drm] removed %d reserved context%s for kernel\n",
+			  reserved_count, reserved_count > 1 ? "s" : "");
 	    }
-	    drmFreeReservedContextList(reserved);
-	    DRIDrvMsg(pScreen->myNum, X_INFO,
-		      "[drm] removed %d reserved context%s for kernel\n",
-		      reserved_count, reserved_count > 1 ? "s" : "");
 	}
 
 	/* Make sure signals get unblocked etc. */
 	drmUnlock(pDRIPriv->drmFD, pDRIPriv->myContext);
-	pDRIPriv->lockRefCount = 0;
-	DRIDrvMsg(pScreen->myNum, X_INFO,
-		  "[drm] unmapping %d bytes of SAREA %p at %p\n",
-		  pDRIInfo->SAREASize,
-		  pDRIPriv->hSAREA,
-		  pDRIPriv->pSAREA);
-	if (drmUnmap(pDRIPriv->pSAREA, pDRIInfo->SAREASize)) {
-	    DRIDrvMsg(pScreen->myNum, X_ERROR,
-		      "[drm] unable to unmap %d bytes"
-		      " of SAREA %p at %p\n",
+	pDRIPriv->pLockRefCount = NULL;
+	closeMaster = (--pDRIEntPriv->refCount == 0) &&
+	    !pDRIEntPriv->keepFDOpen;
+	if (closeMaster || pDRIPriv->hSAREA != pDRIEntPriv->hLSAREA) {
+	    DRIDrvMsg(pScreen->myNum, X_INFO,
+		      "[drm] unmapping %d bytes of SAREA %p at %p\n",
 		      pDRIInfo->SAREASize,
 		      pDRIPriv->hSAREA,
 		      pDRIPriv->pSAREA);
+	    if (drmUnmap(pDRIPriv->pSAREA, pDRIInfo->SAREASize)) {
+		DRIDrvMsg(pScreen->myNum, X_ERROR,
+			  "[drm] unable to unmap %d bytes"
+			  " of SAREA %p at %p\n",
+			  pDRIInfo->SAREASize,
+			  pDRIPriv->hSAREA,
+			  pDRIPriv->pSAREA);
+	    }
+	} else {
+	    pDRIEntPriv->sAreaGrabbed = FALSE;
 	}
 
-	drmClose(pDRIPriv->drmFD);
+	if (closeMaster || (pDRIEntPriv->drmFD != pDRIPriv->drmFD)) {
+	    drmClose(pDRIPriv->drmFD);
+	    if (pDRIEntPriv->drmFD == pDRIPriv->drmFD) {
+		DRIDrvMsg(pScreen->myNum, X_INFO,
+			  "[drm] Closed DRM master.\n");
+		pDRIEntPriv->drmFD = -1;
+	    }
+	}
 
 	xfree(pDRIPriv);
 	pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
@@ -2001,28 +2147,46 @@ void
 DRILock(ScreenPtr pScreen, int flags)
 {
     DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-    if(!pDRIPriv) return;
 
-    if (!pDRIPriv->lockRefCount)
-        DRM_LOCK(pDRIPriv->drmFD, pDRIPriv->pSAREA, pDRIPriv->myContext, flags);
-    pDRIPriv->lockRefCount++;
+    if(!pDRIPriv || !pDRIPriv->pLockRefCount) return;
+
+    if (!*pDRIPriv->pLockRefCount) {
+        DRM_LOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext, flags);
+	*pDRIPriv->pLockingContext = pDRIPriv->myContext;
+    } else if (*pDRIPriv->pLockingContext != pDRIPriv->myContext) {
+	DRIDrvMsg(pScreen->myNum, X_ERROR,
+		  "[DRI] Locking deadlock.\n"
+		  "\tAlready locked with context %d,\n"
+		  "\ttrying to lock with context %d.\n",
+		  pDRIPriv->pLockingContext,
+		  pDRIPriv->myContext);
+    }
+    (*pDRIPriv->pLockRefCount)++;
 }
 
 void
 DRIUnlock(ScreenPtr pScreen)
 {
     DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
-    if(!pDRIPriv) return;
 
-    if (pDRIPriv->lockRefCount > 0) {
-        pDRIPriv->lockRefCount--;
-    }
-    else {
-        ErrorF("DRIUnlock called when not locked\n");
+    if(!pDRIPriv || !pDRIPriv->pLockRefCount) return;
+
+    if (*pDRIPriv->pLockRefCount > 0) {
+	if (pDRIPriv->myContext != *pDRIPriv->pLockingContext) {
+	    DRIDrvMsg(pScreen->myNum, X_ERROR,
+		      "[DRI] Unlocking inconsistency:\n"
+		      "\tContext %d trying to unlock lock held by context %d\n",
+		      pDRIPriv->pLockingContext,
+		      pDRIPriv->myContext);
+	}
+	(*pDRIPriv->pLockRefCount)--;
+    } else {
+        DRIDrvMsg(pScreen->myNum, X_ERROR,
+		  "DRIUnlock called when not locked.\n");
         return;
     }
-    if (!pDRIPriv->lockRefCount)
-        DRM_UNLOCK(pDRIPriv->drmFD, pDRIPriv->pSAREA, pDRIPriv->myContext);
+    if (! *pDRIPriv->pLockRefCount)
+        DRM_UNLOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext);
 }
 
 void *
diff --git a/hw/xfree86/dri/dri.h b/hw/xfree86/dri/dri.h
index f65c571..a21338a 100644
--- a/hw/xfree86/dri/dri.h
+++ b/hw/xfree86/dri/dri.h
@@ -107,7 +107,7 @@ typedef struct {
  */
 
 #define DRIINFO_MAJOR_VERSION   5
-#define DRIINFO_MINOR_VERSION   1
+#define DRIINFO_MINOR_VERSION   2
 #define DRIINFO_PATCH_VERSION   0
 
 typedef struct {
@@ -176,9 +176,17 @@ typedef struct {
 
     /* New with DRI version 5.1.0 */
     void        (*ClipNotify)(ScreenPtr pScreen, WindowPtr *ppWin, int num);
+
+    /* New with DRI version 5.2.0 */
+    Bool                allocSarea;
+    Bool                keepFDOpen;
 } DRIInfoRec, *DRIInfoPtr;
 
 
+extern Bool DRIOpenDRMMaster(ScrnInfoPtr pScrn, unsigned long sAreaSize,
+			     const char *busID,
+			     const char *drmDriverName);
+
 extern Bool DRIScreenInit(ScreenPtr pScreen,
                           DRIInfoPtr pDRIInfo,
                           int *pDRMFD);
@@ -344,6 +352,14 @@ extern char *DRICreatePCIBusID(pciVideoP
 
 extern int drmInstallSIGIOHandler(int fd, void (*f)(int, void *, void *));
 extern int drmRemoveSIGIOHandler(int fd);
+extern int DRIMasterFD(ScrnInfoPtr pScrn);
+
+extern void *DRIMasterSareaPointer(ScrnInfoPtr pScrn);
+
+extern drm_handle_t DRIMasterSareaHandle(ScrnInfoPtr pScrn);
+
+
+
 #define _DRI_H_
 
 #endif
diff --git a/hw/xfree86/dri/dristruct.h b/hw/xfree86/dri/dristruct.h
index 9c42ff9..a3bac85 100644
--- a/hw/xfree86/dri/dristruct.h
+++ b/hw/xfree86/dri/dristruct.h
@@ -73,6 +73,11 @@ struct _DRIContextPrivRec
 #define DRI_SCREEN_PRIV_FROM_INDEX(screenIndex) ((DRIScreenPrivPtr) \
     (screenInfo.screens[screenIndex]->devPrivates[DRIScreenPrivIndex].ptr))
 
+#define DRI_ENT_PRIV(pScrn)  \
+    ((DRIEntPrivIndex < 0) ? \
+     NULL:		     \
+     ((DRIEntPrivPtr)(xf86GetEntityPrivate((pScrn)->entityList[0], \
+					   DRIEntPrivIndex)->ptr)))
 
 typedef struct _DRIScreenPrivRec
 {
@@ -103,6 +108,25 @@ typedef struct _DRIScreenPrivRec
     Bool		wrapped;
     Bool		windowsTouched;
     int			lockRefCount;
+    drm_handle_t        hLSAREA;      /* Handle to SAREA containing lock, for mapping */
+    XF86DRILSAREAPtr    pLSAREA;      /* Mapped pointer to SAREA containing lock */
+    int*                pLockRefCount;
+    int*                pLockingContext;
 } DRIScreenPrivRec, *DRIScreenPrivPtr;
 
+
+typedef struct _DRIEntPrivRec {
+    int drmFD;
+    Bool drmOpened;
+    Bool sAreaGrabbed;
+    drm_handle_t hLSAREA;
+    XF86DRILSAREAPtr pLSAREA;
+    unsigned long sAreaSize;
+    int lockRefCount;
+    int lockingContext;
+    ScreenPtr resOwner;
+    Bool keepFDOpen;
+    int refCount;
+} DRIEntPrivRec, *DRIEntPrivPtr;
+
 #endif /* DRI_STRUCT_H */
diff --git a/hw/xfree86/dri/sarea.h b/hw/xfree86/dri/sarea.h
index a0d6084..1528cc1 100644
--- a/hw/xfree86/dri/sarea.h
+++ b/hw/xfree86/dri/sarea.h
@@ -89,4 +89,9 @@ typedef struct _XF86DRISAREA {
     drm_context_t			dummy_context;
 } XF86DRISAREARec, *XF86DRISAREAPtr;
 
+typedef struct _XF86DRILSAREA  {
+    drmLock                     lock;
+    drmLock                     otherLocks[31];
+} XF86DRILSAREARec, *XF86DRILSAREAPtr;
+
 #endif



More information about the xorg-commit mailing list