[Mesa-dev] [PATCH 2/2] loader: add optional /sys filesystem method for PCI identification.
Emil Velikov
emil.l.velikov at gmail.com
Wed May 21 11:46:52 PDT 2014
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 <gtw at 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;
> }
>
>
More information about the mesa-dev
mailing list