aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2014-03-18 10:00:56 -0400
committerThomas Hellstrom <thellstrom@vmware.com>2014-03-28 09:19:03 -0400
commitadebcb20e4ca9330a293c294e1f104edba21dbaf (patch)
tree09afc68d6963a27e8f2e2e38263e3cd8b6b2c25f
parent4649926d043205d3693551b36e2ed88a264177a5 (diff)
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: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Brian Paul <brianp@vmware.com>
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_surface.c105
-rw-r--r--include/uapi/drm/vmwgfx_drm.h12
2 files changed, 81 insertions, 36 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
index aac243b9ec30..d50cd76378c4 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
@@ -876,6 +876,64 @@ out_unlock:
876 return ret; 876 return ret;
877} 877}
878 878
879
880static int
881vmw_surface_handle_reference(struct vmw_private *dev_priv,
882 struct drm_file *file_priv,
883 uint32_t u_handle,
884 enum drm_vmw_handle_type handle_type,
885 struct ttm_base_object **base_p)
886{
887 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
888 uint32_t handle;
889 struct ttm_base_object *base;
890 int ret;
891
892 if (handle_type == DRM_VMW_HANDLE_PRIME) {
893 ret = ttm_prime_fd_to_handle(tfile, u_handle, &handle);
894 if (unlikely(ret != 0))
895 return ret;
896 } else {
897 if (unlikely(drm_is_render_client(file_priv))) {
898 DRM_ERROR("Render client refused legacy "
899 "surface reference.\n");
900 return -EACCES;
901 }
902 handle = u_handle;
903 }
904
905 ret = -EINVAL;
906 base = ttm_base_object_lookup_for_ref(dev_priv->tdev, handle);
907 if (unlikely(base == NULL)) {
908 DRM_ERROR("Could not find surface to reference.\n");
909 goto out_no_lookup;
910 }
911
912 if (unlikely(ttm_base_object_type(base) != VMW_RES_SURFACE)) {
913 DRM_ERROR("Referenced object is not a surface.\n");
914 goto out_bad_resource;
915 }
916
917 if (handle_type != DRM_VMW_HANDLE_PRIME) {
918 ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL);
919 if (unlikely(ret != 0)) {
920 DRM_ERROR("Could not add a reference to a surface.\n");
921 goto out_bad_resource;
922 }
923 }
924
925 *base_p = base;
926 return 0;
927
928out_bad_resource:
929 ttm_base_object_unref(&base);
930out_no_lookup:
931 if (handle_type == DRM_VMW_HANDLE_PRIME)
932 (void) ttm_ref_object_base_unref(tfile, handle, TTM_REF_USAGE);
933
934 return ret;
935}
936
879/** 937/**
880 * vmw_user_surface_define_ioctl - Ioctl function implementing 938 * vmw_user_surface_define_ioctl - Ioctl function implementing
881 * the user surface reference functionality. 939 * the user surface reference functionality.
@@ -897,27 +955,16 @@ int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
897 struct vmw_user_surface *user_srf; 955 struct vmw_user_surface *user_srf;
898 struct drm_vmw_size __user *user_sizes; 956 struct drm_vmw_size __user *user_sizes;
899 struct ttm_base_object *base; 957 struct ttm_base_object *base;
900 int ret = -EINVAL; 958 int ret;
901
902 base = ttm_base_object_lookup_for_ref(dev_priv->tdev, req->sid);
903 if (unlikely(base == NULL)) {
904 DRM_ERROR("Could not find surface to reference.\n");
905 return -EINVAL;
906 }
907 959
908 if (unlikely(ttm_base_object_type(base) != VMW_RES_SURFACE)) 960 ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid,
909 goto out_bad_resource; 961 req->handle_type, &base);
962 if (unlikely(ret != 0))
963 return ret;
910 964
911 user_srf = container_of(base, struct vmw_user_surface, prime.base); 965 user_srf = container_of(base, struct vmw_user_surface, prime.base);
912 srf = &user_srf->srf; 966 srf = &user_srf->srf;
913 967
914 ret = ttm_ref_object_add(tfile, &user_srf->prime.base,
915 TTM_REF_USAGE, NULL);
916 if (unlikely(ret != 0)) {
917 DRM_ERROR("Could not add a reference to a surface.\n");
918 goto out_no_reference;
919 }
920
921 rep->flags = srf->flags; 968 rep->flags = srf->flags;
922 rep->format = srf->format; 969 rep->format = srf->format;
923 memcpy(rep->mip_levels, srf->mip_levels, sizeof(srf->mip_levels)); 970 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,
930 if (unlikely(ret != 0)) { 977 if (unlikely(ret != 0)) {
931 DRM_ERROR("copy_to_user failed %p %u\n", 978 DRM_ERROR("copy_to_user failed %p %u\n",
932 user_sizes, srf->num_sizes); 979 user_sizes, srf->num_sizes);
980 ttm_ref_object_base_unref(tfile, base->hash.key, TTM_REF_USAGE);
933 ret = -EFAULT; 981 ret = -EFAULT;
934 } 982 }
935out_bad_resource: 983
936out_no_reference:
937 ttm_base_object_unref(&base); 984 ttm_base_object_unref(&base);
938 985
939 return ret; 986 return ret;
@@ -1313,14 +1360,10 @@ int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data,
1313 uint32_t backup_handle; 1360 uint32_t backup_handle;
1314 int ret = -EINVAL; 1361 int ret = -EINVAL;
1315 1362
1316 base = ttm_base_object_lookup_for_ref(dev_priv->tdev, req->sid); 1363 ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid,
1317 if (unlikely(base == NULL)) { 1364 req->handle_type, &base);
1318 DRM_ERROR("Could not find surface to reference.\n"); 1365 if (unlikely(ret != 0))
1319 return -EINVAL; 1366 return ret;
1320 }
1321
1322 if (unlikely(ttm_base_object_type(base) != VMW_RES_SURFACE))
1323 goto out_bad_resource;
1324 1367
1325 user_srf = container_of(base, struct vmw_user_surface, prime.base); 1368 user_srf = container_of(base, struct vmw_user_surface, prime.base);
1326 srf = &user_srf->srf; 1369 srf = &user_srf->srf;
@@ -1329,13 +1372,6 @@ int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data,
1329 goto out_bad_resource; 1372 goto out_bad_resource;
1330 } 1373 }
1331 1374
1332 ret = ttm_ref_object_add(tfile, &user_srf->prime.base,
1333 TTM_REF_USAGE, NULL);
1334 if (unlikely(ret != 0)) {
1335 DRM_ERROR("Could not add a reference to a GB surface.\n");
1336 goto out_bad_resource;
1337 }
1338
1339 mutex_lock(&dev_priv->cmdbuf_mutex); /* Protect res->backup */ 1375 mutex_lock(&dev_priv->cmdbuf_mutex); /* Protect res->backup */
1340 ret = vmw_user_dmabuf_reference(tfile, srf->res.backup, 1376 ret = vmw_user_dmabuf_reference(tfile, srf->res.backup,
1341 &backup_handle); 1377 &backup_handle);
@@ -1344,8 +1380,7 @@ int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data,
1344 if (unlikely(ret != 0)) { 1380 if (unlikely(ret != 0)) {
1345 DRM_ERROR("Could not add a reference to a GB surface " 1381 DRM_ERROR("Could not add a reference to a GB surface "
1346 "backup buffer.\n"); 1382 "backup buffer.\n");
1347 (void) ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, 1383 (void) ttm_ref_object_base_unref(tfile, base->hash.key,
1348 req->sid,
1349 TTM_REF_USAGE); 1384 TTM_REF_USAGE);
1350 goto out_bad_resource; 1385 goto out_bad_resource;
1351 } 1386 }
diff --git a/include/uapi/drm/vmwgfx_drm.h b/include/uapi/drm/vmwgfx_drm.h
index 87792a5fee3b..4fc66f6b12ce 100644
--- a/include/uapi/drm/vmwgfx_drm.h
+++ b/include/uapi/drm/vmwgfx_drm.h
@@ -90,6 +90,15 @@
90#define DRM_VMW_PARAM_MAX_MOB_SIZE 10 90#define DRM_VMW_PARAM_MAX_MOB_SIZE 10
91 91
92/** 92/**
93 * enum drm_vmw_handle_type - handle type for ref ioctls
94 *
95 */
96enum drm_vmw_handle_type {
97 DRM_VMW_HANDLE_LEGACY = 0,
98 DRM_VMW_HANDLE_PRIME = 1
99};
100
101/**
93 * struct drm_vmw_getparam_arg 102 * struct drm_vmw_getparam_arg
94 * 103 *
95 * @value: Returned value. //Out 104 * @value: Returned value. //Out
@@ -177,6 +186,7 @@ struct drm_vmw_surface_create_req {
177 * struct drm_wmv_surface_arg 186 * struct drm_wmv_surface_arg
178 * 187 *
179 * @sid: Surface id of created surface or surface to destroy or reference. 188 * @sid: Surface id of created surface or surface to destroy or reference.
189 * @handle_type: Handle type for DRM_VMW_REF_SURFACE Ioctl.
180 * 190 *
181 * Output data from the DRM_VMW_CREATE_SURFACE Ioctl. 191 * Output data from the DRM_VMW_CREATE_SURFACE Ioctl.
182 * Input argument to the DRM_VMW_UNREF_SURFACE Ioctl. 192 * Input argument to the DRM_VMW_UNREF_SURFACE Ioctl.
@@ -185,7 +195,7 @@ struct drm_vmw_surface_create_req {
185 195
186struct drm_vmw_surface_arg { 196struct drm_vmw_surface_arg {
187 int32_t sid; 197 int32_t sid;
188 uint32_t pad64; 198 enum drm_vmw_handle_type handle_type;
189}; 199};
190 200
191/** 201/**