Skip to content

Commit

Permalink
drm/vmwgfx: Allow prime fds in the surface reference ioctls
Browse files Browse the repository at this point in the history
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: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
  • Loading branch information
Thomas Hellstrom committed Mar 28, 2014
1 parent 4649926 commit adebcb2
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 36 deletions.
105 changes: 70 additions & 35 deletions drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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));
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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;
}
Expand Down
12 changes: 11 additions & 1 deletion include/uapi/drm/vmwgfx_drm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down Expand Up @@ -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.
Expand All @@ -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;
};

/**
Expand Down

0 comments on commit adebcb2

Please sign in to comment.