On 22/05/14 05:01, Gary Wong wrote: > Introduce a simple PCI identification method of looking up the answer > the /sys filesystem (available on Linux). Attempted after libudev, but > before DRM. > > Disabled by default (available only when the --enable-sysfs configure > option is specified). > Imo the sysfs_get_device_name_for_fd() function looks rather messy, but luckily most people will never hit it so :)
With that said, this patch is Acked-by: Emil Velikov <emil.l.veli...@gmail.com> I will give it a week or so for other people to chip in before pushing these to master. Thanks for your contribution. Emil P.S. If you use --in-reply-to, --chain-reply-to you'll have greater chances of patches not getting lost :) > Signed-off-by: Gary Wong <g...@gnu.org> > --- > configure.ac | 36 +++++++++++------ > src/loader/loader.c | 112 > ++++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 137 insertions(+), 11 deletions(-) > > diff --git a/configure.ac b/configure.ac > index 4e4d761..95f0e16 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -818,14 +818,21 @@ 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([sysfs], > + [AS_HELP_STRING([--enable-sysfs], > + [enable /sys PCI identification @<:@default=disabled@:>@])], > + [have_sysfs="$enableval"], > + [have_sysfs=no] > +) > + > if test "x$enable_dri" = xyes; then > if test "$enable_static" = yes; then > AC_MSG_ERROR([Cannot use static libraries for DRI drivers]) > @@ -910,8 +917,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 +1027,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 +1197,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 +1216,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 +1505,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 +1780,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 52be706..0f26265 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 > @@ -212,6 +216,66 @@ out: > } > #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; > + } > + > + 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> > @@ -291,6 +355,10 @@ loader_get_pci_id_for_fd(int fd, int *vendor_id, int > *chip_id) > 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; > @@ -332,6 +400,46 @@ out: > #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; > + } > + > + strcpy(buf, "/dev/"); > + if (fgets(buf + 5, sizeof(buf) - 5, f)) > + device_name = strdup(buf); > + > + fclose(f); > + return device_name; > +} > +#endif > + > + > char * > loader_get_device_name_for_fd(int fd) > { > @@ -341,6 +449,10 @@ loader_get_device_name_for_fd(int fd) > 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 result; > } > > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev