[RFC PATCH v2] xfree86: add a -gpu switch to select primary gpu

Maarten Lankhorst maarten.lankhorst at canonical.com
Wed Jun 12 07:03:53 PDT 2013


Well with the detection bug fixed, here's the patch in a slightly cleaned up form,
tested with nvidia and nouveau. :-)
8< ----
For obvious reasons probably not suitable to be upstreamed, but I'm looking for some feedback on this patch.
This allows some playing around with optimus, if you feel so inclined.

Xorg -gpu 0 would use the boot vga, Xorg -gpu 1 the first pci device that's not.
I was also considering adding support for platform names or device names, but that's not implemented here yet.
---
diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
index 91ec4c8..b9a1065 100644
--- a/hw/xfree86/common/xf86Init.c
+++ b/hw/xfree86/common/xf86Init.c
@@ -95,6 +95,9 @@ void (*xf86OSPMClose) (void) = NULL;
 #endif
 static Bool xorgHWOpenConsole = FALSE;
 
+int xf86gpu_idx = -1;
+const char *xf86gpu_name = NULL;
+
 /* Common pixmap formats */
 
 static PixmapFormatRec formats[MAXFORMATS] = {
@@ -1399,6 +1402,23 @@ ddxProcessArgument(int argc, char **argv, int i)
         xf86PointerName = argv[++i];
         return 2;
     }
+    if (!strcmp(argv[i], "-gpu")) {
+        char *ptr;
+        long idx;
+        CHECK_FOR_REQUIRED_ARGUMENT();
+
+        idx = strtol(argv[++i], &ptr, 10);
+
+        if (idx >= 0 && *argv[i] && !ptr[0]) {
+            xf86gpu_idx = idx;
+            xf86gpu_name = NULL;
+        } else if (strchr(argv[i], ':')) {
+            xf86gpu_idx = -1;
+            xf86gpu_name = argv[i];
+        } else
+            FatalError("Invalid argument passed for -gpu.\n");
+        return 2;
+    }
     if (!strcmp(argv[i], "-keyboard")) {
         CHECK_FOR_REQUIRED_ARGUMENT();
         xf86KeyboardName = argv[++i];
@@ -1507,6 +1527,7 @@ ddxUseMsg(void)
         ("-keyboard name         specify the core keyboard InputDevice name\n");
     ErrorF
         ("-pointer name          specify the core pointer InputDevice name\n");
+    ErrorF("-gpu <index|name>      select the primary gpu\n");
     ErrorF("-nosilk                disable Silken Mouse\n");
     ErrorF("-flipPixels            swap default black/white Pixel values\n");
 #ifdef XF86VIDMODE
diff --git a/hw/xfree86/common/xf86Priv.h b/hw/xfree86/common/xf86Priv.h
index 58cfe0a..a639fbd 100644
--- a/hw/xfree86/common/xf86Priv.h
+++ b/hw/xfree86/common/xf86Priv.h
@@ -96,6 +96,11 @@ extern _X_EXPORT RootWinPropPtr *xf86RegisteredPropertiesTable;
 
 extern ScrnInfoPtr *xf86GPUScreens;      /* List of pointers to ScrnInfoRecs */
 extern int xf86NumGPUScreens;
+
+extern int xf86gpu_idx;
+extern const char *xf86gpu_name;
+
+
 #ifndef DEFAULT_VERBOSE
 #define DEFAULT_VERBOSE		0
 #endif
diff --git a/hw/xfree86/common/xf86pciBus.c b/hw/xfree86/common/xf86pciBus.c
index 258988a..51a3b53 100644
--- a/hw/xfree86/common/xf86pciBus.c
+++ b/hw/xfree86/common/xf86pciBus.c
@@ -77,6 +77,10 @@ int pciSlotClaimed = 0;
     (((c) & 0x00ffff00) \
 	 == ((PCI_CLASS_DISPLAY << 16) | (PCI_SUBCLASS_DISPLAY_VGA << 8)))
 
+#define IS_3D(c) \
+    (((c) & 0x00ffff00) \
+	 == ((PCI_CLASS_DISPLAY << 16) | (PCI_SUBCLASS_DISPLAY_3D << 8)))
+
 static struct pci_slot_match xf86IsolateDevice = {
     PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0
 };
@@ -88,6 +92,7 @@ static struct pci_slot_match xf86IsolateDevice = {
 void
 xf86PciProbe(void)
 {
+    int primary_idx = -1;
     int i = 0, k;
     int num = 0;
     struct pci_device *info;
@@ -113,6 +118,7 @@ xf86PciProbe(void)
             if (primaryBus.type == BUS_NONE && pci_device_is_boot_vga(info)) {
                 primaryBus.type = BUS_PCI;
                 primaryBus.id.pci = info;
+                primary_idx = num - 1;
             }
             info->user_data = 0;
         }
@@ -128,10 +134,12 @@ xf86PciProbe(void)
             pci_device_cfg_read_u16(info, &command, 4);
 
             if ((command & PCI_CMD_MEM_ENABLE)
-                && ((num == 1) || IS_VGA(info->device_class))) {
+                && (num == 1 || IS_VGA(info->device_class) ||
+                    IS_3D(info->device_class))) {
                 if (primaryBus.type == BUS_NONE) {
                     primaryBus.type = BUS_PCI;
                     primaryBus.id.pci = info;
+                    primary_idx = i;
                 }
                 else {
                     xf86Msg(X_NOTICE,
@@ -142,6 +150,17 @@ xf86PciProbe(void)
         }
     }
 
+    if (xf86gpu_idx > 0 && primary_idx >= 0) {
+        if (xf86gpu_idx >= num)
+            FatalError("invalid -gpu %i specified devices, only %i cards found\n", xf86gpu_idx, num);
+
+        primaryBus.type = BUS_PCI;
+        if (xf86gpu_idx > primary_idx)
+            primaryBus.id.pci = xf86PciVideoInfo[xf86gpu_idx];
+        else
+            primaryBus.id.pci = xf86PciVideoInfo[xf86gpu_idx - 1];
+    }
+
     /* Print a summary of the video devices found */
     for (k = 0; k < num; k++) {
         const char *prim = " ";
@@ -153,7 +172,7 @@ xf86PciProbe(void)
             continue;
 
         if (xf86IsPrimaryPci(info))
-            prim = "*";
+            prim = xf86gpu_idx > 0 ? "o" : "*";
 
         xf86Msg(X_PROBED, "PCI:%s(%u:%u:%u:%u) %04x:%04x:%04x:%04x ", prim,
                 info->domain, info->bus, info->dev, info->func,
diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
index e368dee..2fb4694 100644
--- a/hw/xfree86/common/xf86platformBus.c
+++ b/hw/xfree86/common/xf86platformBus.c
@@ -131,7 +131,7 @@ xf86IsPrimaryPlatform(struct xf86_platform_device *plat)
     return ((primaryBus.type == BUS_PLATFORM) && (plat == primaryBus.id.plat));
 }
 
-static void
+static int
 platform_find_pci_info(struct xf86_platform_device *pd, char *busid)
 {
     struct pci_slot_match devmatch;
@@ -143,20 +143,22 @@ platform_find_pci_info(struct xf86_platform_device *pd, char *busid)
                  &devmatch.domain, &devmatch.bus, &devmatch.dev,
                  &devmatch.func);
     if (ret != 4)
-        return;
+        return 0;
 
     iter = pci_slot_match_iterator_create(&devmatch);
     info = pci_device_next(iter);
+    ret = 0;
     if (info) {
         pd->pdev = info;
         pci_device_probe(info);
         if (pci_device_is_boot_vga(info)) {
             primaryBus.type = BUS_PLATFORM;
             primaryBus.id.plat = pd;
+            ret = 1;
         }
     }
     pci_iterator_destroy(iter);
-
+    return ret;
 }
 
 static Bool
@@ -216,22 +219,46 @@ xf86PlatformMatchDriver(char *matches[], int nmatches)
 int
 xf86platformProbe(void)
 {
-    int i;
-    Bool pci = TRUE;
+    int i, primary_idx = 0;
 
     config_odev_probe(xf86PlatformDeviceProbe);
 
-    if (!xf86scanpci()) {
-        pci = FALSE;
-    }
+    if (!xf86scanpci())
+        return 0;
 
     for (i = 0; i < xf86_num_platform_devices; i++) {
         char *busid = xf86_get_platform_attrib(i, ODEV_ATTRIB_BUSID);
 
-        if (pci && (strncmp(busid, "pci:", 4) == 0)) {
-            platform_find_pci_info(&xf86_platform_devices[i], busid);
+        if (strncmp(busid, "pci:", 4) == 0) {
+            if (platform_find_pci_info(&xf86_platform_devices[i], busid))
+                primary_idx = i;
         }
     }
+
+    if (xf86gpu_idx > 0 &&
+        xf86gpu_idx < xf86_num_platform_devices) {
+        if (xf86gpu_idx <= primary_idx)
+            primaryBus.id.plat = &xf86_platform_devices[xf86gpu_idx - 1];
+        else
+            primaryBus.id.plat = &xf86_platform_devices[xf86gpu_idx];
+    }
+
+    for (i = 0; i < xf86_num_platform_devices; i++) {
+        const char *prim = " ";
+        Bool memdone = FALSE, iodone = FALSE;
+        struct xf86_platform_device *dev = &xf86_platform_devices[i];
+
+        if (xf86IsPrimaryPlatform(dev))
+            prim = xf86gpu_idx > 0 ? "o" : "*";
+
+        xf86Msg(X_PROBED, "[%s%i] %s %s %s %04x:%04x\n", prim, i,
+                xf86_get_platform_attrib(i, ODEV_ATTRIB_BUSID),
+                xf86_get_platform_attrib(i, ODEV_ATTRIB_PATH),
+                xf86_get_platform_attrib(i, ODEV_ATTRIB_SYSPATH),
+                dev->pdev ? dev->pdev->vendor_id : 0xffff,
+                dev->pdev ? dev->pdev->device_id : 0xffff);
+    }
+
     return 0;
 }
 
diff --git a/hw/xfree86/os-support/bus/xf86Pci.h b/hw/xfree86/os-support/bus/xf86Pci.h
index f69e55b..1183b7a 100644
--- a/hw/xfree86/os-support/bus/xf86Pci.h
+++ b/hw/xfree86/os-support/bus/xf86Pci.h
@@ -173,6 +173,7 @@
 /* 0x03 display subclasses */
 #define PCI_SUBCLASS_DISPLAY_VGA	0x00
 #define PCI_SUBCLASS_DISPLAY_XGA	0x01
+#define PCI_SUBCLASS_DISPLAY_3D		0x02
 #define PCI_SUBCLASS_DISPLAY_MISC	0x80
 
 /* 0x04 multimedia subclasses */



More information about the xorg-devel mailing list