On 15/05/14 05:39, Gary Wong wrote: > loader_get_pci_id_for_fd() and loader_get_device_name_for_fd() now attempt > all available strategies to identify the hardware, instead of conditionally > compiling in a single test. The existing libudev and DRM approaches have > been retained, and another simple alternative of looking up the answer in > the /sys filesystem (available on Linux) is added. > > This should assist Linux systems that mount /sys but do not include > libudev (Android?), give Mesa a fighting chance of running on systems > where libudev is uninstalled/inaccessible/broken at runtime, and provides > a hook where non-Linux systems (BSD?) could implement their own PCI > identification. > Hi Gary,
Are you trying to get mesa working under GNU Hurd ? IIRC Jonathan is able to get mesa working under OpenBSD and I would expect other non-linux platforms to just work(tm). Although with that said I may have broken Android (not sure if autohell detects is as a linux platform). As you can notice I'm not a huge fan of adding yet another way of retrieving the device/driver name although I would not object if you're willing to split this patch a bit, have the option off by default and fix bugs if/when they pop up :) Cheers, Emil > Signed-off-by: Gary Wong <g...@gnu.org> > --- > configure.ac | 51 ++++++++++++---- > src/loader/loader.c | 173 > +++++++++++++++++++++++++++++++++++++++++++++++----- > 2 files changed, 195 insertions(+), 29 deletions(-) > > diff --git a/configure.ac b/configure.ac > index d3e96de..fe572cd 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -818,13 +818,31 @@ fi > > case "$host_os" in > linux*) > - need_libudev=yes ;; > + need_pci_id=yes ;; > *) > - need_libudev=no ;; > + need_pci_id=no ;; > esac > > -PKG_CHECK_MODULES([LIBUDEV], [libudev >= $LIBUDEV_REQUIRED], > - have_libudev=yes, have_libudev=no) > +AC_ARG_ENABLE([libudev], > + [AS_HELP_STRING([--disable-libudev], > + [disable libudev PCI identification @<:@default=enabled on supported > platforms@:>@])], > + [attempt_libudev="$enableval"], > + [attempt_libudev=yes] > +) > + > +if test "x$attempt_libudev" = "xyes"; then > + PKG_CHECK_MODULES([LIBUDEV], [libudev >= $LIBUDEV_REQUIRED], > + have_libudev=yes, have_libudev=no) > +else > + have_libudev=no > +fi > + > +AC_ARG_ENABLE([sysfs], > + [AS_HELP_STRING([--disable-sysfs], > + [disable /sys PCI identification @<:@default=enabled on supported > platforms@:>@])], > + [have_sysfs="$enableval"], > + [have_sysfs=yes] > +) > > if test "x$enable_dri" = xyes; then > if test "$enable_static" = yes; then > @@ -910,8 +928,15 @@ xyesno) > ;; > esac > > +have_pci_id=no > if test "$have_libudev" = yes; then > DEFINES="$DEFINES -DHAVE_LIBUDEV" > + have_pci_id=yes > +fi > + > +if test "$have_sysfs" = yes; then > + DEFINES="$DEFINES -DHAVE_SYSFS" > + have_pci_id=yes > fi > > # This is outside the case (above) so that it is invoked even for non-GLX > @@ -1013,8 +1038,8 @@ if test "x$enable_dri" = xyes; then > DEFINES="$DEFINES -DHAVE_DRI3" > fi > > - if test "x$have_libudev" != xyes; then > - AC_MSG_ERROR([libudev-dev required for building DRI]) > + if test "x$have_pci_id" != xyes; then > + AC_MSG_ERROR([libudev-dev or sysfs required for building DRI]) > fi > > case "$host_cpu" in > @@ -1183,8 +1208,8 @@ if test "x$enable_gbm" = xauto; then > esac > fi > if test "x$enable_gbm" = xyes; then > - if test "x$need_libudev$have_libudev" = xyesno; then > - AC_MSG_ERROR([gbm requires udev >= $LIBUDEV_REQUIRED]) > + if test "x$need_pci_id$have_pci_id" = xyesno; then > + AC_MSG_ERROR([gbm requires udev >= $LIBUDEV_REQUIRED or sysfs]) > fi > > if test "x$enable_dri" = xyes; then > @@ -1202,7 +1227,7 @@ if test "x$enable_gbm" = xyes; then > fi > fi > AM_CONDITIONAL(HAVE_GBM, test "x$enable_gbm" = xyes) > -if test "x$need_libudev" = xyes; then > +if test "x$need_pci_id$have_libudev" = xyesyes; then > GBM_PC_REQ_PRIV="libudev >= $LIBUDEV_REQUIRED" > else > GBM_PC_REQ_PRIV="" > @@ -1491,9 +1516,9 @@ for plat in $egl_platforms; do > ;; > esac > > - case "$plat$need_libudev$have_libudev" in > + case "$plat$need_pci_id$have_pci_id" in > waylandyesno|drmyesno) > - AC_MSG_ERROR([cannot build $plat platform without udev > >= $LIBUDEV_REQUIRED]) ;; > + AC_MSG_ERROR([cannot build $plat platform without udev > >= $LIBUDEV_REQUIRED or sysfs]) ;; > esac > done > > @@ -1766,8 +1791,8 @@ gallium_require_llvm() { > > gallium_require_drm_loader() { > if test "x$enable_gallium_loader" = xyes; then > - if test "x$need_libudev$have_libudev" = xyesno; then > - AC_MSG_ERROR([Gallium drm loader requires libudev >= > $LIBUDEV_REQUIRED]) > + if test "x$need_pci_id$have_pci_id" = xyesno; then > + AC_MSG_ERROR([Gallium drm loader requires libudev >= > $LIBUDEV_REQUIRED or sysfs]) > fi > if test "x$have_libdrm" != xyes; then > AC_MSG_ERROR([Gallium drm loader requires libdrm >= > $LIBDRM_REQUIRED]) > diff --git a/src/loader/loader.c b/src/loader/loader.c > index 666d015..33e77b3 100644 > --- a/src/loader/loader.c > +++ b/src/loader/loader.c > @@ -71,6 +71,10 @@ > #include <assert.h> > #include <dlfcn.h> > #endif > +#ifdef HAVE_SYSFS > +#include <sys/stat.h> > +#include <sys/types.h> > +#endif > #include "loader.h" > > #ifndef __NOT_HAVE_DRM_H > @@ -113,8 +117,8 @@ udev_dlopen_handle(void) > udev_handle = dlopen("libudev.so.0", RTLD_LOCAL | RTLD_LAZY); > > if (!udev_handle) { > - log_(_LOADER_FATAL, "Couldn't dlopen libudev.so.1 or > libudev.so.0, " > - "driver detection may be broken.\n"); > + log_(_LOADER_WARNING, "Couldn't dlopen libudev.so.1 or " > + "libudev.so.0, driver detection may be broken.\n"); > } > } > } > @@ -122,16 +126,19 @@ udev_dlopen_handle(void) > return udev_handle; > } > > +static int dlcheck_failed; > + > static void * > -asserted_dlsym(void *dlopen_handle, const char *name) > +checked_dlsym(void *dlopen_handle, const char *name) > { > void *result = dlsym(dlopen_handle, name); > - assert(result); > + if (!result) > + dlcheck_failed = 1; > return result; > } > > #define UDEV_SYMBOL(ret, name, args) \ > - ret (*name) args = asserted_dlsym(udev_dlopen_handle(), #name); > + ret (*name) args = checked_dlsym(udev_dlopen_handle(), #name); > > > static inline struct udev_device * > @@ -142,6 +149,9 @@ udev_device_new_from_fd(struct udev *udev, int fd) > UDEV_SYMBOL(struct udev_device *, udev_device_new_from_devnum, > (struct udev *udev, char type, dev_t devnum)); > > + if (dlcheck_failed) > + return NULL; > + > if (fstat(fd, &buf) < 0) { > log_(_LOADER_WARNING, "MESA-LOADER: failed to stat fd %d\n", fd); > return NULL; > @@ -157,8 +167,8 @@ udev_device_new_from_fd(struct udev *udev, int fd) > return device; > } > > -int > -loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id) > +static int > +libudev_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id) > { > struct udev *udev = NULL; > struct udev_device *device = NULL, *parent; > @@ -174,6 +184,9 @@ loader_get_pci_id_for_fd(int fd, int *vendor_id, int > *chip_id) > > *chip_id = -1; > > + if (dlcheck_failed) > + return 0; > + > udev = udev_new(); > device = udev_device_new_from_fd(udev, fd); > if (!device) > @@ -201,16 +214,76 @@ out: > > return (*chip_id >= 0); > } > +#endif > + > +#if defined(HAVE_SYSFS) > +static int > +dev_node_from_fd(int fd, unsigned int *maj, unsigned int *min) > +{ > + struct stat buf; > + > + if (fstat(fd, &buf) < 0) { > + log_(_LOADER_WARNING, "MESA-LOADER: failed to stat fd %d\n", fd); > + return -1; > + } > > -#elif !defined(__NOT_HAVE_DRM_H) > + if (!S_ISCHR(buf.st_mode)) { > + log_(_LOADER_WARNING, "MESA-LOADER: fd %d not a character device\n", > fd); > + return -1; > + } > + > + *maj = major(buf.st_rdev); > + *min = minor(buf.st_rdev); > + > + return 0; > +} > > +static int > +sysfs_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id) > +{ > + unsigned int maj, min; > + FILE *f; > + char buf[ 0x40 ]; > + > + if (dev_node_from_fd(fd, &maj, &min) < 0) { > + *chip_id = -1; > + return 0; > + } > + > + snprintf( buf, sizeof buf, "/sys/dev/char/%d:%d/device/vendor", maj, min > ); > + if (!(f = fopen(buf, "r"))) { > + *chip_id = -1; > + return 0; > + } > + if (fscanf(f, "%x", vendor_id) != 1) { > + *chip_id = -1; > + fclose(f); > + return 0; > + } > + fclose(f); > + snprintf( buf, sizeof buf, "/sys/dev/char/%d:%d/device/device", maj, min > ); > + if (!(f = fopen(buf, "r"))) { > + *chip_id = -1; > + return 0; > + } > + if (fscanf(f, "%x", chip_id) != 1) { > + *chip_id = -1; > + fclose(f); > + return 0; > + } > + fclose(f); > + return 1; > +} > +#endif > + > +#if !defined(__NOT_HAVE_DRM_H) > /* for i915 */ > #include <i915_drm.h> > /* for radeon */ > #include <radeon_drm.h> > > -int > -loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id) > +static int > +drm_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id) > { > drmVersionPtr version; > > @@ -272,23 +345,33 @@ loader_get_pci_id_for_fd(int fd, int *vendor_id, int > *chip_id) > > return (*chip_id >= 0); > } > +#endif > > -#else > > int > loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id) > { > +#if HAVE_LIBUDEV > + if (libudev_get_pci_id_for_fd(fd, vendor_id, chip_id)) > + return 1; > +#endif > +#if HAVE_SYSFS > + if (sysfs_get_pci_id_for_fd(fd, vendor_id, chip_id)) > + return 1; > +#endif > +#if !defined(__NOT_HAVE_DRM_H) > + if (drm_get_pci_id_for_fd(fd, vendor_id, chip_id)) > + return 1; > +#endif > return 0; > } > > -#endif > - > > -char * > -loader_get_device_name_for_fd(int fd) > +#ifdef HAVE_LIBUDEV > +static char * > +libudev_get_device_name_for_fd(int fd) > { > char *device_name = NULL; > -#ifdef HAVE_LIBUDEV > struct udev *udev; > struct udev_device *device; > const char *const_device_name; > @@ -312,9 +395,67 @@ loader_get_device_name_for_fd(int fd) > out: > udev_device_unref(device); > udev_unref(udev); > + return device_name; > +} > #endif > + > + > +#if HAVE_SYSFS > +static char * > +sysfs_get_device_name_for_fd(int fd) > +{ > + char *device_name = NULL; > + unsigned int maj, min; > + FILE *f; > + char buf[ 0x40 ]; > + static const char match[ 9 ] = "\0DEVNAME="; > + int expected = 1; > + > + if (dev_node_from_fd(fd, &maj, &min) < 0) > + return NULL; > + > + snprintf( buf, sizeof buf, "/sys/dev/char/%d:%d/uevent", maj, min ); > + if (!(f = fopen(buf, "r"))) > + return NULL; > + > + while( expected < sizeof match ) { > + int c = getc(f); > + > + if (c == EOF) { > + fclose(f); > + return NULL; > + } else if (c == match[expected] ) > + expected++; > + else > + expected = 0; > + } > + > + if (!fgets(buf, sizeof buf, f)) > + device_name = NULL; > + else > + device_name = strdup(buf); > + > + fclose(f); > return device_name; > } > +#endif > + > + > +char * > +loader_get_device_name_for_fd(int fd) > +{ > + char *result; > + > +#if HAVE_LIBUDEV > + if ((result = libudev_get_device_name_for_fd(fd))) > + return result; > +#endif > +#if HAVE_SYSFS > + if ((result = sysfs_get_device_name_for_fd(fd))) > + return result; > +#endif > + return NULL; > +} > > char * > loader_get_driver_for_fd(int fd, unsigned driver_types) > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev