loader: add optional /sys filesystem method for PCI identification.
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). Signed-off-by: Gary Wong <gtw@gnu.org> Acked-by: Emil Velikov <emil.l.velikov@gmail.com>
This commit is contained in:
parent
090c772b8a
commit
85b6f36ca5
36
configure.ac
36
configure.ac
|
@ -870,14 +870,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])
|
||||
|
@ -973,8 +980,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
|
||||
|
@ -1076,8 +1090,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
|
||||
|
@ -1252,8 +1266,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
|
||||
|
@ -1271,7 +1285,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=""
|
||||
|
@ -1560,9 +1574,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
|
||||
|
||||
|
@ -1843,8 +1857,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])
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
@ -340,6 +448,10 @@ loader_get_device_name_for_fd(int fd)
|
|||
#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 result;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue