aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorDeepak Rawat <drawat@vmware.com>2018-06-20 17:48:35 -0400
committerThomas Hellstrom <thellstrom@vmware.com>2018-07-06 14:16:09 -0400
commit14b1c33e84295693c3b1a1d7c6ac82b3f384cd17 (patch)
treeed9718f7f57d58e20f92aa194181ab4a982b4abc /drivers/gpu
parent397a11175f830e1ceb82b608a1c7adbacfbe39b0 (diff)
drm/vmwgfx: Add new ioctl for GB surface create and reference
New ioctls DRM_VMW_GB_SURFACE_CREATE_EXT and DRM_VMW_GB_SURFACE_REF_EXT are added which support 64-bit wide svga device surface flags, quality level and multisample pattern. Signed-off-by: Deepak Rawat <drawat@vmware.com> Reviewed-by: Sinclair Yeh <syeh@vmware.com> Reviewed-by: Brian Paul <brianp@vmware.com> Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Charmaine Lee <charmainel@vmware.com> Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c12
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h8
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c20
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_surface.c468
5 files changed, 335 insertions, 175 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 6cf81e19182f..59229111f303 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -137,6 +137,12 @@
137#define DRM_IOCTL_VMW_CREATE_EXTENDED_CONTEXT \ 137#define DRM_IOCTL_VMW_CREATE_EXTENDED_CONTEXT \
138 DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_CREATE_EXTENDED_CONTEXT, \ 138 DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_CREATE_EXTENDED_CONTEXT, \
139 struct drm_vmw_context_arg) 139 struct drm_vmw_context_arg)
140#define DRM_IOCTL_VMW_GB_SURFACE_CREATE_EXT \
141 DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_GB_SURFACE_CREATE_EXT, \
142 union drm_vmw_gb_surface_create_ext_arg)
143#define DRM_IOCTL_VMW_GB_SURFACE_REF_EXT \
144 DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_GB_SURFACE_REF_EXT, \
145 union drm_vmw_gb_surface_reference_ext_arg)
140 146
141/** 147/**
142 * The core DRM version of this macro doesn't account for 148 * The core DRM version of this macro doesn't account for
@@ -224,6 +230,12 @@ static const struct drm_ioctl_desc vmw_ioctls[] = {
224 VMW_IOCTL_DEF(VMW_CREATE_EXTENDED_CONTEXT, 230 VMW_IOCTL_DEF(VMW_CREATE_EXTENDED_CONTEXT,
225 vmw_extended_context_define_ioctl, 231 vmw_extended_context_define_ioctl,
226 DRM_AUTH | DRM_RENDER_ALLOW), 232 DRM_AUTH | DRM_RENDER_ALLOW),
233 VMW_IOCTL_DEF(VMW_GB_SURFACE_CREATE_EXT,
234 vmw_gb_surface_define_ext_ioctl,
235 DRM_AUTH | DRM_RENDER_ALLOW),
236 VMW_IOCTL_DEF(VMW_GB_SURFACE_REF_EXT,
237 vmw_gb_surface_reference_ext_ioctl,
238 DRM_AUTH | DRM_RENDER_ALLOW),
227}; 239};
228 240
229static const struct pci_device_id vmw_pci_id_list[] = { 241static const struct pci_device_id vmw_pci_id_list[] = {
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 7e5c93083036..59af14714797 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -1087,7 +1087,15 @@ int vmw_surface_gb_priv_define(struct drm_device *dev,
1087 uint32_t multisample_count, 1087 uint32_t multisample_count,
1088 uint32_t array_size, 1088 uint32_t array_size,
1089 struct drm_vmw_size size, 1089 struct drm_vmw_size size,
1090 SVGA3dMSPattern multisample_pattern,
1091 SVGA3dMSQualityLevel quality_level,
1090 struct vmw_surface **srf_out); 1092 struct vmw_surface **srf_out);
1093extern int vmw_gb_surface_define_ext_ioctl(struct drm_device *dev,
1094 void *data,
1095 struct drm_file *file_priv);
1096extern int vmw_gb_surface_reference_ext_ioctl(struct drm_device *dev,
1097 void *data,
1098 struct drm_file *file_priv);
1091 1099
1092/* 1100/*
1093 * Shader management - vmwgfx_shader.c 1101 * Shader management - vmwgfx_shader.c
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 0fb363458ab5..3201b0a51d10 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -1238,15 +1238,17 @@ static int vmw_create_bo_proxy(struct drm_device *dev,
1238 content_base_size.depth = 1; 1238 content_base_size.depth = 1;
1239 1239
1240 ret = vmw_surface_gb_priv_define(dev, 1240 ret = vmw_surface_gb_priv_define(dev,
1241 0, /* kernel visible only */ 1241 0, /* kernel visible only */
1242 0, /* flags */ 1242 0, /* flags */
1243 format, 1243 format,
1244 true, /* can be a scanout buffer */ 1244 true, /* can be a scanout buffer */
1245 1, /* num of mip levels */ 1245 1, /* num of mip levels */
1246 0, 1246 0,
1247 0, 1247 0,
1248 content_base_size, 1248 content_base_size,
1249 srf_out); 1249 SVGA3D_MS_PATTERN_NONE,
1250 SVGA3D_MS_QUALITY_NONE,
1251 srf_out);
1250 if (ret) { 1252 if (ret) {
1251 DRM_ERROR("Failed to allocate proxy content buffer\n"); 1253 DRM_ERROR("Failed to allocate proxy content buffer\n");
1252 return ret; 1254 return ret;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index 6630abf3a95c..f9872c9e60c4 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -1188,6 +1188,8 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane,
1188 content_srf.multisample_count, 1188 content_srf.multisample_count,
1189 0, 1189 0,
1190 display_base_size, 1190 display_base_size,
1191 content_srf.multisample_pattern,
1192 content_srf.quality_level,
1191 &vps->surf); 1193 &vps->surf);
1192 if (ret != 0) { 1194 if (ret != 0) {
1193 DRM_ERROR("Couldn't allocate STDU surface.\n"); 1195 DRM_ERROR("Couldn't allocate STDU surface.\n");
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
index a5f93f62c7fa..1d4c010a0e48 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
@@ -33,6 +33,10 @@
33#include "vmwgfx_binding.h" 33#include "vmwgfx_binding.h"
34#include "device_include/svga3d_surfacedefs.h" 34#include "device_include/svga3d_surfacedefs.h"
35 35
36#define SVGA3D_FLAGS_64(upper32, lower32) (((uint64_t)upper32 << 32) | lower32)
37#define SVGA3D_FLAGS_UPPER_32(svga3d_flags) (svga3d_flags >> 32)
38#define SVGA3D_FLAGS_LOWER_32(svga3d_flags) \
39 (svga3d_flags & ((uint64_t)U32_MAX))
36 40
37/** 41/**
38 * struct vmw_user_surface - User-space visible surface resource 42 * struct vmw_user_surface - User-space visible surface resource
@@ -81,7 +85,16 @@ static int vmw_gb_surface_unbind(struct vmw_resource *res,
81 bool readback, 85 bool readback,
82 struct ttm_validate_buffer *val_buf); 86 struct ttm_validate_buffer *val_buf);
83static int vmw_gb_surface_destroy(struct vmw_resource *res); 87static int vmw_gb_surface_destroy(struct vmw_resource *res);
84 88static int
89vmw_gb_surface_define_internal(struct drm_device *dev,
90 struct drm_vmw_gb_surface_create_ext_req *req,
91 struct drm_vmw_gb_surface_create_rep *rep,
92 struct drm_file *file_priv);
93static int
94vmw_gb_surface_reference_internal(struct drm_device *dev,
95 struct drm_vmw_surface_arg *req,
96 struct drm_vmw_gb_surface_ref_ext_rep *rep,
97 struct drm_file *file_priv);
85 98
86static const struct vmw_user_resource_conv user_surface_conv = { 99static const struct vmw_user_resource_conv user_surface_conv = {
87 .object_type = VMW_RES_SURFACE, 100 .object_type = VMW_RES_SURFACE,
@@ -1289,193 +1302,55 @@ static int vmw_gb_surface_destroy(struct vmw_resource *res)
1289 1302
1290/** 1303/**
1291 * vmw_gb_surface_define_ioctl - Ioctl function implementing 1304 * vmw_gb_surface_define_ioctl - Ioctl function implementing
1292 * the user surface define functionality. 1305 * the user surface define functionality.
1293 * 1306 *
1294 * @dev: Pointer to a struct drm_device. 1307 * @dev: Pointer to a struct drm_device.
1295 * @data: Pointer to data copied from / to user-space. 1308 * @data: Pointer to data copied from / to user-space.
1296 * @file_priv: Pointer to a drm file private structure. 1309 * @file_priv: Pointer to a drm file private structure.
1297 */ 1310 */
1298int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data, 1311int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
1299 struct drm_file *file_priv) 1312 struct drm_file *file_priv)
1300{ 1313{
1301 struct vmw_private *dev_priv = vmw_priv(dev);
1302 struct vmw_user_surface *user_srf;
1303 struct vmw_surface *srf;
1304 struct vmw_resource *res;
1305 struct vmw_resource *tmp;
1306 union drm_vmw_gb_surface_create_arg *arg = 1314 union drm_vmw_gb_surface_create_arg *arg =
1307 (union drm_vmw_gb_surface_create_arg *)data; 1315 (union drm_vmw_gb_surface_create_arg *)data;
1308 struct drm_vmw_gb_surface_create_req *req = &arg->req;
1309 struct drm_vmw_gb_surface_create_rep *rep = &arg->rep; 1316 struct drm_vmw_gb_surface_create_rep *rep = &arg->rep;
1310 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 1317 struct drm_vmw_gb_surface_create_ext_req req_ext;
1311 int ret;
1312 uint32_t size;
1313 uint32_t backup_handle = 0;
1314
1315 if (req->multisample_count != 0)
1316 return -EINVAL;
1317
1318 if (req->mip_levels > DRM_VMW_MAX_MIP_LEVELS)
1319 return -EINVAL;
1320
1321 if (unlikely(vmw_user_surface_size == 0))
1322 vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
1323 128;
1324
1325 size = vmw_user_surface_size + 128;
1326
1327 /* Define a surface based on the parameters. */
1328 ret = vmw_surface_gb_priv_define(dev,
1329 size,
1330 (SVGA3dSurfaceAllFlags)req->svga3d_flags,
1331 req->format,
1332 req->drm_surface_flags & drm_vmw_surface_flag_scanout,
1333 req->mip_levels,
1334 req->multisample_count,
1335 req->array_size,
1336 req->base_size,
1337 &srf);
1338 if (unlikely(ret != 0))
1339 return ret;
1340
1341 user_srf = container_of(srf, struct vmw_user_surface, srf);
1342 if (drm_is_primary_client(file_priv))
1343 user_srf->master = drm_master_get(file_priv->master);
1344
1345 ret = ttm_read_lock(&dev_priv->reservation_sem, true);
1346 if (unlikely(ret != 0))
1347 return ret;
1348
1349 res = &user_srf->srf.res;
1350
1351
1352 if (req->buffer_handle != SVGA3D_INVALID_ID) {
1353 ret = vmw_user_bo_lookup(tfile, req->buffer_handle,
1354 &res->backup,
1355 &user_srf->backup_base);
1356 if (ret == 0) {
1357 if (res->backup->base.num_pages * PAGE_SIZE <
1358 res->backup_size) {
1359 DRM_ERROR("Surface backup buffer is too small.\n");
1360 vmw_bo_unreference(&res->backup);
1361 ret = -EINVAL;
1362 goto out_unlock;
1363 } else {
1364 backup_handle = req->buffer_handle;
1365 }
1366 }
1367 } else if (req->drm_surface_flags & drm_vmw_surface_flag_create_buffer)
1368 ret = vmw_user_bo_alloc(dev_priv, tfile,
1369 res->backup_size,
1370 req->drm_surface_flags &
1371 drm_vmw_surface_flag_shareable,
1372 &backup_handle,
1373 &res->backup,
1374 &user_srf->backup_base);
1375
1376 if (unlikely(ret != 0)) {
1377 vmw_resource_unreference(&res);
1378 goto out_unlock;
1379 }
1380
1381 tmp = vmw_resource_reference(res);
1382 ret = ttm_prime_object_init(tfile, res->backup_size, &user_srf->prime,
1383 req->drm_surface_flags &
1384 drm_vmw_surface_flag_shareable,
1385 VMW_RES_SURFACE,
1386 &vmw_user_surface_base_release, NULL);
1387
1388 if (unlikely(ret != 0)) {
1389 vmw_resource_unreference(&tmp);
1390 vmw_resource_unreference(&res);
1391 goto out_unlock;
1392 }
1393
1394 rep->handle = user_srf->prime.base.hash.key;
1395 rep->backup_size = res->backup_size;
1396 if (res->backup) {
1397 rep->buffer_map_handle =
1398 drm_vma_node_offset_addr(&res->backup->base.vma_node);
1399 rep->buffer_size = res->backup->base.num_pages * PAGE_SIZE;
1400 rep->buffer_handle = backup_handle;
1401 } else {
1402 rep->buffer_map_handle = 0;
1403 rep->buffer_size = 0;
1404 rep->buffer_handle = SVGA3D_INVALID_ID;
1405 }
1406 1318
1407 vmw_resource_unreference(&res); 1319 req_ext.base = arg->req;
1320 req_ext.version = drm_vmw_gb_surface_v1;
1321 req_ext.svga3d_flags_upper_32_bits = 0;
1322 req_ext.multisample_pattern = SVGA3D_MS_PATTERN_NONE;
1323 req_ext.quality_level = SVGA3D_MS_QUALITY_NONE;
1324 req_ext.must_be_zero = 0;
1408 1325
1409out_unlock: 1326 return vmw_gb_surface_define_internal(dev, &req_ext, rep, file_priv);
1410 ttm_read_unlock(&dev_priv->reservation_sem);
1411 return ret;
1412} 1327}
1413 1328
1414/** 1329/**
1415 * vmw_gb_surface_reference_ioctl - Ioctl function implementing 1330 * vmw_gb_surface_reference_ioctl - Ioctl function implementing
1416 * the user surface reference functionality. 1331 * the user surface reference functionality.
1417 * 1332 *
1418 * @dev: Pointer to a struct drm_device. 1333 * @dev: Pointer to a struct drm_device.
1419 * @data: Pointer to data copied from / to user-space. 1334 * @data: Pointer to data copied from / to user-space.
1420 * @file_priv: Pointer to a drm file private structure. 1335 * @file_priv: Pointer to a drm file private structure.
1421 */ 1336 */
1422int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data, 1337int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data,
1423 struct drm_file *file_priv) 1338 struct drm_file *file_priv)
1424{ 1339{
1425 struct vmw_private *dev_priv = vmw_priv(dev);
1426 union drm_vmw_gb_surface_reference_arg *arg = 1340 union drm_vmw_gb_surface_reference_arg *arg =
1427 (union drm_vmw_gb_surface_reference_arg *)data; 1341 (union drm_vmw_gb_surface_reference_arg *)data;
1428 struct drm_vmw_surface_arg *req = &arg->req; 1342 struct drm_vmw_surface_arg *req = &arg->req;
1429 struct drm_vmw_gb_surface_ref_rep *rep = &arg->rep; 1343 struct drm_vmw_gb_surface_ref_rep *rep = &arg->rep;
1430 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 1344 struct drm_vmw_gb_surface_ref_ext_rep rep_ext;
1431 struct vmw_surface *srf; 1345 int ret;
1432 struct vmw_user_surface *user_srf; 1346
1433 struct ttm_base_object *base; 1347 ret = vmw_gb_surface_reference_internal(dev, req, &rep_ext, file_priv);
1434 uint32_t backup_handle;
1435 int ret = -EINVAL;
1436 1348
1437 ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid,
1438 req->handle_type, &base);
1439 if (unlikely(ret != 0)) 1349 if (unlikely(ret != 0))
1440 return ret; 1350 return ret;
1441 1351
1442 user_srf = container_of(base, struct vmw_user_surface, prime.base); 1352 rep->creq = rep_ext.creq.base;
1443 srf = &user_srf->srf; 1353 rep->crep = rep_ext.crep;
1444 if (!srf->res.backup) {
1445 DRM_ERROR("Shared GB surface is missing a backup buffer.\n");
1446 goto out_bad_resource;
1447 }
1448
1449 mutex_lock(&dev_priv->cmdbuf_mutex); /* Protect res->backup */
1450 ret = vmw_user_bo_reference(tfile, srf->res.backup, &backup_handle);
1451 mutex_unlock(&dev_priv->cmdbuf_mutex);
1452
1453 if (unlikely(ret != 0)) {
1454 DRM_ERROR("Could not add a reference to a GB surface "
1455 "backup buffer.\n");
1456 (void) ttm_ref_object_base_unref(tfile, base->hash.key,
1457 TTM_REF_USAGE);
1458 goto out_bad_resource;
1459 }
1460
1461 rep->creq.svga3d_flags = (uint32_t)srf->flags;
1462 rep->creq.format = srf->format;
1463 rep->creq.mip_levels = srf->mip_levels[0];
1464 rep->creq.drm_surface_flags = 0;
1465 rep->creq.multisample_count = srf->multisample_count;
1466 rep->creq.autogen_filter = srf->autogen_filter;
1467 rep->creq.array_size = srf->array_size;
1468 rep->creq.buffer_handle = backup_handle;
1469 rep->creq.base_size = srf->base_size;
1470 rep->crep.handle = user_srf->prime.base.hash.key;
1471 rep->crep.backup_size = srf->res.backup_size;
1472 rep->crep.buffer_handle = backup_handle;
1473 rep->crep.buffer_map_handle =
1474 drm_vma_node_offset_addr(&srf->res.backup->base.vma_node);
1475 rep->crep.buffer_size = srf->res.backup->base.num_pages * PAGE_SIZE;
1476
1477out_bad_resource:
1478 ttm_base_object_unref(&base);
1479 1354
1480 return ret; 1355 return ret;
1481} 1356}
@@ -1493,6 +1368,8 @@ out_bad_resource:
1493 * @multisample_count: 1368 * @multisample_count:
1494 * @array_size: Surface array size. 1369 * @array_size: Surface array size.
1495 * @size: width, heigh, depth of the surface requested 1370 * @size: width, heigh, depth of the surface requested
1371 * @multisample_pattern: Multisampling pattern when msaa is supported
1372 * @quality_level: Precision settings
1496 * @user_srf_out: allocated user_srf. Set to NULL on failure. 1373 * @user_srf_out: allocated user_srf. Set to NULL on failure.
1497 * 1374 *
1498 * GB surfaces allocated by this function will not have a user mode handle, and 1375 * GB surfaces allocated by this function will not have a user mode handle, and
@@ -1509,6 +1386,8 @@ int vmw_surface_gb_priv_define(struct drm_device *dev,
1509 uint32_t multisample_count, 1386 uint32_t multisample_count,
1510 uint32_t array_size, 1387 uint32_t array_size,
1511 struct drm_vmw_size size, 1388 struct drm_vmw_size size,
1389 SVGA3dMSPattern multisample_pattern,
1390 SVGA3dMSQualityLevel quality_level,
1512 struct vmw_surface **srf_out) 1391 struct vmw_surface **srf_out)
1513{ 1392{
1514 struct vmw_private *dev_priv = vmw_priv(dev); 1393 struct vmw_private *dev_priv = vmw_priv(dev);
@@ -1519,7 +1398,7 @@ int vmw_surface_gb_priv_define(struct drm_device *dev,
1519 }; 1398 };
1520 struct vmw_surface *srf; 1399 struct vmw_surface *srf;
1521 int ret; 1400 int ret;
1522 u32 num_layers; 1401 u32 num_layers = 1;
1523 1402
1524 *srf_out = NULL; 1403 *srf_out = NULL;
1525 1404
@@ -1594,15 +1473,13 @@ int vmw_surface_gb_priv_define(struct drm_device *dev,
1594 srf->autogen_filter = SVGA3D_TEX_FILTER_NONE; 1473 srf->autogen_filter = SVGA3D_TEX_FILTER_NONE;
1595 srf->array_size = array_size; 1474 srf->array_size = array_size;
1596 srf->multisample_count = multisample_count; 1475 srf->multisample_count = multisample_count;
1597 srf->multisample_pattern = SVGA3D_MS_PATTERN_NONE; 1476 srf->multisample_pattern = multisample_pattern;
1598 srf->quality_level = SVGA3D_MS_QUALITY_NONE; 1477 srf->quality_level = quality_level;
1599 1478
1600 if (array_size) 1479 if (array_size)
1601 num_layers = array_size; 1480 num_layers = array_size;
1602 else if (svga3d_flags & SVGA3D_SURFACE_CUBEMAP) 1481 else if (svga3d_flags & SVGA3D_SURFACE_CUBEMAP)
1603 num_layers = SVGA3D_MAX_SURFACE_FACES; 1482 num_layers = SVGA3D_MAX_SURFACE_FACES;
1604 else
1605 num_layers = 1;
1606 1483
1607 srf->res.backup_size = 1484 srf->res.backup_size =
1608 svga3dsurface_get_serialized_size(srf->format, 1485 svga3dsurface_get_serialized_size(srf->format,
@@ -1633,3 +1510,262 @@ out_unlock:
1633 ttm_read_unlock(&dev_priv->reservation_sem); 1510 ttm_read_unlock(&dev_priv->reservation_sem);
1634 return ret; 1511 return ret;
1635} 1512}
1513
1514/**
1515 * vmw_gb_surface_define_ext_ioctl - Ioctl function implementing
1516 * the user surface define functionality.
1517 *
1518 * @dev: Pointer to a struct drm_device.
1519 * @data: Pointer to data copied from / to user-space.
1520 * @file_priv: Pointer to a drm file private structure.
1521 */
1522int vmw_gb_surface_define_ext_ioctl(struct drm_device *dev, void *data,
1523 struct drm_file *file_priv)
1524{
1525 union drm_vmw_gb_surface_create_ext_arg *arg =
1526 (union drm_vmw_gb_surface_create_ext_arg *)data;
1527 struct drm_vmw_gb_surface_create_ext_req *req = &arg->req;
1528 struct drm_vmw_gb_surface_create_rep *rep = &arg->rep;
1529
1530 return vmw_gb_surface_define_internal(dev, req, rep, file_priv);
1531}
1532
1533/**
1534 * vmw_gb_surface_reference_ext_ioctl - Ioctl function implementing
1535 * the user surface reference functionality.
1536 *
1537 * @dev: Pointer to a struct drm_device.
1538 * @data: Pointer to data copied from / to user-space.
1539 * @file_priv: Pointer to a drm file private structure.
1540 */
1541int vmw_gb_surface_reference_ext_ioctl(struct drm_device *dev, void *data,
1542 struct drm_file *file_priv)
1543{
1544 union drm_vmw_gb_surface_reference_ext_arg *arg =
1545 (union drm_vmw_gb_surface_reference_ext_arg *)data;
1546 struct drm_vmw_surface_arg *req = &arg->req;
1547 struct drm_vmw_gb_surface_ref_ext_rep *rep = &arg->rep;
1548
1549 return vmw_gb_surface_reference_internal(dev, req, rep, file_priv);
1550}
1551
1552/**
1553 * vmw_gb_surface_define_internal - Ioctl function implementing
1554 * the user surface define functionality.
1555 *
1556 * @dev: Pointer to a struct drm_device.
1557 * @req: Request argument from user-space.
1558 * @rep: Response argument to user-space.
1559 * @file_priv: Pointer to a drm file private structure.
1560 */
1561static int
1562vmw_gb_surface_define_internal(struct drm_device *dev,
1563 struct drm_vmw_gb_surface_create_ext_req *req,
1564 struct drm_vmw_gb_surface_create_rep *rep,
1565 struct drm_file *file_priv)
1566{
1567 struct vmw_private *dev_priv = vmw_priv(dev);
1568 struct vmw_user_surface *user_srf;
1569 struct vmw_surface *srf;
1570 struct vmw_resource *res;
1571 struct vmw_resource *tmp;
1572 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
1573 int ret;
1574 uint32_t size;
1575 uint32_t backup_handle = 0;
1576 SVGA3dSurfaceAllFlags svga3d_flags_64 =
1577 SVGA3D_FLAGS_64(req->svga3d_flags_upper_32_bits,
1578 req->base.svga3d_flags);
1579
1580 if (!dev_priv->has_sm4_1) {
1581 /*
1582 * If SM4_1 is not support then cannot send 64-bit flag to
1583 * device.
1584 */
1585 if (req->svga3d_flags_upper_32_bits != 0)
1586 return -EINVAL;
1587
1588 if (req->base.multisample_count != 0)
1589 return -EINVAL;
1590
1591 if (req->multisample_pattern != SVGA3D_MS_PATTERN_NONE)
1592 return -EINVAL;
1593
1594 if (req->quality_level != SVGA3D_MS_QUALITY_NONE)
1595 return -EINVAL;
1596 }
1597
1598 if (req->base.mip_levels > DRM_VMW_MAX_MIP_LEVELS)
1599 return -EINVAL;
1600
1601 if (unlikely(vmw_user_surface_size == 0))
1602 vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
1603 128;
1604
1605 size = vmw_user_surface_size + 128;
1606
1607 /* Define a surface based on the parameters. */
1608 ret = vmw_surface_gb_priv_define(dev,
1609 size,
1610 svga3d_flags_64,
1611 req->base.format,
1612 req->base.drm_surface_flags &
1613 drm_vmw_surface_flag_scanout,
1614 req->base.mip_levels,
1615 req->base.multisample_count,
1616 req->base.array_size,
1617 req->base.base_size,
1618 req->multisample_pattern,
1619 req->quality_level,
1620 &srf);
1621 if (unlikely(ret != 0))
1622 return ret;
1623
1624 user_srf = container_of(srf, struct vmw_user_surface, srf);
1625 if (drm_is_primary_client(file_priv))
1626 user_srf->master = drm_master_get(file_priv->master);
1627
1628 ret = ttm_read_lock(&dev_priv->reservation_sem, true);
1629 if (unlikely(ret != 0))
1630 return ret;
1631
1632 res = &user_srf->srf.res;
1633
1634 if (req->base.buffer_handle != SVGA3D_INVALID_ID) {
1635 ret = vmw_user_bo_lookup(tfile, req->base.buffer_handle,
1636 &res->backup,
1637 &user_srf->backup_base);
1638 if (ret == 0) {
1639 if (res->backup->base.num_pages * PAGE_SIZE <
1640 res->backup_size) {
1641 DRM_ERROR("Surface backup buffer too small.\n");
1642 vmw_bo_unreference(&res->backup);
1643 ret = -EINVAL;
1644 goto out_unlock;
1645 } else {
1646 backup_handle = req->base.buffer_handle;
1647 }
1648 }
1649 } else if (req->base.drm_surface_flags &
1650 drm_vmw_surface_flag_create_buffer)
1651 ret = vmw_user_bo_alloc(dev_priv, tfile,
1652 res->backup_size,
1653 req->base.drm_surface_flags &
1654 drm_vmw_surface_flag_shareable,
1655 &backup_handle,
1656 &res->backup,
1657 &user_srf->backup_base);
1658
1659 if (unlikely(ret != 0)) {
1660 vmw_resource_unreference(&res);
1661 goto out_unlock;
1662 }
1663
1664 tmp = vmw_resource_reference(res);
1665 ret = ttm_prime_object_init(tfile, res->backup_size, &user_srf->prime,
1666 req->base.drm_surface_flags &
1667 drm_vmw_surface_flag_shareable,
1668 VMW_RES_SURFACE,
1669 &vmw_user_surface_base_release, NULL);
1670
1671 if (unlikely(ret != 0)) {
1672 vmw_resource_unreference(&tmp);
1673 vmw_resource_unreference(&res);
1674 goto out_unlock;
1675 }
1676
1677 rep->handle = user_srf->prime.base.hash.key;
1678 rep->backup_size = res->backup_size;
1679 if (res->backup) {
1680 rep->buffer_map_handle =
1681 drm_vma_node_offset_addr(&res->backup->base.vma_node);
1682 rep->buffer_size = res->backup->base.num_pages * PAGE_SIZE;
1683 rep->buffer_handle = backup_handle;
1684 } else {
1685 rep->buffer_map_handle = 0;
1686 rep->buffer_size = 0;
1687 rep->buffer_handle = SVGA3D_INVALID_ID;
1688 }
1689
1690 vmw_resource_unreference(&res);
1691
1692out_unlock:
1693 ttm_read_unlock(&dev_priv->reservation_sem);
1694 return ret;
1695}
1696
1697/**
1698 * vmw_gb_surface_reference_internal - Ioctl function implementing
1699 * the user surface reference functionality.
1700 *
1701 * @dev: Pointer to a struct drm_device.
1702 * @req: Pointer to user-space request surface arg.
1703 * @rep: Pointer to response to user-space.
1704 * @file_priv: Pointer to a drm file private structure.
1705 */
1706static int
1707vmw_gb_surface_reference_internal(struct drm_device *dev,
1708 struct drm_vmw_surface_arg *req,
1709 struct drm_vmw_gb_surface_ref_ext_rep *rep,
1710 struct drm_file *file_priv)
1711{
1712 struct vmw_private *dev_priv = vmw_priv(dev);
1713 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
1714 struct vmw_surface *srf;
1715 struct vmw_user_surface *user_srf;
1716 struct ttm_base_object *base;
1717 uint32_t backup_handle;
1718 int ret = -EINVAL;
1719
1720 ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid,
1721 req->handle_type, &base);
1722 if (unlikely(ret != 0))
1723 return ret;
1724
1725 user_srf = container_of(base, struct vmw_user_surface, prime.base);
1726 srf = &user_srf->srf;
1727 if (!srf->res.backup) {
1728 DRM_ERROR("Shared GB surface is missing a backup buffer.\n");
1729 goto out_bad_resource;
1730 }
1731
1732 mutex_lock(&dev_priv->cmdbuf_mutex); /* Protect res->backup */
1733 ret = vmw_user_bo_reference(tfile, srf->res.backup, &backup_handle);
1734 mutex_unlock(&dev_priv->cmdbuf_mutex);
1735
1736 if (unlikely(ret != 0)) {
1737 DRM_ERROR("Could not add a reference to a GB surface "
1738 "backup buffer.\n");
1739 (void) ttm_ref_object_base_unref(tfile, base->hash.key,
1740 TTM_REF_USAGE);
1741 goto out_bad_resource;
1742 }
1743
1744 rep->creq.base.svga3d_flags = SVGA3D_FLAGS_LOWER_32(srf->flags);
1745 rep->creq.base.format = srf->format;
1746 rep->creq.base.mip_levels = srf->mip_levels[0];
1747 rep->creq.base.drm_surface_flags = 0;
1748 rep->creq.base.multisample_count = srf->multisample_count;
1749 rep->creq.base.autogen_filter = srf->autogen_filter;
1750 rep->creq.base.array_size = srf->array_size;
1751 rep->creq.base.buffer_handle = backup_handle;
1752 rep->creq.base.base_size = srf->base_size;
1753 rep->crep.handle = user_srf->prime.base.hash.key;
1754 rep->crep.backup_size = srf->res.backup_size;
1755 rep->crep.buffer_handle = backup_handle;
1756 rep->crep.buffer_map_handle =
1757 drm_vma_node_offset_addr(&srf->res.backup->base.vma_node);
1758 rep->crep.buffer_size = srf->res.backup->base.num_pages * PAGE_SIZE;
1759
1760 rep->creq.version = drm_vmw_gb_surface_v1;
1761 rep->creq.svga3d_flags_upper_32_bits =
1762 SVGA3D_FLAGS_UPPER_32(srf->flags);
1763 rep->creq.multisample_pattern = srf->multisample_pattern;
1764 rep->creq.quality_level = srf->quality_level;
1765 rep->creq.must_be_zero = 0;
1766
1767out_bad_resource:
1768 ttm_base_object_unref(&base);
1769
1770 return ret;
1771}