[Mesa-dev] [PATCH 3/8] loader: Get driver name from udev hwdb when available
Emil Velikov
emil.l.velikov at gmail.com
Fri Feb 7 01:46:49 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>
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.velikov at 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
More information about the mesa-dev
mailing list