Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit adebcb20 authored by Thomas Hellstrom's avatar Thomas Hellstrom
Browse files

drm/vmwgfx: Allow prime fds in the surface reference ioctls



Allow prime fds and at the same time block legacy handles for render-nodes
in the surface reference ioctls. This means these ioctls can be used
directly from prime-aware clients, and that they can be called from
render-nodes.

Signed-off-by: default avatarThomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: default avatarBrian Paul <brianp@vmware.com>
parent 4649926d
Loading
Loading
Loading
Loading
+70 −35
Original line number Diff line number Diff line
@@ -876,6 +876,64 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
	return ret;
}


static int
vmw_surface_handle_reference(struct vmw_private *dev_priv,
			     struct drm_file *file_priv,
			     uint32_t u_handle,
			     enum drm_vmw_handle_type handle_type,
			     struct ttm_base_object **base_p)
{
	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
	uint32_t handle;
	struct ttm_base_object *base;
	int ret;

	if (handle_type == DRM_VMW_HANDLE_PRIME) {
		ret = ttm_prime_fd_to_handle(tfile, u_handle, &handle);
		if (unlikely(ret != 0))
			return ret;
	} else {
		if (unlikely(drm_is_render_client(file_priv))) {
			DRM_ERROR("Render client refused legacy "
				  "surface reference.\n");
			return -EACCES;
		}
		handle = u_handle;
	}

	ret = -EINVAL;
	base = ttm_base_object_lookup_for_ref(dev_priv->tdev, handle);
	if (unlikely(base == NULL)) {
		DRM_ERROR("Could not find surface to reference.\n");
		goto out_no_lookup;
	}

	if (unlikely(ttm_base_object_type(base) != VMW_RES_SURFACE)) {
		DRM_ERROR("Referenced object is not a surface.\n");
		goto out_bad_resource;
	}

	if (handle_type != DRM_VMW_HANDLE_PRIME) {
		ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL);
		if (unlikely(ret != 0)) {
			DRM_ERROR("Could not add a reference to a surface.\n");
			goto out_bad_resource;
		}
	}

	*base_p = base;
	return 0;

out_bad_resource:
	ttm_base_object_unref(&base);
out_no_lookup:
	if (handle_type == DRM_VMW_HANDLE_PRIME)
		(void) ttm_ref_object_base_unref(tfile, handle, TTM_REF_USAGE);

	return ret;
}

/**
 * vmw_user_surface_define_ioctl - Ioctl function implementing
 *                                  the user surface reference functionality.
@@ -897,27 +955,16 @@ int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
	struct vmw_user_surface *user_srf;
	struct drm_vmw_size __user *user_sizes;
	struct ttm_base_object *base;
	int ret = -EINVAL;

	base = ttm_base_object_lookup_for_ref(dev_priv->tdev, req->sid);
	if (unlikely(base == NULL)) {
		DRM_ERROR("Could not find surface to reference.\n");
		return -EINVAL;
	}
	int ret;

	if (unlikely(ttm_base_object_type(base) != VMW_RES_SURFACE))
		goto out_bad_resource;
	ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid,
					   req->handle_type, &base);
	if (unlikely(ret != 0))
		return ret;

	user_srf = container_of(base, struct vmw_user_surface, prime.base);
	srf = &user_srf->srf;

	ret = ttm_ref_object_add(tfile, &user_srf->prime.base,
				 TTM_REF_USAGE, NULL);
	if (unlikely(ret != 0)) {
		DRM_ERROR("Could not add a reference to a surface.\n");
		goto out_no_reference;
	}

	rep->flags = srf->flags;
	rep->format = srf->format;
	memcpy(rep->mip_levels, srf->mip_levels, sizeof(srf->mip_levels));
@@ -930,10 +977,10 @@ int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
	if (unlikely(ret != 0)) {
		DRM_ERROR("copy_to_user failed %p %u\n",
			  user_sizes, srf->num_sizes);
		ttm_ref_object_base_unref(tfile, base->hash.key, TTM_REF_USAGE);
		ret = -EFAULT;
	}
out_bad_resource:
out_no_reference:

	ttm_base_object_unref(&base);

	return ret;
@@ -1313,14 +1360,10 @@ int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data,
	uint32_t backup_handle;
	int ret = -EINVAL;

	base = ttm_base_object_lookup_for_ref(dev_priv->tdev, req->sid);
	if (unlikely(base == NULL)) {
		DRM_ERROR("Could not find surface to reference.\n");
		return -EINVAL;
	}

	if (unlikely(ttm_base_object_type(base) != VMW_RES_SURFACE))
		goto out_bad_resource;
	ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid,
					   req->handle_type, &base);
	if (unlikely(ret != 0))
		return ret;

	user_srf = container_of(base, struct vmw_user_surface, prime.base);
	srf = &user_srf->srf;
@@ -1329,13 +1372,6 @@ int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data,
		goto out_bad_resource;
	}

	ret = ttm_ref_object_add(tfile, &user_srf->prime.base,
				 TTM_REF_USAGE, NULL);
	if (unlikely(ret != 0)) {
		DRM_ERROR("Could not add a reference to a GB surface.\n");
		goto out_bad_resource;
	}

	mutex_lock(&dev_priv->cmdbuf_mutex); /* Protect res->backup */
	ret = vmw_user_dmabuf_reference(tfile, srf->res.backup,
					&backup_handle);
@@ -1344,8 +1380,7 @@ int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data,
	if (unlikely(ret != 0)) {
		DRM_ERROR("Could not add a reference to a GB surface "
			  "backup buffer.\n");
		(void) ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,
						 req->sid,
		(void) ttm_ref_object_base_unref(tfile, base->hash.key,
						 TTM_REF_USAGE);
		goto out_bad_resource;
	}
+11 −1
Original line number Diff line number Diff line
@@ -89,6 +89,15 @@
#define DRM_VMW_PARAM_MAX_MOB_MEMORY   9
#define DRM_VMW_PARAM_MAX_MOB_SIZE     10

/**
 * enum drm_vmw_handle_type - handle type for ref ioctls
 *
 */
enum drm_vmw_handle_type {
	DRM_VMW_HANDLE_LEGACY = 0,
	DRM_VMW_HANDLE_PRIME = 1
};

/**
 * struct drm_vmw_getparam_arg
 *
@@ -177,6 +186,7 @@ struct drm_vmw_surface_create_req {
 * struct drm_wmv_surface_arg
 *
 * @sid: Surface id of created surface or surface to destroy or reference.
 * @handle_type: Handle type for DRM_VMW_REF_SURFACE Ioctl.
 *
 * Output data from the DRM_VMW_CREATE_SURFACE Ioctl.
 * Input argument to the DRM_VMW_UNREF_SURFACE Ioctl.
@@ -185,7 +195,7 @@ struct drm_vmw_surface_create_req {

struct drm_vmw_surface_arg {
	int32_t sid;
	uint32_t pad64;
	enum drm_vmw_handle_type handle_type;
};

/**