[Mesa-dev] [PATCH 6/8] loader: Switch loader to match modalias strings instead of PCI IDs
Emil Velikov
emil.l.velikov at gmail.com
Fri Feb 7 01:46:52 CET 2014
This lets us match any device on any bus, including platform devices.
Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
v2: (Emil)
- correctly handle chip_id = 0 devices under android
- fnmatch.h is only available under linux
- cleanup a few typos s/driver-map/modalias-map/
XXX:
- scons build is broken
Signed-off-by: Emil Velikov <emil.l.velikov at gmail.com>
---
include/pci_ids/pci_id_driver_map.h | 81 ----------------------------
src/loader/.gitignore | 1 +
src/loader/Makefile.am | 6 ++-
src/loader/Makefile.sources | 3 +-
src/loader/dump-hwdb.sh | 50 +++++++++++++-----
src/loader/loader.c | 102 +++++++++++++++++++++++++-----------
6 files changed, 114 insertions(+), 129 deletions(-)
delete mode 100644 include/pci_ids/pci_id_driver_map.h
diff --git a/include/pci_ids/pci_id_driver_map.h b/include/pci_ids/pci_id_driver_map.h
deleted file mode 100644
index db9e07f..0000000
--- a/include/pci_ids/pci_id_driver_map.h
+++ /dev/null
@@ -1,81 +0,0 @@
-#ifndef _PCI_ID_DRIVER_MAP_H_
-#define _PCI_ID_DRIVER_MAP_H_
-
-#include <stddef.h>
-
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-#endif
-
-#ifndef __IS_LOADER
-# error "Only include from loader.c"
-#endif
-
-static const int i915_chip_ids[] = {
-#define CHIPSET(chip, desc, name) chip,
-#include "pci_ids/i915_pci_ids.h"
-#undef CHIPSET
-};
-
-static const int i965_chip_ids[] = {
-#define CHIPSET(chip, family, name) chip,
-#include "pci_ids/i965_pci_ids.h"
-#undef CHIPSET
-};
-
-static const int r100_chip_ids[] = {
-#define CHIPSET(chip, name, family) chip,
-#include "pci_ids/radeon_pci_ids.h"
-#undef CHIPSET
-};
-
-static const int r200_chip_ids[] = {
-#define CHIPSET(chip, name, family) chip,
-#include "pci_ids/r200_pci_ids.h"
-#undef CHIPSET
-};
-
-static const int r300_chip_ids[] = {
-#define CHIPSET(chip, name, family) chip,
-#include "pci_ids/r300_pci_ids.h"
-#undef CHIPSET
-};
-
-static const int r600_chip_ids[] = {
-#define CHIPSET(chip, name, family) chip,
-#include "pci_ids/r600_pci_ids.h"
-#undef CHIPSET
-};
-
-static const int radeonsi_chip_ids[] = {
-#define CHIPSET(chip, name, family) chip,
-#include "pci_ids/radeonsi_pci_ids.h"
-#undef CHIPSET
-};
-
-static const int vmwgfx_chip_ids[] = {
-#define CHIPSET(chip, name, family) chip,
-#include "pci_ids/vmwgfx_pci_ids.h"
-#undef CHIPSET
-};
-
-static const struct {
- int vendor_id;
- const char *driver;
- const int *chip_ids;
- int num_chips_ids;
- unsigned driver_types;
-} driver_map[] = {
- { 0x8086, "i915", i915_chip_ids, ARRAY_SIZE(i915_chip_ids), _LOADER_DRI | _LOADER_GALLIUM },
- { 0x8086, "i965", i965_chip_ids, ARRAY_SIZE(i965_chip_ids), _LOADER_DRI | _LOADER_GALLIUM },
- { 0x1002, "radeon", r100_chip_ids, ARRAY_SIZE(r100_chip_ids), _LOADER_DRI },
- { 0x1002, "r200", r200_chip_ids, ARRAY_SIZE(r200_chip_ids), _LOADER_DRI },
- { 0x1002, "r300", r300_chip_ids, ARRAY_SIZE(r300_chip_ids), _LOADER_GALLIUM },
- { 0x1002, "r600", r600_chip_ids, ARRAY_SIZE(r600_chip_ids), _LOADER_GALLIUM },
- { 0x1002, "radeonsi", radeonsi_chip_ids, ARRAY_SIZE(radeonsi_chip_ids), _LOADER_GALLIUM},
- { 0x10de, "nouveau", NULL, -1, _LOADER_GALLIUM },
- { 0x15ad, "vmwgfx", vmwgfx_chip_ids, ARRAY_SIZE(vmwgfx_chip_ids), _LOADER_GALLIUM },
- { 0x0000, NULL, NULL, 0 },
-};
-
-#endif /* _PCI_ID_DRIVER_MAP_H_ */
diff --git a/src/loader/.gitignore b/src/loader/.gitignore
index b2ba87a..3289ee9 100644
--- a/src/loader/.gitignore
+++ b/src/loader/.gitignore
@@ -1 +1,2 @@
20-dri-driver.hwdb*
+modalias-map.h*
diff --git a/src/loader/Makefile.am b/src/loader/Makefile.am
index 96132d0..f850caa 100644
--- a/src/loader/Makefile.am
+++ b/src/loader/Makefile.am
@@ -42,6 +42,9 @@ endif
libloader_la_SOURCES = $(LOADER_C_FILES)
+modalias-map.h :
+ $(srcdir)/dump-hwdb.sh $(top_srcdir)/include/pci_ids modalias-map > $@-tmp && mv $@-tmp $@
+
dist_udevhwdb_DATA = 20-dri-driver.hwdb
# Update hwdb on installation. Do not bother if installing
@@ -53,4 +56,5 @@ install-data-hook :
$(srcdir)/dump-hwdb.sh $(top_srcdir)/include/pci_ids > $@-tmp && mv $@-tmp $@
CLEANFILES = \
- 20-dri-driver.hwdb*
+ 20-dri-driver.hwdb* \
+ modalias-map.h*
diff --git a/src/loader/Makefile.sources b/src/loader/Makefile.sources
index 51a64ea..78ed204 100644
--- a/src/loader/Makefile.sources
+++ b/src/loader/Makefile.sources
@@ -1,2 +1,3 @@
LOADER_C_FILES := \
- loader.c
\ No newline at end of file
+ loader.c \
+ modalias-map.h
\ No newline at end of file
diff --git a/src/loader/dump-hwdb.sh b/src/loader/dump-hwdb.sh
index 59ecc06..f933764 100755
--- a/src/loader/dump-hwdb.sh
+++ b/src/loader/dump-hwdb.sh
@@ -2,21 +2,20 @@
set -e
-PROP_NAME=DRI_DRIVER
+function modalias_list() {
+ while read vendor driver; do
+ pci_id_file=$1/${driver}_pci_ids.h
+ if ! test -r $pci_id_file; then
+ printf "$driver pci:v%08X*bc03*\n" $vendor
+ continue
+ fi
-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
+ gcc -E $pci_id_file |
+ while IFS=' (,' read c id rest; do
+ test -z "$id" && continue
+ printf "$driver pci:v%08Xd%08X*\n" $vendor $id
+ done
+ done <<EOF
0x8086 i915
0x8086 i965
0x1002 radeon
@@ -27,3 +26,26 @@ done <<EOF
0x10de nouveau
0x15ad vmwgfx
EOF
+}
+
+case $2 in
+ hwdb)
+ modalias_list $1 | while read driver modalias; do
+ printf "$modalias\n PCI_DRIVER=$driver\n\n"
+ done
+ ;;
+
+ modalias-map)
+ printf "#define NUL \"\\\\0\"\n"
+ printf "static const char modalias_map[] =\n"
+ modalias_list $1 | while read driver modalias; do
+ printf "\t\"$modalias\" NUL \"$driver\" NUL\n"
+ done
+ printf "\tNUL;\n"
+ printf "#undef NUL\n"
+ ;;
+
+ *)
+ echo "usage: $0 headers-location hwdb | modalias-map"
+ ;;
+esac
diff --git a/src/loader/loader.c b/src/loader/loader.c
index db14a74..cbb501d 100644
--- a/src/loader/loader.c
+++ b/src/loader/loader.c
@@ -67,6 +67,9 @@
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
+#if defined(__linux__)
+#include <fnmatch.h>
+#endif
#ifdef HAVE_LIBUDEV
#include <assert.h>
#include <dlfcn.h>
@@ -77,8 +80,7 @@
#include <xf86drm.h>
#endif
-#define __IS_LOADER
-#include "pci_ids/pci_id_driver_map.h"
+#include "modalias-map.h"
static void default_logger(int level, const char *fmt, ...)
{
@@ -93,35 +95,24 @@ static void default_logger(int level, const char *fmt, ...)
static void (*log_)(int level, const char *fmt, ...) = default_logger;
static char *
-lookup_driver_for_pci_id(int vendor_id, int chip_id, unsigned int driver_types)
+lookup_driver_for_modalias(const char *modalias)
{
- int i, j;
-
- for (i = 0; driver_map[i].driver; i++) {
- if (vendor_id != driver_map[i].vendor_id)
- continue;
-
- if (!(driver_types & driver_map[i].driver_types))
- continue;
-
- if (driver_map[i].num_chips_ids == -1)
- goto out;
+ const char *m, *d;
+ char *driver = NULL;
- for (j = 0; j < driver_map[i].num_chips_ids; j++)
- if (driver_map[i].chip_ids[j] == chip_id)
- goto out;
+ for (m = modalias_map; *m; m = d + strlen(d) + 1) {
+ d = m + strlen(m) + 1;
+ if (fnmatch(m, modalias, FNM_NOESCAPE) == 0) {
+ driver = strdup(d);
+ break;
+ }
}
- out:
- if (driver_map[i].driver) {
+ if (driver)
log_(_LOADER_DEBUG,
- "pci id: %04x:%04x, driver %s from internal db",
- vendor_id, chip_id, driver_map[i].driver);
+ "using driver %s for %s from internal db", driver, modalias);
- return strdup(driver_map[i].driver);
- }
-
- return NULL;
+ return driver;
}
static char *
@@ -299,22 +290,63 @@ out:
return (*chip_id >= 0);
}
+int
+loader_get_modalias_for_fd(int fd)
+{
+ struct udev *udev;
+ struct udev_device *device, *parent;
+ const char *modalias;
+ 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 *));
+
+ 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;
+ }
+
+ modalias = udev_device_get_sysattr_value(parent, "modalias");
+ if (modalias == NULL)
+ log_(_LOADER_WARNING, "MESA-LOADER: cannot retrieve device modalias\n");
+ }
+
+out_device_unref:
+ udev_device_unref(device);
+
+out_unref:
+ udev_unref(udev);
+
+ return modalias;
+}
+
char *
loader_get_driver_for_fd(int fd, unsigned int driver_types)
{
int vendor_id, chip_id = -1;
- char *driver = NULL;
+ char *driver, *modalias;
if (!driver_types)
driver_types = _LOADER_GALLIUM | _LOADER_DRI;
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);
-
- driver = lookup_driver_for_pci_id(vendor_id, chip_id, driver_types);
+ if (driver == NULL)
+ modalias = loader_get_modalias_for_fd(fd);
+ if (modalias != NULL)
+ driver = lookup_driver_for_modalias(modalias);
}
+ if (driver == NULL)
+ driver = fallback_to_kernel_name(fd);
if (driver == NULL)
log_(_LOADER_WARNING, "no driver %s for %d\n", fd);
@@ -403,6 +435,7 @@ char *
loader_get_driver_for_fd(int fd, unsigned int driver_types)
{
int vendor_id, chip_id;
+ char modalias[32];
if (!driver_types)
driver_types = _LOADER_GALLIUM | _LOADER_DRI;
@@ -410,7 +443,12 @@ loader_get_driver_for_fd(int fd, unsigned int driver_types)
if (!loader_get_pci_id_for_fd(fd, &vendor_id, &chip_id))
return fallback_to_kernel_name(fd);
- return lookup_driver_for_pci_id(vendor_id, chip_id, driver_types);
+ if (chip_id != 0)
+ snprintf(modalias, sizeof(modalias), "pci:v%08Xd%08X", vendor_id, chip_id);
+ else
+ snprintf(modalias, sizeof(modalias), "pci:v%08X", vendor_id);
+
+ return lookup_driver_for_modalias(modalias);
}
#else
--
1.8.5.2
More information about the mesa-dev
mailing list