diff mbox

[v2,0/7] xfree86: Handle drm race condition

Message ID 514837A6.5010301@canonical.com (mailing list archive)
State New, archived
Headers show

Commit Message

Maarten Lankhorst March 19, 2013, 10:02 a.m. UTC
Hey,

Op 19-03-13 10:21, Chris Wilson schreef:
> On Mon, Mar 18, 2013 at 01:51:44PM -0700, Bryce Harrington wrote:
>> Update:  Squashes a couple commits to avoid potential hang if
>> git bisecting.  No other changes from v1.
> I'd probably drop the last EAGAIN patch as that is part of the libdrm
> API, but other than that it looks to be a reasonably self-contained w/a
> for this perplexing problem.
>
> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
> -Chris
>
And completely wrong, version I pushed to ubuntu's xorg-server for comparison:

>8--

Nacked-by: Maarten Lankhorst <maarten.lankhorst@canonical.com>
diff mbox

Patch

--- a/hw/xfree86/os-support/linux/lnx_platform.c
+++ b/hw/xfree86/os-support/linux/lnx_platform.c
@@ -7,6 +7,7 @@ 
 #include <xf86drm.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <errno.h>
 
 /* Linux platform device support */
 #include "xf86_OSproc.h"
@@ -17,23 +18,54 @@ 
 
 #include "hotplug.h"
 
+static Bool get_drm_master(int fd)
+{
+    int ret, tries = 400;
+
+    LogMessage(X_INFO, "spinning!\n");
+
+    while (tries--) {
+        if (drmSetMaster(fd) >= 0)
+            return TRUE;
+
+        if (errno != EINVAL)
+            break;
+
+        usleep(10000);
+    }
+    return FALSE;
+}
+
 static Bool
 get_drm_info(struct OdevAttributes *attribs, char *path)
 {
     drmSetVersion sv;
     char *buf;
     int fd;
+    int err = 0;
 
     fd = open(path, O_RDWR, O_CLOEXEC);
     if (fd == -1)
         return FALSE;
 
-    sv.drm_di_major = 1;
-    sv.drm_di_minor = 4;
-    sv.drm_dd_major = -1;       /* Don't care */
-    sv.drm_dd_minor = -1;       /* Don't care */
-    if (drmSetInterfaceVersion(fd, &sv)) {
-        ErrorF("setversion 1.4 failed\n");
+    while (1) {
+        sv.drm_di_major = 1;
+        sv.drm_di_minor = 4;
+        sv.drm_dd_major = -1;       /* Don't care */
+        sv.drm_dd_minor = -1;       /* Don't care */
+
+        err = drmSetInterfaceVersion(fd, &sv);
+        if (!err)
+            break;
+
+        if (err == -EACCES) {
+            if (get_drm_master(fd))
+                continue;
+            ErrorF("drmSetMaster failed with -%i(%m)\n", errno);
+        } else
+            ErrorF("drmSetInterfaceVersion failed with %i(%s)\n", err, strerror(-err));
+
+        close(fd);
         return FALSE;
     }