Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+81 -36
+70 -35
drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
··· 876 876 return ret; 877 877 } 878 878 879 + 880 + static int 881 + vmw_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 + 928 + out_bad_resource: 929 + ttm_base_object_unref(&base); 930 + out_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 938 * vmw_user_surface_define_ioctl - Ioctl function implementing 881 939 * the user surface reference functionality. ··· 955 897 struct vmw_user_surface *user_srf; 956 898 struct drm_vmw_size __user *user_sizes; 957 899 struct ttm_base_object *base; 958 - int ret = -EINVAL; 900 + int ret; 959 901 960 - base = ttm_base_object_lookup_for_ref(dev_priv->tdev, req->sid); 961 - if (unlikely(base == NULL)) { 962 - DRM_ERROR("Could not find surface to reference.\n"); 963 - return -EINVAL; 964 - } 965 - 966 - if (unlikely(ttm_base_object_type(base) != VMW_RES_SURFACE)) 967 - goto out_bad_resource; 902 + ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid, 903 + req->handle_type, &base); 904 + if (unlikely(ret != 0)) 905 + return ret; 968 906 969 907 user_srf = container_of(base, struct vmw_user_surface, prime.base); 970 908 srf = &user_srf->srf; 971 - 972 - ret = ttm_ref_object_add(tfile, &user_srf->prime.base, 973 - TTM_REF_USAGE, NULL); 974 - if (unlikely(ret != 0)) { 975 - DRM_ERROR("Could not add a reference to a surface.\n"); 976 - goto out_no_reference; 977 - } 978 909 979 910 rep->flags = srf->flags; 980 911 rep->format = srf->format; ··· 977 930 if (unlikely(ret != 0)) { 978 931 DRM_ERROR("copy_to_user failed %p %u\n", 979 932 user_sizes, srf->num_sizes); 933 + ttm_ref_object_base_unref(tfile, base->hash.key, TTM_REF_USAGE); 980 934 ret = -EFAULT; 981 935 } 982 - out_bad_resource: 983 - out_no_reference: 936 + 984 937 ttm_base_object_unref(&base); 985 938 986 939 return ret; ··· 1360 1313 uint32_t backup_handle; 1361 1314 int ret = -EINVAL; 1362 1315 1363 - base = ttm_base_object_lookup_for_ref(dev_priv->tdev, req->sid); 1364 - if (unlikely(base == NULL)) { 1365 - DRM_ERROR("Could not find surface to reference.\n"); 1366 - return -EINVAL; 1367 - } 1368 - 1369 - if (unlikely(ttm_base_object_type(base) != VMW_RES_SURFACE)) 1370 - goto out_bad_resource; 1316 + ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid, 1317 + req->handle_type, &base); 1318 + if (unlikely(ret != 0)) 1319 + return ret; 1371 1320 1372 1321 user_srf = container_of(base, struct vmw_user_surface, prime.base); 1373 1322 srf = &user_srf->srf; 1374 1323 if (srf->res.backup == NULL) { 1375 1324 DRM_ERROR("Shared GB surface is missing a backup buffer.\n"); 1376 - goto out_bad_resource; 1377 - } 1378 - 1379 - ret = ttm_ref_object_add(tfile, &user_srf->prime.base, 1380 - TTM_REF_USAGE, NULL); 1381 - if (unlikely(ret != 0)) { 1382 - DRM_ERROR("Could not add a reference to a GB surface.\n"); 1383 1325 goto out_bad_resource; 1384 1326 } 1385 1327 ··· 1380 1344 if (unlikely(ret != 0)) { 1381 1345 DRM_ERROR("Could not add a reference to a GB surface " 1382 1346 "backup buffer.\n"); 1383 - (void) ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, 1384 - req->sid, 1347 + (void) ttm_ref_object_base_unref(tfile, base->hash.key, 1385 1348 TTM_REF_USAGE); 1386 1349 goto out_bad_resource; 1387 1350 }
+11 -1
include/uapi/drm/vmwgfx_drm.h
··· 90 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 + */ 96 + enum drm_vmw_handle_type { 97 + DRM_VMW_HANDLE_LEGACY = 0, 98 + DRM_VMW_HANDLE_PRIME = 1 99 + }; 100 + 101 + /** 93 102 * struct drm_vmw_getparam_arg 94 103 * 95 104 * @value: Returned value. //Out ··· 186 177 * struct drm_wmv_surface_arg 187 178 * 188 179 * @sid: Surface id of created surface or surface to destroy or reference. 180 + * @handle_type: Handle type for DRM_VMW_REF_SURFACE Ioctl. 189 181 * 190 182 * Output data from the DRM_VMW_CREATE_SURFACE Ioctl. 191 183 * Input argument to the DRM_VMW_UNREF_SURFACE Ioctl. ··· 195 185 196 186 struct drm_vmw_surface_arg { 197 187 int32_t sid; 198 - uint32_t pad64; 188 + enum drm_vmw_handle_type handle_type; 199 189 }; 200 190 201 191 /**