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 <k...@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@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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev