[PATCH] config/udev: get driver suggestions from udev

Aaron Plattner aplattner at nvidia.com
Wed Oct 17 15:02:53 PDT 2012


If the udev device corresponding to a platform drm device has an "xorg_drivers"
property associated with it, treat that as a comma-separated list of driver
suggestions to use.  Otherwise, fall back to the existing PCI ID table.

This lets people create a udev rule to associate an X driver with a given drm
device using rules that look like this:

  SUBSYSTEM=="drm", DRIVERS=="i915", ENV{xorg_drivers}="intel"

Signed-off-by: Aaron Plattner <aplattner at nvidia.com>
---
 config/udev.c                       | 23 ++++++++++++++++++++---
 hw/xfree86/common/xf86platformBus.c | 20 +++++++++++++++++++-
 include/hotplug.h                   |  2 ++
 3 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/config/udev.c b/config/udev.c
index 454838f..43e8775 100644
--- a/config/udev.c
+++ b/config/udev.c
@@ -55,6 +55,7 @@ static struct udev_monitor *udev_monitor;
 #ifdef CONFIG_UDEV_KMS
 static Bool
 config_udev_odev_setup_attribs(const char *path, const char *syspath,
+                               const char *suggested_drivers,
                                config_odev_probe_proc_ptr probe_callback);
 #endif
 
@@ -94,13 +95,18 @@ device_added(struct udev_device *udev_device)
 #ifdef CONFIG_UDEV_KMS
     if (!strcmp(udev_device_get_subsystem(udev_device), "drm")) {
         const char *sysname = udev_device_get_sysname(udev_device);
+        const char *suggested_drivers;
 
         if (strncmp(sysname, "card", 4) != 0)
             return;
 
         LogMessage(X_INFO, "config/udev: Adding drm device (%s)\n", path);
 
-        config_udev_odev_setup_attribs(path, syspath, NewGPUDeviceRequest);
+        suggested_drivers = udev_device_get_property_value(udev_device,
+                                                           "xorg_drivers");
+
+        config_udev_odev_setup_attribs(path, syspath, suggested_drivers,
+                                       NewGPUDeviceRequest);
         return;
     }
 #endif
@@ -271,7 +277,7 @@ device_removed(struct udev_device *device)
         if (!path)
             return;
 
-        config_udev_odev_setup_attribs(path, syspath, DeleteGPUDeviceRequest);
+        config_udev_odev_setup_attribs(path, syspath, NULL, DeleteGPUDeviceRequest);
         return;
     }
 #endif
@@ -421,6 +427,7 @@ config_udev_fini(void)
 
 static Bool
 config_udev_odev_setup_attribs(const char *path, const char *syspath,
+                               const char *suggested_drivers,
                                config_odev_probe_proc_ptr probe_callback)
 {
     struct OdevAttributes *attribs = config_odev_allocate_attribute_list();
@@ -437,6 +444,13 @@ config_udev_odev_setup_attribs(const char *path, const char *syspath,
     if (ret == FALSE)
         goto fail;
 
+    if (suggested_drivers) {
+        ret = config_odev_add_attribute(attribs, ODEV_ATTRIB_SUGGESTED_DRIVERS,
+                                        suggested_drivers);
+        if (ret == FALSE)
+            goto fail;
+    }
+
     /* ownership of attribs is passed to probe layer */
     probe_callback(attribs);
     return TRUE;
@@ -471,6 +485,8 @@ config_udev_odev_probe(config_odev_probe_proc_ptr probe_callback)
         struct udev_device *udev_device = udev_device_new_from_syspath(udev, syspath);
         const char *path = udev_device_get_devnode(udev_device);
         const char *sysname = udev_device_get_sysname(udev_device);
+        const char *suggested_drivers =
+            udev_device_get_property_value(udev_device, "xorg_drivers");
 
         if (!path || !syspath)
             goto no_probe;
@@ -479,7 +495,8 @@ config_udev_odev_probe(config_odev_probe_proc_ptr probe_callback)
         else if (strncmp(sysname, "card", 4) != 0)
             goto no_probe;
 
-        config_udev_odev_setup_attribs(path, syspath, probe_callback);
+        config_udev_odev_setup_attribs(path, syspath, suggested_drivers,
+                                       probe_callback);
 
     no_probe:
         udev_device_unref(udev_device);
diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
index 0525e39..d48b48d 100644
--- a/hw/xfree86/common/xf86platformBus.c
+++ b/hw/xfree86/common/xf86platformBus.c
@@ -183,6 +183,7 @@ xf86PlatformMatchDriver(char *matches[], int nmatches)
 
     for (pass = 0; pass < 2; pass++) {
         for (i = 0; i < xf86_num_platform_devices; i++) {
+            const char *suggested_drivers;
 
             if (xf86IsPrimaryPlatform(&xf86_platform_devices[i]) && (pass == 1))
                 continue;
@@ -199,7 +200,24 @@ xf86PlatformMatchDriver(char *matches[], int nmatches)
                 /* find end of matches list */
             }
 
-            if ((info != NULL) && (j < nmatches)) {
+            /* see if the kernel suggested any drivers */
+            suggested_drivers =
+                xf86_get_platform_attrib(i, ODEV_ATTRIB_SUGGESTED_DRIVERS);
+            if (suggested_drivers) {
+                char *tmp = strdup(suggested_drivers);
+
+                if (tmp) {
+                    char *tok;
+                    for (tok = strtok(tmp, ","); tok && j < nmatches;
+                         tok = strtok(NULL, ",")) {
+                        matches[j++] = strdup(tok);
+                    }
+                    free(tmp);
+                }
+            }
+            else if ((info != NULL) && (j < nmatches)) {
+                /* use the PCI ID match table if no suggestions were provided by
+                 * the kernel driver */
                 j += xf86VideoPtrToDriverList(info, &(matches[j]), nmatches - j);
             }
         }
diff --git a/include/hotplug.h b/include/hotplug.h
index 2a95b45..6e89c51 100644
--- a/include/hotplug.h
+++ b/include/hotplug.h
@@ -61,6 +61,8 @@ config_odev_free_attributes(struct OdevAttributes *attribs);
 #define ODEV_ATTRIB_SYSPATH 2
 /* DRI-style bus id */
 #define ODEV_ATTRIB_BUSID 3
+/* Comma-separated list of X.Org drivers suggested by the kernel driver */
+#define ODEV_ATTRIB_SUGGESTED_DRIVERS 4
 
 typedef void (*config_odev_probe_proc_ptr)(struct OdevAttributes *attribs);
 void config_odev_probe(config_odev_probe_proc_ptr probe_callback);
-- 
1.7.12



More information about the xorg-devel mailing list