[Mesa-dev] [PATCH v3 3/3] egl/android: Add DRM node probing and filtering
Rob Herring
robh at kernel.org
Wed Jun 13 15:15:26 UTC 2018
+Amit and John
On Sat, Jun 9, 2018 at 11:27 AM, Robert Foss <robert.foss at 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.foss at 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
>
More information about the mesa-dev
mailing list