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> v2: (Emil) - wrap hwdb code into loader_get_hwdb_driver_for_fd, introduce dummy function when udev is not present - pass the headers location as an argument to the script - printf vendor/device id in upper hex - add 20-dri-driver.hwdb* to .gitignore and CLEANFILES - note in the release notes that udev hwdb needs to be rebuild in the package post-install hook Signed-off-by: Emil Velikov <emil.l.veli...@gmail.com> --- configure.ac | 14 ++++++++++ docs/relnotes/10.2.html | 12 ++++++++ src/loader/.gitignore | 1 + src/loader/Makefile.am | 13 +++++++++ src/loader/dump-hwdb.sh | 29 +++++++++++++++++++ src/loader/loader.c | 74 +++++++++++++++++++++++++++++++++++++++++++------ 6 files changed, 135 insertions(+), 8 deletions(-) create mode 100644 src/loader/.gitignore create mode 100755 src/loader/dump-hwdb.sh diff --git a/configure.ac b/configure.ac index 8bf9b94..dfc9c02 100644 --- a/configure.ac +++ b/configure.ac @@ -777,6 +777,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/docs/relnotes/10.2.html b/docs/relnotes/10.2.html index 332c33a..1165850 100644 --- a/docs/relnotes/10.2.html +++ b/docs/relnotes/10.2.html @@ -53,6 +53,18 @@ TBD. <h2>Changes</h2> +<p> +Mesa now generates a hwdb that is used with udev. Normally <tt>make +install</tt> automatically updates the udev database, unless +<tt>DESTDIR</tt> is set. +</p> +<p> +Note: make sure that your package includes the following post-install command. +<pre> +udevadm hwdb --update +</pre> + + <ul> </ul> diff --git a/src/loader/.gitignore b/src/loader/.gitignore new file mode 100644 index 0000000..b2ba87a --- /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..96132d0 100644 --- a/src/loader/Makefile.am +++ b/src/loader/Makefile.am @@ -41,3 +41,16 @@ 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 $(top_srcdir)/include/pci_ids > $@-tmp && mv $@-tmp $@ + +CLEANFILES = \ + 20-dri-driver.hwdb* diff --git a/src/loader/dump-hwdb.sh b/src/loader/dump-hwdb.sh new file mode 100755 index 0000000..59ecc06 --- /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=$1/${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 + + gcc -E $pci_id_file | + 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 +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 46828df..3bc8d6a 100644 --- a/src/loader/loader.c +++ b/src/loader/loader.c @@ -203,6 +203,47 @@ udev_device_new_from_fd(struct udev *udev, int fd) return device; } +static char * +loader_get_hwdb_driver_for_fd(int fd) +{ + struct udev *udev; + struct udev_device *device, *parent; + UDEV_SYMBOL(struct udev *, udev_new, (void)); + UDEV_SYMBOL(struct udev_device *, udev_device_get_parent, + (struct udev_device *)); + UDEV_SYMBOL(const char *, udev_device_get_property_value, + (struct udev_device *, const char *)); + UDEV_SYMBOL(struct udev_device *, udev_device_unref, + (struct udev_device *)); + UDEV_SYMBOL(struct udev *, udev_unref, (struct udev *)); + const char *hwdb_driver; + char *driver = NULL; + + udev = udev_new(); + device = udev_device_new_from_fd(udev, fd); + if (device == NULL) + goto out_unref; + + parent = udev_device_get_parent(device); + if (parent == NULL) { + log_(_LOADER_WARNING, "MESA-LOADER: could not get parent device\n"); + goto out_device_unref; + } + + hwdb_driver = udev_device_get_property_value(parent, "DRI_DRIVER"); + if (hwdb_driver != NULL) { + driver = strdup(hwdb_driver); + } + +out_device_unref: + udev_device_unref(device); + +out_unref: + udev_unref(udev); + + return driver; +} + int loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id) { @@ -255,6 +296,12 @@ out: /* for radeon */ #include <radeon_drm.h> +char * +loader_get_hwdb_driver_for_fd(int fd) +{ + return NULL +} + int loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id) { @@ -321,6 +368,12 @@ loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id) #else +char * +loader_get_hwdb_driver_for_fd(int fd) +{ + return NULL +} + int loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id) { @@ -365,22 +418,27 @@ out: char * loader_get_driver_for_fd(int fd, unsigned int driver_types) { - int vendor_id, chip_id; + int vendor_id, chip_id = -1; char *driver = NULL; if (!driver_types) driver_types = _LOADER_GALLIUM | _LOADER_DRI; - if (!loader_get_pci_id_for_fd(fd, &vendor_id, &chip_id)) - return fallback_to_kernel_name(fd); + driver = loader_get_hwdb_driver_for_fd(fd); + if (driver == NULL) { + if (!loader_get_pci_id_for_fd(fd, &vendor_id, &chip_id)) + return fallback_to_kernel_name(fd); - if (driver == NULL) driver = lookup_driver_for_pci_id(vendor_id, chip_id, 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_DEBUG, "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; } -- 1.8.5.2 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev