+Amit and John On Sat, Jun 9, 2018 at 11:27 AM, Robert Foss <robert.f...@collabora.com> wrote: > This patch both adds support for probing & filtering DRM nodes > and switches away from using the GRALLOC_MODULE_PERFORM_GET_DRM_FD > gralloc call. > > Currently the filtering is based just on the driver name, > and the desired name is supplied using the "drm.gpu.vendor_name" > Android property.
There's a potential issue with this whole approach and that is SELinux. With the way SELinux locks down accesses, getting probing thru device files to work can be a pain. It may be better now than the prior version because sysfs is not probed. I'll leave it to Amit or John to comment. Rob > > Signed-off-by: Robert Foss <robert.f...@collabora.com> > --- > > Changes since v2: > - Switch from drmGetDevices2 to manual renderD node iteration > - Add probe_res enum to communicate probing results better > - Avoid using _eglError() in internal static functions > - Avoid actually loading the driver while probing, just verify > that it exists. > - Replace strlen call with the assumed length PROPERTY_VALUE_MAX > > Changes since v1: > - Do not rely on libdrm for probing > - Distinguish between errors and when no drm devices are found > > Changes since RFC: > - Rebased on newer libdrm drmHandleMatch patch > - Added support for driver probing > > > src/egl/drivers/dri2/platform_android.c | 222 ++++++++++++++++++------ > 1 file changed, 169 insertions(+), 53 deletions(-) > > diff --git a/src/egl/drivers/dri2/platform_android.c > b/src/egl/drivers/dri2/platform_android.c > index 4ba96aad90..a2cbe92d93 100644 > --- a/src/egl/drivers/dri2/platform_android.c > +++ b/src/egl/drivers/dri2/platform_android.c > @@ -27,12 +27,16 @@ > * DEALINGS IN THE SOFTWARE. > */ > > +#include <cutils/properties.h> > #include <errno.h> > +#include <dirent.h> > #include <dlfcn.h> > #include <fcntl.h> > #include <xf86drm.h> > #include <stdbool.h> > +#include <stdio.h> > #include <sync/sync.h> > +#include <sys/types.h> > > #include "loader.h" > #include "egl_dri2.h" > @@ -1130,31 +1134,6 @@ droid_add_configs_for_visuals(_EGLDriver *drv, > _EGLDisplay *dpy) > return (config_count != 0); > } > > -enum { > - /* perform(const struct gralloc_module_t *mod, > - * int op, > - * int *fd); > - */ > - GRALLOC_MODULE_PERFORM_GET_DRM_FD = 0x40000002, > -}; > - > -static int > -droid_open_device(struct dri2_egl_display *dri2_dpy) > -{ > - int fd = -1, err = -EINVAL; > - > - if (dri2_dpy->gralloc->perform) > - err = dri2_dpy->gralloc->perform(dri2_dpy->gralloc, > - GRALLOC_MODULE_PERFORM_GET_DRM_FD, > - &fd); > - if (err || fd < 0) { > - _eglLog(_EGL_WARNING, "fail to get drm fd"); > - fd = -1; > - } > - > - return (fd >= 0) ? fcntl(fd, F_DUPFD_CLOEXEC, 3) : -1; > -} > - > static const struct dri2_egl_display_vtbl droid_display_vtbl = { > .authenticate = NULL, > .create_window_surface = droid_create_window_surface, > @@ -1215,6 +1194,168 @@ static const __DRIextension > *droid_image_loader_extensions[] = { > NULL, > }; > > +EGLBoolean > +droid_load_driver(_EGLDisplay *disp) > +{ > + struct dri2_egl_display *dri2_dpy = disp->DriverData; > + const char *err; > + > + dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd); > + if (dri2_dpy->driver_name == NULL) > + return false; > + > + dri2_dpy->is_render_node = drmGetNodeTypeFromFd(dri2_dpy->fd) == > DRM_NODE_RENDER; > + > + if (!dri2_dpy->is_render_node) { > + #ifdef HAVE_DRM_GRALLOC > + /* Handle control nodes using __DRI_DRI2_LOADER extension and GEM > names > + * for backwards compatibility with drm_gralloc. (Do not use on new > + * systems.) */ > + dri2_dpy->loader_extensions = droid_dri2_loader_extensions; > + if (!dri2_load_driver(disp)) { > + err = "DRI2: failed to load driver"; > + goto error; > + } > + #else > + err = "DRI2: handle is not for a render node"; > + goto error; > + #endif > + } else { > + dri2_dpy->loader_extensions = droid_image_loader_extensions; > + if (!dri2_load_driver_dri3(disp)) { > + err = "DRI3: failed to load driver"; > + goto error; > + } > + } > + > + return true; > + > +error: > + free(dri2_dpy->driver_name); > + dri2_dpy->driver_name = NULL; > + return false; > +} > + > +static bool > +droid_probe_driver(int fd) > +{ > + char *driver_name; > + > + driver_name = loader_get_driver_for_fd(fd); > + if (driver_name == NULL) > + return false; > + > + free(driver_name); > + return true; > +} > + > +typedef enum { > + probe_error = -1, > + probe_success = 0, > + probe_filtered_out = 1, > + probe_no_driver = 2 > +} probe_ret_t; > + > +static probe_ret_t > +droid_probe_device(_EGLDisplay *disp, int fd, char *vendor) > +{ > + int ret; > + > + drmVersionPtr ver = drmGetVersion(fd); > + if (!ver) > + return probe_error; > + > + if (vendor != NULL && ver->name != NULL && > + strncmp(vendor, ver->name, PROPERTY_VALUE_MAX) != 0) { > + ret = probe_filtered_out; > + goto cleanup; > + } > + > + > + if (!droid_probe_driver(fd)) { > + ret = probe_no_driver; > + goto cleanup; > + } > + > + ret = probe_success; > + > +cleanup: > + drmFreeVersion(ver); > + return ret; > +} > + > +static int > +droid_open_device(_EGLDisplay *disp) > +{ > + const int MAX_DRM_DEVICES = 32; > + int prop_set, num_devices; > + int fd = -1, fallback_fd = -1; > + > + char *vendor_name = NULL; > + char vendor_buf[PROPERTY_VALUE_MAX]; > + if (property_get("drm.gpu.vendor_name", vendor_buf, NULL) > 0); > + vendor_name = vendor_buf; > + > + const char *drm_dir_name = "/dev/dri"; > + DIR *sysdir = opendir(drm_dir_name); > + if (!sysdir) > + return -errno; > + > + struct dirent *dent; > + while ((dent = readdir(sysdir))) { > + char dev_path[128]; > + char *render_dev_prefix = "renderD"; > + size_t prefix_len = strlen(render_dev_prefix); > + > + if (strncmp(render_dev_prefix, dent->d_name, prefix_len) != 0) > + continue; > + > + sprintf(dev_path, "%s/%s", drm_dir_name, dent->d_name); > + fd = loader_open_device(dev_path); > + if (fd == -1) { > + _eglLog(_EGL_WARNING, "%s() Failed to open DRM device %s", > + __func__, dev_path); > + continue; > + } > + > + int ret = droid_probe_device(disp, fd, vendor_name); > + switch (ret) { > + case probe_success: > + goto success; > + case probe_filtered_out: > + goto allow_fallback; > + case probe_error: > + case probe_no_driver: > + goto next; > + } > + > +allow_fallback: > + if (fallback_fd == -1) > + fallback_fd = fd; > +next: > + if (fallback_fd != fd) > + close(fd); > + fd = -1; > + continue; > + } > + > +success: > + closedir(sysdir); > + > + if (fallback_fd < 0 && fd < 0) { > + _eglLog(_EGL_WARNING, "Failed to open any DRM device"); > + return -1; > + } > + > + if (fd < 0) { > + _eglLog(_EGL_WARNING, "Failed to open desired DRM device, using > fallback"); > + return fallback_fd; > + } > + > + close(fallback_fd); > + return fd; > +} > + > EGLBoolean > dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *disp) > { > @@ -1242,42 +1383,17 @@ dri2_initialize_android(_EGLDriver *drv, _EGLDisplay > *disp) > > disp->DriverData = (void *) dri2_dpy; > > - dri2_dpy->fd = droid_open_device(dri2_dpy); > + dri2_dpy->fd = droid_open_device(disp); > if (dri2_dpy->fd < 0) { > err = "DRI2: failed to open device"; > goto cleanup; > } > > - dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd); > - if (dri2_dpy->driver_name == NULL) { > - err = "DRI2: failed to get driver name"; > + if (!droid_load_driver(disp)) { > + err = "DRI2: failed to load driver"; > goto cleanup; > } > > - dri2_dpy->is_render_node = drmGetNodeTypeFromFd(dri2_dpy->fd) == > DRM_NODE_RENDER; > - > - if (!dri2_dpy->is_render_node) { > - #ifdef HAVE_DRM_GRALLOC > - /* Handle control nodes using __DRI_DRI2_LOADER extension and GEM > names > - * for backwards compatibility with drm_gralloc. (Do not use on new > - * systems.) */ > - dri2_dpy->loader_extensions = droid_dri2_loader_extensions; > - if (!dri2_load_driver(disp)) { > - err = "DRI2: failed to load driver"; > - goto cleanup; > - } > - #else > - err = "DRI2: handle is not for a render node"; > - goto cleanup; > - #endif > - } else { > - dri2_dpy->loader_extensions = droid_image_loader_extensions; > - if (!dri2_load_driver_dri3(disp)) { > - err = "DRI3: failed to load driver"; > - goto cleanup; > - } > - } > - > if (!dri2_create_screen(disp)) { > err = "DRI2: failed to create screen"; > goto cleanup; > -- > 2.17.1 > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev