[Mesa-dev] [PATCH] loader: allow alternative methods for PCI identification.

Emil Velikov emil.l.velikov at gmail.com
Mon May 19 16:07:15 PDT 2014


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 <gtw at 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)
> 



More information about the mesa-dev mailing list