On 21/05/14 02:40, 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). >
Gary does uevent provide the full device path on your system ? Can you please keep the code style similar to the rest of the file - no space around [] and () - use sizeof(bla) - (pedantic) snprintf can fail/truncate. - empty lines with whitespace > Signed-off-by: Gary Wong <g...@gnu.org> > --- > configure.ac | 51 ++++++++++++++++++------ > src/loader/loader.c | 113 > ++++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 151 insertions(+), 13 deletions(-) > > diff --git a/configure.ac b/configure.ac > index 4e4d761..6b708dc 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@:>@])], ^^^^ Not strictly correct. I would just go with "auto" > + [attempt_libudev="$enableval"], > + [attempt_libudev=yes] [enable_libudev="$enableval"], [enable_libudev=auto] The above is more consistent with the mayhem that our current configure.ac :) > +) > + > +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([--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 > @@ -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 d8246e8..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 > @@ -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,47 @@ out: > #endif > > > +#if HAVE_SYSFS > +static char * > +sysfs_get_device_name_for_fd(int fd) > +{ On my linux system this approach returns "dri/card0" only. Whereas it should produce "/dev/dri/card0". > + 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; > + } The above indentation looks funky - please use spaces. > + > + if (!fgets(buf, sizeof buf, f)) > + device_name = NULL; > + else > + device_name = strdup(buf); > + device_name is already NULL. if (fgets(buf, sizeof(buf), f)) device_name = strdup(buf); -Emil > + fclose(f); > + return device_name; > +} > +#endif > + > + > char * > loader_get_device_name_for_fd(int fd) > { > @@ -341,6 +450,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 NULL; > } > > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev