diff options
Diffstat (limited to 'mesalib/src/loader/loader.c')
-rw-r--r-- | mesalib/src/loader/loader.c | 86 |
1 files changed, 72 insertions, 14 deletions
diff --git a/mesalib/src/loader/loader.c b/mesalib/src/loader/loader.c index a5bd7692e..811f8a257 100644 --- a/mesalib/src/loader/loader.c +++ b/mesalib/src/loader/loader.c @@ -67,6 +67,10 @@ #include <stdarg.h> #include <stdio.h> #include <string.h> +#ifdef HAVE_LIBUDEV +#include <assert.h> +#include <dlfcn.h> +#endif #include "loader.h" #ifndef __NOT_HAVE_DRM_H @@ -78,12 +82,11 @@ static void default_logger(int level, const char *fmt, ...) { - if (level >= _LOADER_WARNING) { + if (level <= _LOADER_WARNING) { va_list args; va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); - fprintf(stderr, "\n"); } } @@ -92,21 +95,62 @@ static void (*log_)(int level, const char *fmt, ...) = default_logger; #ifdef HAVE_LIBUDEV #include <libudev.h> +static void *udev_handle = NULL; + +static void * +udev_dlopen_handle(void) +{ + if (!udev_handle) { + udev_handle = dlopen("libudev.so.1", RTLD_LOCAL | RTLD_LAZY); + + if (!udev_handle) { + /* libudev.so.1 changed the return types of the two unref functions + * from voids to pointers. We don't use those return values, and the + * only ABI I've heard that cares about this kind of change (calling + * a function with a void * return that actually only returns void) + * might be ia64. + */ + 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"); + } + } + } + + return udev_handle; +} + +static void * +asserted_dlsym(void *dlopen_handle, const char *name) +{ + void *result = dlsym(dlopen_handle, name); + assert(result); + return result; +} + +#define UDEV_SYMBOL(ret, name, args) \ + ret (*name) args = asserted_dlsym(udev_dlopen_handle(), #name); + + static inline struct udev_device * udev_device_new_from_fd(struct udev *udev, int fd) { struct udev_device *device; struct stat buf; + UDEV_SYMBOL(struct udev_device *, udev_device_new_from_devnum, + (struct udev *udev, char type, dev_t devnum)); if (fstat(fd, &buf) < 0) { - log_(_LOADER_WARNING, "MESA-LOADER: failed to stat fd %d", fd); + log_(_LOADER_WARNING, "MESA-LOADER: failed to stat fd %d\n", fd); return NULL; } device = udev_device_new_from_devnum(udev, 'c', buf.st_rdev); if (device == NULL) { log_(_LOADER_WARNING, - "MESA-LOADER: could not create udev device for fd %d", fd); + "MESA-LOADER: could not create udev device for fd %d\n", fd); return NULL; } @@ -119,6 +163,14 @@ loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id) struct udev *udev = NULL; struct udev_device *device = NULL, *parent; const char *pci_id; + UDEV_SYMBOL(struct udev *, udev_new, (void)); + UDEV_SYMBOL(struct udev_device *, udev_device_get_parent, + (struct udev_device *)); + UDEV_SYMBOL(const char *, udev_device_get_property_value, + (struct udev_device *, const char *)); + UDEV_SYMBOL(struct udev_device *, udev_device_unref, + (struct udev_device *)); + UDEV_SYMBOL(struct udev *, udev_unref, (struct udev *)); *chip_id = -1; @@ -129,14 +181,14 @@ loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id) parent = udev_device_get_parent(device); if (parent == NULL) { - log_(_LOADER_WARNING, "MESA-LOADER: could not get parent device"); + log_(_LOADER_WARNING, "MESA-LOADER: could not get parent device\n"); goto out; } pci_id = udev_device_get_property_value(parent, "PCI_ID"); if (pci_id == NULL || sscanf(pci_id, "%x:%x", vendor_id, chip_id) != 2) { - log_(_LOADER_WARNING, "MESA-LOADER: malformed or no PCI ID"); + log_(_LOADER_WARNING, "MESA-LOADER: malformed or no PCI ID\n"); *chip_id = -1; goto out; } @@ -166,11 +218,11 @@ loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id) version = drmGetVersion(fd); if (!version) { - log_(_LOADER_WARNING, "MESA-LOADER: invalid drm fd"); + log_(_LOADER_WARNING, "MESA-LOADER: invalid drm fd\n"); return FALSE; } if (!version->name) { - log_(_LOADER_WARNING, "MESA-LOADER: unable to determine the driver name"); + log_(_LOADER_WARNING, "MESA-LOADER: unable to determine the driver name\n"); drmFreeVersion(version); return FALSE; } @@ -186,7 +238,7 @@ loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id) gp.value = chip_id; ret = drmCommandWriteRead(fd, DRM_I915_GETPARAM, &gp, sizeof(gp)); if (ret) { - log_(_LOADER_WARNING, "MESA-LOADER: failed to get param for i915"); + log_(_LOADER_WARNING, "MESA-LOADER: failed to get param for i915\n"); *chip_id = -1; } } @@ -201,7 +253,7 @@ loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id) info.value = (unsigned long) chip_id; ret = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)); if (ret) { - log_(_LOADER_WARNING, "MESA-LOADER: failed to get info for radeon"); + log_(_LOADER_WARNING, "MESA-LOADER: failed to get info for radeon\n"); *chip_id = -1; } } @@ -240,6 +292,12 @@ loader_get_device_name_for_fd(int fd) struct udev *udev; struct udev_device *device; const char *const_device_name; + UDEV_SYMBOL(struct udev *, udev_new, (void)); + UDEV_SYMBOL(const char *, udev_device_get_devnode, + (struct udev_device *)); + UDEV_SYMBOL(struct udev_device *, udev_device_unref, + (struct udev_device *)); + UDEV_SYMBOL(struct udev *, udev_unref, (struct udev *)); udev = udev_new(); device = udev_device_new_from_fd(udev, fd); @@ -274,12 +332,12 @@ loader_get_driver_for_fd(int fd, unsigned driver_types) drmVersionPtr version = drmGetVersion(fd); if (!version) { - log_(_LOADER_WARNING, "failed to get driver name for fd %d", fd); + log_(_LOADER_WARNING, "failed to get driver name for fd %d\n", fd); return NULL; } driver = strndup(version->name, version->name_len); - log_(_LOADER_INFO, "using driver %s for %d", driver, fd); + log_(_LOADER_INFO, "using driver %s for %d\n", driver, fd); drmFreeVersion(version); #endif @@ -307,8 +365,8 @@ loader_get_driver_for_fd(int fd, unsigned driver_types) } out: - log_(driver ? _LOADER_INFO : _LOADER_WARNING, - "pci id for fd %d: %04x:%04x, driver %s", + log_(driver ? _LOADER_DEBUG : _LOADER_WARNING, + "pci id for fd %d: %04x:%04x, driver %s\n", fd, vendor_id, chip_id, driver); return driver; } |