[Mesa-dev] [PATCH v2] loader: Get driver name from udev hwdb when available

Kristian Høgsberg krh at bitplanet.net
Tue Feb 4 19:45:42 CET 2014


The udev hwdb is a mechanism for applying udev properties to devices at
hotplug time.  The hwdb text files are compiled into a binary database
that lets udev efficiently look up and apply properties to devices that
match a given modalias.

This patch exports the mesa PCI ID tables as hwdb files and extends the
loader code to try to look up the driver name from the DRI_DRIVER udev
property.  The benefits to this approach are:

 - No longer PCI specific, any device udev can match with a modalias can
   be assigned a DRI driver.

 - Available outside mesa; writing a DRI2 compatible generic DDX with
   glamor needs to know the DRI driver name to send to the client.

 - Can be overridden by custom udev rules.

Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
---

This v2 rewrites dump-hwdb in shell so we don't have to worry about
cross-compilation and host cc stuff.  One down-side to this is that we
duplicate the vendor id + driver name mapping from pci_id_driver_map.h,
but it's not a whole lot of duplication.

Eric, the install-data-hook is fine, it looks like this:

  [krh at tokamak loader]$ make install udevhwdbdir=$PWD/foo 
  ...
  gmake  install-data-hook
  test -z "" && udevadm hwdb --update
  Failure writing database /etc/udev/hwdb.bin: Permission denied
  gmake[2]: [install-data-hook] Error 1 (ignored)

and doesn't break make install otherwise.

Kristian


 configure.ac            | 14 ++++++++++++++
 src/loader/.gitignore   |  1 +
 src/loader/Makefile.am  | 11 +++++++++++
 src/loader/dump-hwdb.sh | 29 +++++++++++++++++++++++++++++
 src/loader/loader.c     | 33 +++++++++++++++++++++++++--------
 src/loader/loader.h     |  2 +-
 6 files changed, 81 insertions(+), 9 deletions(-)
 create mode 100644 src/loader/.gitignore
 create mode 100755 src/loader/dump-hwdb.sh

diff --git a/configure.ac b/configure.ac
index ba158e8..9bf27d4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -771,6 +771,20 @@ if test "x$have_libdrm" = xyes; then
 	DEFINES="$DEFINES -DHAVE_LIBDRM"
 fi
 
+# This /lib prefix does not change with 32/64 bits it's always /lib
+case "$prefix" in
+/usr) default_udevhwdbdir=/lib/udev/hwdb.d ;;
+NONE) default_udevhwdbdir=${ac_default_prefix}/lib/udev/hwdb.d ;;
+*)    default_udevhwdbdir=$prefix/lib/udev/hwdb.d ;;
+esac
+
+AC_ARG_WITH([udev-hwdb-dir],
+    [AS_HELP_STRING([--with-udev-hwdb-dir=DIR],
+        [directory for the udev hwdb @<:@/lib/udev/hwdb.d@:>@])],
+    [udevhwdbdir="$withval"],
+    [udevhwdbdir=$default_udevhwdbdir])
+AC_SUBST([udevhwdbdir])
+
 PKG_CHECK_MODULES([LIBUDEV], [libudev >= $LIBUDEV_REQUIRED],
                   have_libudev=yes, have_libudev=no)
 
diff --git a/src/loader/.gitignore b/src/loader/.gitignore
new file mode 100644
index 0000000..e11c470
--- /dev/null
+++ b/src/loader/.gitignore
@@ -0,0 +1 @@
+20-dri-driver.hwdb
diff --git a/src/loader/Makefile.am b/src/loader/Makefile.am
index bddf7ac..14c85d0 100644
--- a/src/loader/Makefile.am
+++ b/src/loader/Makefile.am
@@ -41,3 +41,14 @@ libloader_la_LIBADD = \
 endif
 
 libloader_la_SOURCES = $(LOADER_C_FILES)
+
+
+dist_udevhwdb_DATA = 20-dri-driver.hwdb
+
+# Update hwdb on installation. Do not bother if installing
+# in DESTDIR, since this is likely for packaging purposes.
+install-data-hook :
+	-test -z "$(DESTDIR)" && udevadm hwdb --update
+
+20-dri-driver.hwdb :
+	$(srcdir)/dump-hwdb.sh > $@-tmp && mv $@-tmp $@
diff --git a/src/loader/dump-hwdb.sh b/src/loader/dump-hwdb.sh
new file mode 100755
index 0000000..2034c75
--- /dev/null
+++ b/src/loader/dump-hwdb.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+set -e
+
+PROP_NAME=DRI_DRIVER
+
+while read vendor driver; do
+    pci_id_file=../../include/pci_ids/${driver}_pci_ids.h
+    if ! test -r $pci_id_file; then
+        printf "pci:v%08x*bc03*\n $PROP_NAME=$driver\n\n" $vendor
+        continue
+    fi
+
+    while IFS=' (,' read c id rest; do
+        test -z "$id" && continue
+        printf "pci:v%08xd%08x*\n $PROP_NAME=$driver\n\n" $vendor $id
+
+    done < $pci_id_file
+done <<EOF
+0x8086 i915
+0x8086 i965
+0x1002 radeon
+0x1002 r200
+0x1002 r300
+0x1002 r600
+0x1002 radeonsi
+0x10de nouveau
+0x15ad vmwgfx
+EOF
diff --git a/src/loader/loader.c b/src/loader/loader.c
index 626046a..6e4c9e7 100644
--- a/src/loader/loader.c
+++ b/src/loader/loader.c
@@ -143,7 +143,7 @@ udev_device_new_from_fd(struct udev *udev, int fd)
 }
 
 int
-loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id)
+loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id, char **driver)
 {
    struct udev *udev = NULL;
    struct udev_device *device = NULL, *parent;
@@ -156,8 +156,10 @@ loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id)
    UDEV_SYMBOL(struct udev_device *, udev_device_unref,
                (struct udev_device *));
    UDEV_SYMBOL(struct udev *, udev_unref, (struct udev *));
+   const char *hwdb_driver;
 
    *chip_id = -1;
+   *driver = NULL;
 
    udev = udev_new();
    device = udev_device_new_from_fd(udev, fd);
@@ -170,6 +172,12 @@ loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id)
       goto out;
    }
 
+   hwdb_driver = udev_device_get_property_value(parent, "DRI_DRIVER");
+   if (hwdb_driver != NULL) {
+      *driver = strdup(hwdb_driver);
+      goto out;
+   }
+
    pci_id = udev_device_get_property_value(parent, "PCI_ID");
    if (pci_id == NULL ||
        sscanf(pci_id, "%x:%x", vendor_id, chip_id) != 2) {
@@ -184,7 +192,7 @@ out:
    if (udev)
       udev_unref(udev);
 
-   return (*chip_id >= 0);
+   return (*driver != NULL) || (*chip_id >= 0);
 }
 
 #elif defined(ANDROID) && !defined(__NOT_HAVE_DRM_H)
@@ -195,11 +203,12 @@ out:
 #include <radeon_drm.h>
 
 int
-loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id)
+loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id, char **driver)
 {
    drmVersionPtr version;
 
    *chip_id = -1;
+   *driver = NULL;
 
    version = drmGetVersion(fd);
    if (!version) {
@@ -261,7 +270,7 @@ loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id)
 #else
 
 int
-loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id)
+loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id, char **driver)
 {
    return 0;
 }
@@ -310,7 +319,7 @@ loader_get_driver_for_fd(int fd, unsigned driver_types)
    if (!driver_types)
       driver_types = _LOADER_GALLIUM | _LOADER_DRI;
 
-   if (!loader_get_pci_id_for_fd(fd, &vendor_id, &chip_id)) {
+   if (!loader_get_pci_id_for_fd(fd, &vendor_id, &chip_id, &driver)) {
 
 #ifndef __NOT_HAVE_DRM_H
       /* fallback to drmGetVersion(): */
@@ -330,6 +339,9 @@ loader_get_driver_for_fd(int fd, unsigned driver_types)
       return driver;
    }
 
+   if (driver)
+      goto out;
+
    for (i = 0; driver_map[i].driver; i++) {
       if (vendor_id != driver_map[i].vendor_id)
          continue;
@@ -350,9 +362,14 @@ loader_get_driver_for_fd(int fd, unsigned driver_types)
    }
 
 out:
-   log_(driver ? _LOADER_DEBUG : _LOADER_WARNING,
-         "pci id for fd %d: %04x:%04x, driver %s\n",
-         fd, vendor_id, chip_id, driver);
+   if (driver && chip_id == -1) {
+      log_(_LOADER_INFO, "using driver %s from udev hwdb", driver);
+   } else {
+      log_(driver ? _LOADER_DEBUG : _LOADER_WARNING,
+           "pci id for fd %d: %04x:%04x, driver %s",
+           fd, vendor_id, chip_id, driver);
+   }
+
    return driver;
 }
 
diff --git a/src/loader/loader.h b/src/loader/loader.h
index dfd77ba..5771280 100644
--- a/src/loader/loader.h
+++ b/src/loader/loader.h
@@ -33,7 +33,7 @@
 #define _LOADER_GALLIUM      (1 << 1)
 
 int
-loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id);
+loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id, char **driver);
 
 char *
 loader_get_driver_for_fd(int fd, unsigned driver_types);
-- 
1.8.4.2



More information about the mesa-dev mailing list