Home | History | Annotate | Line # | Download | only in vmwgfx
vmwgfx_surface.c revision 1.1.1.2.28.1
      1 /*	$NetBSD: vmwgfx_surface.c,v 1.1.1.2.28.1 2018/09/06 06:56:34 pgoyette Exp $	*/
      2 
      3 /**************************************************************************
      4  *
      5  * Copyright  2009-2015 VMware, Inc., Palo Alto, CA., USA
      6  * All Rights Reserved.
      7  *
      8  * Permission is hereby granted, free of charge, to any person obtaining a
      9  * copy of this software and associated documentation files (the
     10  * "Software"), to deal in the Software without restriction, including
     11  * without limitation the rights to use, copy, modify, merge, publish,
     12  * distribute, sub license, and/or sell copies of the Software, and to
     13  * permit persons to whom the Software is furnished to do so, subject to
     14  * the following conditions:
     15  *
     16  * The above copyright notice and this permission notice (including the
     17  * next paragraph) shall be included in all copies or substantial portions
     18  * of the Software.
     19  *
     20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     22  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
     23  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
     24  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     25  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     26  * USE OR OTHER DEALINGS IN THE SOFTWARE.
     27  *
     28  **************************************************************************/
     29 
     30 #include <sys/cdefs.h>
     31 __KERNEL_RCSID(0, "$NetBSD: vmwgfx_surface.c,v 1.1.1.2.28.1 2018/09/06 06:56:34 pgoyette Exp $");
     32 
     33 #include "vmwgfx_drv.h"
     34 #include "vmwgfx_resource_priv.h"
     35 #include "vmwgfx_so.h"
     36 #include "vmwgfx_binding.h"
     37 #include <ttm/ttm_placement.h>
     38 #include "device_include/svga3d_surfacedefs.h"
     39 
     40 
     41 /**
     42  * struct vmw_user_surface - User-space visible surface resource
     43  *
     44  * @base:           The TTM base object handling user-space visibility.
     45  * @srf:            The surface metadata.
     46  * @size:           TTM accounting size for the surface.
     47  * @master: master of the creating client. Used for security check.
     48  */
     49 struct vmw_user_surface {
     50 	struct ttm_prime_object prime;
     51 	struct vmw_surface srf;
     52 	uint32_t size;
     53 	struct drm_master *master;
     54 	struct ttm_base_object *backup_base;
     55 };
     56 
     57 /**
     58  * struct vmw_surface_offset - Backing store mip level offset info
     59  *
     60  * @face:           Surface face.
     61  * @mip:            Mip level.
     62  * @bo_offset:      Offset into backing store of this mip level.
     63  *
     64  */
     65 struct vmw_surface_offset {
     66 	uint32_t face;
     67 	uint32_t mip;
     68 	uint32_t bo_offset;
     69 };
     70 
     71 static void vmw_user_surface_free(struct vmw_resource *res);
     72 static struct vmw_resource *
     73 vmw_user_surface_base_to_res(struct ttm_base_object *base);
     74 static int vmw_legacy_srf_bind(struct vmw_resource *res,
     75 			       struct ttm_validate_buffer *val_buf);
     76 static int vmw_legacy_srf_unbind(struct vmw_resource *res,
     77 				 bool readback,
     78 				 struct ttm_validate_buffer *val_buf);
     79 static int vmw_legacy_srf_create(struct vmw_resource *res);
     80 static int vmw_legacy_srf_destroy(struct vmw_resource *res);
     81 static int vmw_gb_surface_create(struct vmw_resource *res);
     82 static int vmw_gb_surface_bind(struct vmw_resource *res,
     83 			       struct ttm_validate_buffer *val_buf);
     84 static int vmw_gb_surface_unbind(struct vmw_resource *res,
     85 				 bool readback,
     86 				 struct ttm_validate_buffer *val_buf);
     87 static int vmw_gb_surface_destroy(struct vmw_resource *res);
     88 
     89 
     90 static const struct vmw_user_resource_conv user_surface_conv = {
     91 	.object_type = VMW_RES_SURFACE,
     92 	.base_obj_to_res = vmw_user_surface_base_to_res,
     93 	.res_free = vmw_user_surface_free
     94 };
     95 
     96 const struct vmw_user_resource_conv *user_surface_converter =
     97 	&user_surface_conv;
     98 
     99 
    100 static uint64_t vmw_user_surface_size;
    101 
    102 static const struct vmw_res_func vmw_legacy_surface_func = {
    103 	.res_type = vmw_res_surface,
    104 	.needs_backup = false,
    105 	.may_evict = true,
    106 	.type_name = "legacy surfaces",
    107 	.backup_placement = &vmw_srf_placement,
    108 	.create = &vmw_legacy_srf_create,
    109 	.destroy = &vmw_legacy_srf_destroy,
    110 	.bind = &vmw_legacy_srf_bind,
    111 	.unbind = &vmw_legacy_srf_unbind
    112 };
    113 
    114 static const struct vmw_res_func vmw_gb_surface_func = {
    115 	.res_type = vmw_res_surface,
    116 	.needs_backup = true,
    117 	.may_evict = true,
    118 	.type_name = "guest backed surfaces",
    119 	.backup_placement = &vmw_mob_placement,
    120 	.create = vmw_gb_surface_create,
    121 	.destroy = vmw_gb_surface_destroy,
    122 	.bind = vmw_gb_surface_bind,
    123 	.unbind = vmw_gb_surface_unbind
    124 };
    125 
    126 /**
    127  * struct vmw_surface_dma - SVGA3D DMA command
    128  */
    129 struct vmw_surface_dma {
    130 	SVGA3dCmdHeader header;
    131 	SVGA3dCmdSurfaceDMA body;
    132 	SVGA3dCopyBox cb;
    133 	SVGA3dCmdSurfaceDMASuffix suffix;
    134 };
    135 
    136 /**
    137  * struct vmw_surface_define - SVGA3D Surface Define command
    138  */
    139 struct vmw_surface_define {
    140 	SVGA3dCmdHeader header;
    141 	SVGA3dCmdDefineSurface body;
    142 };
    143 
    144 /**
    145  * struct vmw_surface_destroy - SVGA3D Surface Destroy command
    146  */
    147 struct vmw_surface_destroy {
    148 	SVGA3dCmdHeader header;
    149 	SVGA3dCmdDestroySurface body;
    150 };
    151 
    152 
    153 /**
    154  * vmw_surface_dma_size - Compute fifo size for a dma command.
    155  *
    156  * @srf: Pointer to a struct vmw_surface
    157  *
    158  * Computes the required size for a surface dma command for backup or
    159  * restoration of the surface represented by @srf.
    160  */
    161 static inline uint32_t vmw_surface_dma_size(const struct vmw_surface *srf)
    162 {
    163 	return srf->num_sizes * sizeof(struct vmw_surface_dma);
    164 }
    165 
    166 
    167 /**
    168  * vmw_surface_define_size - Compute fifo size for a surface define command.
    169  *
    170  * @srf: Pointer to a struct vmw_surface
    171  *
    172  * Computes the required size for a surface define command for the definition
    173  * of the surface represented by @srf.
    174  */
    175 static inline uint32_t vmw_surface_define_size(const struct vmw_surface *srf)
    176 {
    177 	return sizeof(struct vmw_surface_define) + srf->num_sizes *
    178 		sizeof(SVGA3dSize);
    179 }
    180 
    181 
    182 /**
    183  * vmw_surface_destroy_size - Compute fifo size for a surface destroy command.
    184  *
    185  * Computes the required size for a surface destroy command for the destruction
    186  * of a hw surface.
    187  */
    188 static inline uint32_t vmw_surface_destroy_size(void)
    189 {
    190 	return sizeof(struct vmw_surface_destroy);
    191 }
    192 
    193 /**
    194  * vmw_surface_destroy_encode - Encode a surface_destroy command.
    195  *
    196  * @id: The surface id
    197  * @cmd_space: Pointer to memory area in which the commands should be encoded.
    198  */
    199 static void vmw_surface_destroy_encode(uint32_t id,
    200 				       void *cmd_space)
    201 {
    202 	struct vmw_surface_destroy *cmd = (struct vmw_surface_destroy *)
    203 		cmd_space;
    204 
    205 	cmd->header.id = SVGA_3D_CMD_SURFACE_DESTROY;
    206 	cmd->header.size = sizeof(cmd->body);
    207 	cmd->body.sid = id;
    208 }
    209 
    210 /**
    211  * vmw_surface_define_encode - Encode a surface_define command.
    212  *
    213  * @srf: Pointer to a struct vmw_surface object.
    214  * @cmd_space: Pointer to memory area in which the commands should be encoded.
    215  */
    216 static void vmw_surface_define_encode(const struct vmw_surface *srf,
    217 				      void *cmd_space)
    218 {
    219 	struct vmw_surface_define *cmd = (struct vmw_surface_define *)
    220 		cmd_space;
    221 	struct drm_vmw_size *src_size;
    222 	SVGA3dSize *cmd_size;
    223 	uint32_t cmd_len;
    224 	int i;
    225 
    226 	cmd_len = sizeof(cmd->body) + srf->num_sizes * sizeof(SVGA3dSize);
    227 
    228 	cmd->header.id = SVGA_3D_CMD_SURFACE_DEFINE;
    229 	cmd->header.size = cmd_len;
    230 	cmd->body.sid = srf->res.id;
    231 	cmd->body.surfaceFlags = srf->flags;
    232 	cmd->body.format = srf->format;
    233 	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i)
    234 		cmd->body.face[i].numMipLevels = srf->mip_levels[i];
    235 
    236 	cmd += 1;
    237 	cmd_size = (SVGA3dSize *) cmd;
    238 	src_size = srf->sizes;
    239 
    240 	for (i = 0; i < srf->num_sizes; ++i, cmd_size++, src_size++) {
    241 		cmd_size->width = src_size->width;
    242 		cmd_size->height = src_size->height;
    243 		cmd_size->depth = src_size->depth;
    244 	}
    245 }
    246 
    247 /**
    248  * vmw_surface_dma_encode - Encode a surface_dma command.
    249  *
    250  * @srf: Pointer to a struct vmw_surface object.
    251  * @cmd_space: Pointer to memory area in which the commands should be encoded.
    252  * @ptr: Pointer to an SVGAGuestPtr indicating where the surface contents
    253  * should be placed or read from.
    254  * @to_surface: Boolean whether to DMA to the surface or from the surface.
    255  */
    256 static void vmw_surface_dma_encode(struct vmw_surface *srf,
    257 				   void *cmd_space,
    258 				   const SVGAGuestPtr *ptr,
    259 				   bool to_surface)
    260 {
    261 	uint32_t i;
    262 	struct vmw_surface_dma *cmd = (struct vmw_surface_dma *)cmd_space;
    263 	const struct svga3d_surface_desc *desc =
    264 		svga3dsurface_get_desc(srf->format);
    265 
    266 	for (i = 0; i < srf->num_sizes; ++i) {
    267 		SVGA3dCmdHeader *header = &cmd->header;
    268 		SVGA3dCmdSurfaceDMA *body = &cmd->body;
    269 		SVGA3dCopyBox *cb = &cmd->cb;
    270 		SVGA3dCmdSurfaceDMASuffix *suffix = &cmd->suffix;
    271 		const struct vmw_surface_offset *cur_offset = &srf->offsets[i];
    272 		const struct drm_vmw_size *cur_size = &srf->sizes[i];
    273 
    274 		header->id = SVGA_3D_CMD_SURFACE_DMA;
    275 		header->size = sizeof(*body) + sizeof(*cb) + sizeof(*suffix);
    276 
    277 		body->guest.ptr = *ptr;
    278 		body->guest.ptr.offset += cur_offset->bo_offset;
    279 		body->guest.pitch = svga3dsurface_calculate_pitch(desc,
    280 								  cur_size);
    281 		body->host.sid = srf->res.id;
    282 		body->host.face = cur_offset->face;
    283 		body->host.mipmap = cur_offset->mip;
    284 		body->transfer = ((to_surface) ?  SVGA3D_WRITE_HOST_VRAM :
    285 				  SVGA3D_READ_HOST_VRAM);
    286 		cb->x = 0;
    287 		cb->y = 0;
    288 		cb->z = 0;
    289 		cb->srcx = 0;
    290 		cb->srcy = 0;
    291 		cb->srcz = 0;
    292 		cb->w = cur_size->width;
    293 		cb->h = cur_size->height;
    294 		cb->d = cur_size->depth;
    295 
    296 		suffix->suffixSize = sizeof(*suffix);
    297 		suffix->maximumOffset =
    298 			svga3dsurface_get_image_buffer_size(desc, cur_size,
    299 							    body->guest.pitch);
    300 		suffix->flags.discard = 0;
    301 		suffix->flags.unsynchronized = 0;
    302 		suffix->flags.reserved = 0;
    303 		++cmd;
    304 	}
    305 };
    306 
    307 
    308 /**
    309  * vmw_hw_surface_destroy - destroy a Device surface
    310  *
    311  * @res:        Pointer to a struct vmw_resource embedded in a struct
    312  *              vmw_surface.
    313  *
    314  * Destroys a the device surface associated with a struct vmw_surface if
    315  * any, and adjusts accounting and resource count accordingly.
    316  */
    317 static void vmw_hw_surface_destroy(struct vmw_resource *res)
    318 {
    319 
    320 	struct vmw_private *dev_priv = res->dev_priv;
    321 	struct vmw_surface *srf;
    322 	void *cmd;
    323 
    324 	if (res->func->destroy == vmw_gb_surface_destroy) {
    325 		(void) vmw_gb_surface_destroy(res);
    326 		return;
    327 	}
    328 
    329 	if (res->id != -1) {
    330 
    331 		cmd = vmw_fifo_reserve(dev_priv, vmw_surface_destroy_size());
    332 		if (unlikely(cmd == NULL)) {
    333 			DRM_ERROR("Failed reserving FIFO space for surface "
    334 				  "destruction.\n");
    335 			return;
    336 		}
    337 
    338 		vmw_surface_destroy_encode(res->id, cmd);
    339 		vmw_fifo_commit(dev_priv, vmw_surface_destroy_size());
    340 
    341 		/*
    342 		 * used_memory_size_atomic, or separate lock
    343 		 * to avoid taking dev_priv::cmdbuf_mutex in
    344 		 * the destroy path.
    345 		 */
    346 
    347 		mutex_lock(&dev_priv->cmdbuf_mutex);
    348 		srf = vmw_res_to_srf(res);
    349 		dev_priv->used_memory_size -= res->backup_size;
    350 		mutex_unlock(&dev_priv->cmdbuf_mutex);
    351 	}
    352 	vmw_fifo_resource_dec(dev_priv);
    353 }
    354 
    355 /**
    356  * vmw_legacy_srf_create - Create a device surface as part of the
    357  * resource validation process.
    358  *
    359  * @res: Pointer to a struct vmw_surface.
    360  *
    361  * If the surface doesn't have a hw id.
    362  *
    363  * Returns -EBUSY if there wasn't sufficient device resources to
    364  * complete the validation. Retry after freeing up resources.
    365  *
    366  * May return other errors if the kernel is out of guest resources.
    367  */
    368 static int vmw_legacy_srf_create(struct vmw_resource *res)
    369 {
    370 	struct vmw_private *dev_priv = res->dev_priv;
    371 	struct vmw_surface *srf;
    372 	uint32_t submit_size;
    373 	uint8_t *cmd;
    374 	int ret;
    375 
    376 	if (likely(res->id != -1))
    377 		return 0;
    378 
    379 	srf = vmw_res_to_srf(res);
    380 	if (unlikely(dev_priv->used_memory_size + res->backup_size >=
    381 		     dev_priv->memory_size))
    382 		return -EBUSY;
    383 
    384 	/*
    385 	 * Alloc id for the resource.
    386 	 */
    387 
    388 	ret = vmw_resource_alloc_id(res);
    389 	if (unlikely(ret != 0)) {
    390 		DRM_ERROR("Failed to allocate a surface id.\n");
    391 		goto out_no_id;
    392 	}
    393 
    394 	if (unlikely(res->id >= SVGA3D_MAX_SURFACE_IDS)) {
    395 		ret = -EBUSY;
    396 		goto out_no_fifo;
    397 	}
    398 
    399 	/*
    400 	 * Encode surface define- commands.
    401 	 */
    402 
    403 	submit_size = vmw_surface_define_size(srf);
    404 	cmd = vmw_fifo_reserve(dev_priv, submit_size);
    405 	if (unlikely(cmd == NULL)) {
    406 		DRM_ERROR("Failed reserving FIFO space for surface "
    407 			  "creation.\n");
    408 		ret = -ENOMEM;
    409 		goto out_no_fifo;
    410 	}
    411 
    412 	vmw_surface_define_encode(srf, cmd);
    413 	vmw_fifo_commit(dev_priv, submit_size);
    414 	/*
    415 	 * Surface memory usage accounting.
    416 	 */
    417 
    418 	dev_priv->used_memory_size += res->backup_size;
    419 	return 0;
    420 
    421 out_no_fifo:
    422 	vmw_resource_release_id(res);
    423 out_no_id:
    424 	return ret;
    425 }
    426 
    427 /**
    428  * vmw_legacy_srf_dma - Copy backup data to or from a legacy surface.
    429  *
    430  * @res:            Pointer to a struct vmw_res embedded in a struct
    431  *                  vmw_surface.
    432  * @val_buf:        Pointer to a struct ttm_validate_buffer containing
    433  *                  information about the backup buffer.
    434  * @bind:           Boolean wether to DMA to the surface.
    435  *
    436  * Transfer backup data to or from a legacy surface as part of the
    437  * validation process.
    438  * May return other errors if the kernel is out of guest resources.
    439  * The backup buffer will be fenced or idle upon successful completion,
    440  * and if the surface needs persistent backup storage, the backup buffer
    441  * will also be returned reserved iff @bind is true.
    442  */
    443 static int vmw_legacy_srf_dma(struct vmw_resource *res,
    444 			      struct ttm_validate_buffer *val_buf,
    445 			      bool bind)
    446 {
    447 	SVGAGuestPtr ptr;
    448 	struct vmw_fence_obj *fence;
    449 	uint32_t submit_size;
    450 	struct vmw_surface *srf = vmw_res_to_srf(res);
    451 	uint8_t *cmd;
    452 	struct vmw_private *dev_priv = res->dev_priv;
    453 
    454 	BUG_ON(val_buf->bo == NULL);
    455 
    456 	submit_size = vmw_surface_dma_size(srf);
    457 	cmd = vmw_fifo_reserve(dev_priv, submit_size);
    458 	if (unlikely(cmd == NULL)) {
    459 		DRM_ERROR("Failed reserving FIFO space for surface "
    460 			  "DMA.\n");
    461 		return -ENOMEM;
    462 	}
    463 	vmw_bo_get_guest_ptr(val_buf->bo, &ptr);
    464 	vmw_surface_dma_encode(srf, cmd, &ptr, bind);
    465 
    466 	vmw_fifo_commit(dev_priv, submit_size);
    467 
    468 	/*
    469 	 * Create a fence object and fence the backup buffer.
    470 	 */
    471 
    472 	(void) vmw_execbuf_fence_commands(NULL, dev_priv,
    473 					  &fence, NULL);
    474 
    475 	vmw_fence_single_bo(val_buf->bo, fence);
    476 
    477 	if (likely(fence != NULL))
    478 		vmw_fence_obj_unreference(&fence);
    479 
    480 	return 0;
    481 }
    482 
    483 /**
    484  * vmw_legacy_srf_bind - Perform a legacy surface bind as part of the
    485  *                       surface validation process.
    486  *
    487  * @res:            Pointer to a struct vmw_res embedded in a struct
    488  *                  vmw_surface.
    489  * @val_buf:        Pointer to a struct ttm_validate_buffer containing
    490  *                  information about the backup buffer.
    491  *
    492  * This function will copy backup data to the surface if the
    493  * backup buffer is dirty.
    494  */
    495 static int vmw_legacy_srf_bind(struct vmw_resource *res,
    496 			       struct ttm_validate_buffer *val_buf)
    497 {
    498 	if (!res->backup_dirty)
    499 		return 0;
    500 
    501 	return vmw_legacy_srf_dma(res, val_buf, true);
    502 }
    503 
    504 
    505 /**
    506  * vmw_legacy_srf_unbind - Perform a legacy surface unbind as part of the
    507  *                         surface eviction process.
    508  *
    509  * @res:            Pointer to a struct vmw_res embedded in a struct
    510  *                  vmw_surface.
    511  * @val_buf:        Pointer to a struct ttm_validate_buffer containing
    512  *                  information about the backup buffer.
    513  *
    514  * This function will copy backup data from the surface.
    515  */
    516 static int vmw_legacy_srf_unbind(struct vmw_resource *res,
    517 				 bool readback,
    518 				 struct ttm_validate_buffer *val_buf)
    519 {
    520 	if (unlikely(readback))
    521 		return vmw_legacy_srf_dma(res, val_buf, false);
    522 	return 0;
    523 }
    524 
    525 /**
    526  * vmw_legacy_srf_destroy - Destroy a device surface as part of a
    527  *                          resource eviction process.
    528  *
    529  * @res:            Pointer to a struct vmw_res embedded in a struct
    530  *                  vmw_surface.
    531  */
    532 static int vmw_legacy_srf_destroy(struct vmw_resource *res)
    533 {
    534 	struct vmw_private *dev_priv = res->dev_priv;
    535 	uint32_t submit_size;
    536 	uint8_t *cmd;
    537 
    538 	BUG_ON(res->id == -1);
    539 
    540 	/*
    541 	 * Encode the dma- and surface destroy commands.
    542 	 */
    543 
    544 	submit_size = vmw_surface_destroy_size();
    545 	cmd = vmw_fifo_reserve(dev_priv, submit_size);
    546 	if (unlikely(cmd == NULL)) {
    547 		DRM_ERROR("Failed reserving FIFO space for surface "
    548 			  "eviction.\n");
    549 		return -ENOMEM;
    550 	}
    551 
    552 	vmw_surface_destroy_encode(res->id, cmd);
    553 	vmw_fifo_commit(dev_priv, submit_size);
    554 
    555 	/*
    556 	 * Surface memory usage accounting.
    557 	 */
    558 
    559 	dev_priv->used_memory_size -= res->backup_size;
    560 
    561 	/*
    562 	 * Release the surface ID.
    563 	 */
    564 
    565 	vmw_resource_release_id(res);
    566 
    567 	return 0;
    568 }
    569 
    570 
    571 /**
    572  * vmw_surface_init - initialize a struct vmw_surface
    573  *
    574  * @dev_priv:       Pointer to a device private struct.
    575  * @srf:            Pointer to the struct vmw_surface to initialize.
    576  * @res_free:       Pointer to a resource destructor used to free
    577  *                  the object.
    578  */
    579 static int vmw_surface_init(struct vmw_private *dev_priv,
    580 			    struct vmw_surface *srf,
    581 			    void (*res_free) (struct vmw_resource *res))
    582 {
    583 	int ret;
    584 	struct vmw_resource *res = &srf->res;
    585 
    586 	BUG_ON(res_free == NULL);
    587 	if (!dev_priv->has_mob)
    588 		vmw_fifo_resource_inc(dev_priv);
    589 	ret = vmw_resource_init(dev_priv, res, true, res_free,
    590 				(dev_priv->has_mob) ? &vmw_gb_surface_func :
    591 				&vmw_legacy_surface_func);
    592 
    593 	if (unlikely(ret != 0)) {
    594 		if (!dev_priv->has_mob)
    595 			vmw_fifo_resource_dec(dev_priv);
    596 		res_free(res);
    597 		return ret;
    598 	}
    599 
    600 	/*
    601 	 * The surface won't be visible to hardware until a
    602 	 * surface validate.
    603 	 */
    604 
    605 	INIT_LIST_HEAD(&srf->view_list);
    606 	vmw_resource_activate(res, vmw_hw_surface_destroy);
    607 	return ret;
    608 }
    609 
    610 /**
    611  * vmw_user_surface_base_to_res - TTM base object to resource converter for
    612  *                                user visible surfaces
    613  *
    614  * @base:           Pointer to a TTM base object
    615  *
    616  * Returns the struct vmw_resource embedded in a struct vmw_surface
    617  * for the user-visible object identified by the TTM base object @base.
    618  */
    619 static struct vmw_resource *
    620 vmw_user_surface_base_to_res(struct ttm_base_object *base)
    621 {
    622 	return &(container_of(base, struct vmw_user_surface,
    623 			      prime.base)->srf.res);
    624 }
    625 
    626 /**
    627  * vmw_user_surface_free - User visible surface resource destructor
    628  *
    629  * @res:            A struct vmw_resource embedded in a struct vmw_surface.
    630  */
    631 static void vmw_user_surface_free(struct vmw_resource *res)
    632 {
    633 	struct vmw_surface *srf = vmw_res_to_srf(res);
    634 	struct vmw_user_surface *user_srf =
    635 	    container_of(srf, struct vmw_user_surface, srf);
    636 	struct vmw_private *dev_priv = srf->res.dev_priv;
    637 	uint32_t size = user_srf->size;
    638 
    639 	if (user_srf->master)
    640 		drm_master_put(&user_srf->master);
    641 	kfree(srf->offsets);
    642 	kfree(srf->sizes);
    643 	kfree(srf->snooper.image);
    644 	ttm_prime_object_kfree(user_srf, prime);
    645 	ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
    646 }
    647 
    648 /**
    649  * vmw_user_surface_free - User visible surface TTM base object destructor
    650  *
    651  * @p_base:         Pointer to a pointer to a TTM base object
    652  *                  embedded in a struct vmw_user_surface.
    653  *
    654  * Drops the base object's reference on its resource, and the
    655  * pointer pointed to by *p_base is set to NULL.
    656  */
    657 static void vmw_user_surface_base_release(struct ttm_base_object **p_base)
    658 {
    659 	struct ttm_base_object *base = *p_base;
    660 	struct vmw_user_surface *user_srf =
    661 	    container_of(base, struct vmw_user_surface, prime.base);
    662 	struct vmw_resource *res = &user_srf->srf.res;
    663 
    664 	*p_base = NULL;
    665 	if (user_srf->backup_base)
    666 		ttm_base_object_unref(&user_srf->backup_base);
    667 	vmw_resource_unreference(&res);
    668 }
    669 
    670 /**
    671  * vmw_user_surface_destroy_ioctl - Ioctl function implementing
    672  *                                  the user surface destroy functionality.
    673  *
    674  * @dev:            Pointer to a struct drm_device.
    675  * @data:           Pointer to data copied from / to user-space.
    676  * @file_priv:      Pointer to a drm file private structure.
    677  */
    678 int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
    679 			      struct drm_file *file_priv)
    680 {
    681 	struct drm_vmw_surface_arg *arg = (struct drm_vmw_surface_arg *)data;
    682 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
    683 
    684 	return ttm_ref_object_base_unref(tfile, arg->sid, TTM_REF_USAGE);
    685 }
    686 
    687 /**
    688  * vmw_user_surface_define_ioctl - Ioctl function implementing
    689  *                                  the user surface define functionality.
    690  *
    691  * @dev:            Pointer to a struct drm_device.
    692  * @data:           Pointer to data copied from / to user-space.
    693  * @file_priv:      Pointer to a drm file private structure.
    694  */
    695 int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
    696 			     struct drm_file *file_priv)
    697 {
    698 	struct vmw_private *dev_priv = vmw_priv(dev);
    699 	struct vmw_user_surface *user_srf;
    700 	struct vmw_surface *srf;
    701 	struct vmw_resource *res;
    702 	struct vmw_resource *tmp;
    703 	union drm_vmw_surface_create_arg *arg =
    704 	    (union drm_vmw_surface_create_arg *)data;
    705 	struct drm_vmw_surface_create_req *req = &arg->req;
    706 	struct drm_vmw_surface_arg *rep = &arg->rep;
    707 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
    708 	struct drm_vmw_size __user *user_sizes;
    709 	int ret;
    710 	int i, j;
    711 	uint32_t cur_bo_offset;
    712 	struct drm_vmw_size *cur_size;
    713 	struct vmw_surface_offset *cur_offset;
    714 	uint32_t num_sizes;
    715 	uint32_t size;
    716 	const struct svga3d_surface_desc *desc;
    717 
    718 	if (unlikely(vmw_user_surface_size == 0))
    719 		vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
    720 			128;
    721 
    722 	num_sizes = 0;
    723 	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
    724 		if (req->mip_levels[i] > DRM_VMW_MAX_MIP_LEVELS)
    725 			return -EINVAL;
    726 		num_sizes += req->mip_levels[i];
    727 	}
    728 
    729 	if (num_sizes > DRM_VMW_MAX_SURFACE_FACES * DRM_VMW_MAX_MIP_LEVELS ||
    730 	    num_sizes == 0)
    731 		return -EINVAL;
    732 
    733 	size = vmw_user_surface_size + 128 +
    734 		ttm_round_pot(num_sizes * sizeof(struct drm_vmw_size)) +
    735 		ttm_round_pot(num_sizes * sizeof(struct vmw_surface_offset));
    736 
    737 
    738 	desc = svga3dsurface_get_desc(req->format);
    739 	if (unlikely(desc->block_desc == SVGA3DBLOCKDESC_NONE)) {
    740 		DRM_ERROR("Invalid surface format for surface creation.\n");
    741 		DRM_ERROR("Format requested is: %d\n", req->format);
    742 		return -EINVAL;
    743 	}
    744 
    745 	ret = ttm_read_lock(&dev_priv->reservation_sem, true);
    746 	if (unlikely(ret != 0))
    747 		return ret;
    748 
    749 	ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
    750 				   size, false, true);
    751 	if (unlikely(ret != 0)) {
    752 		if (ret != -ERESTARTSYS)
    753 			DRM_ERROR("Out of graphics memory for surface"
    754 				  " creation.\n");
    755 		goto out_unlock;
    756 	}
    757 
    758 	user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL);
    759 	if (unlikely(user_srf == NULL)) {
    760 		ret = -ENOMEM;
    761 		goto out_no_user_srf;
    762 	}
    763 
    764 	srf = &user_srf->srf;
    765 	res = &srf->res;
    766 
    767 	srf->flags = req->flags;
    768 	srf->format = req->format;
    769 	srf->scanout = req->scanout;
    770 
    771 	memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels));
    772 	srf->num_sizes = num_sizes;
    773 	user_srf->size = size;
    774 
    775 	srf->sizes = kmalloc(srf->num_sizes * sizeof(*srf->sizes), GFP_KERNEL);
    776 	if (unlikely(srf->sizes == NULL)) {
    777 		ret = -ENOMEM;
    778 		goto out_no_sizes;
    779 	}
    780 	srf->offsets = kmalloc(srf->num_sizes * sizeof(*srf->offsets),
    781 			       GFP_KERNEL);
    782 	if (unlikely(srf->sizes == NULL)) {
    783 		ret = -ENOMEM;
    784 		goto out_no_offsets;
    785 	}
    786 
    787 	user_sizes = (struct drm_vmw_size __user *)(unsigned long)
    788 	    req->size_addr;
    789 
    790 	ret = copy_from_user(srf->sizes, user_sizes,
    791 			     srf->num_sizes * sizeof(*srf->sizes));
    792 	if (unlikely(ret != 0)) {
    793 		ret = -EFAULT;
    794 		goto out_no_copy;
    795 	}
    796 
    797 	srf->base_size = *srf->sizes;
    798 	srf->autogen_filter = SVGA3D_TEX_FILTER_NONE;
    799 	srf->multisample_count = 0;
    800 
    801 	cur_bo_offset = 0;
    802 	cur_offset = srf->offsets;
    803 	cur_size = srf->sizes;
    804 
    805 	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
    806 		for (j = 0; j < srf->mip_levels[i]; ++j) {
    807 			uint32_t stride = svga3dsurface_calculate_pitch
    808 				(desc, cur_size);
    809 
    810 			cur_offset->face = i;
    811 			cur_offset->mip = j;
    812 			cur_offset->bo_offset = cur_bo_offset;
    813 			cur_bo_offset += svga3dsurface_get_image_buffer_size
    814 				(desc, cur_size, stride);
    815 			++cur_offset;
    816 			++cur_size;
    817 		}
    818 	}
    819 	res->backup_size = cur_bo_offset;
    820 	if (srf->scanout &&
    821 	    srf->num_sizes == 1 &&
    822 	    srf->sizes[0].width == 64 &&
    823 	    srf->sizes[0].height == 64 &&
    824 	    srf->format == SVGA3D_A8R8G8B8) {
    825 
    826 		srf->snooper.image = kmalloc(64 * 64 * 4, GFP_KERNEL);
    827 		/* clear the image */
    828 		if (srf->snooper.image) {
    829 			memset(srf->snooper.image, 0x00, 64 * 64 * 4);
    830 		} else {
    831 			DRM_ERROR("Failed to allocate cursor_image\n");
    832 			ret = -ENOMEM;
    833 			goto out_no_copy;
    834 		}
    835 	} else {
    836 		srf->snooper.image = NULL;
    837 	}
    838 	srf->snooper.crtc = NULL;
    839 
    840 	user_srf->prime.base.shareable = false;
    841 	user_srf->prime.base.tfile = NULL;
    842 	if (drm_is_primary_client(file_priv))
    843 		user_srf->master = drm_master_get(file_priv->master);
    844 
    845 	/**
    846 	 * From this point, the generic resource management functions
    847 	 * destroy the object on failure.
    848 	 */
    849 
    850 	ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free);
    851 	if (unlikely(ret != 0))
    852 		goto out_unlock;
    853 
    854 	/*
    855 	 * A gb-aware client referencing a shared surface will
    856 	 * expect a backup buffer to be present.
    857 	 */
    858 	if (dev_priv->has_mob && req->shareable) {
    859 		uint32_t backup_handle;
    860 
    861 		ret = vmw_user_dmabuf_alloc(dev_priv, tfile,
    862 					    res->backup_size,
    863 					    true,
    864 					    &backup_handle,
    865 					    &res->backup,
    866 					    &user_srf->backup_base);
    867 		if (unlikely(ret != 0)) {
    868 			vmw_resource_unreference(&res);
    869 			goto out_unlock;
    870 		}
    871 	}
    872 
    873 	tmp = vmw_resource_reference(&srf->res);
    874 	ret = ttm_prime_object_init(tfile, res->backup_size, &user_srf->prime,
    875 				    req->shareable, VMW_RES_SURFACE,
    876 				    &vmw_user_surface_base_release, NULL);
    877 
    878 	if (unlikely(ret != 0)) {
    879 		vmw_resource_unreference(&tmp);
    880 		vmw_resource_unreference(&res);
    881 		goto out_unlock;
    882 	}
    883 
    884 	rep->sid = user_srf->prime.base.hash.key;
    885 	vmw_resource_unreference(&res);
    886 
    887 	ttm_read_unlock(&dev_priv->reservation_sem);
    888 	return 0;
    889 out_no_copy:
    890 	kfree(srf->offsets);
    891 out_no_offsets:
    892 	kfree(srf->sizes);
    893 out_no_sizes:
    894 	ttm_prime_object_kfree(user_srf, prime);
    895 out_no_user_srf:
    896 	ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
    897 out_unlock:
    898 	ttm_read_unlock(&dev_priv->reservation_sem);
    899 	return ret;
    900 }
    901 
    902 
    903 static int
    904 vmw_surface_handle_reference(struct vmw_private *dev_priv,
    905 			     struct drm_file *file_priv,
    906 			     uint32_t u_handle,
    907 			     enum drm_vmw_handle_type handle_type,
    908 			     struct ttm_base_object **base_p)
    909 {
    910 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
    911 	struct vmw_user_surface *user_srf;
    912 	uint32_t handle;
    913 	struct ttm_base_object *base;
    914 	int ret;
    915 	bool require_exist = false;
    916 
    917 	if (handle_type == DRM_VMW_HANDLE_PRIME) {
    918 		ret = ttm_prime_fd_to_handle(tfile, u_handle, &handle);
    919 		if (unlikely(ret != 0))
    920 			return ret;
    921 	} else {
    922 		if (unlikely(drm_is_render_client(file_priv)))
    923 			require_exist = true;
    924 
    925 		if (ACCESS_ONCE(vmw_fpriv(file_priv)->locked_master)) {
    926 			DRM_ERROR("Locked master refused legacy "
    927 				  "surface reference.\n");
    928 			return -EACCES;
    929 		}
    930 
    931 		handle = u_handle;
    932 	}
    933 
    934 	ret = -EINVAL;
    935 	base = ttm_base_object_lookup_for_ref(dev_priv->tdev, handle);
    936 	if (unlikely(base == NULL)) {
    937 		DRM_ERROR("Could not find surface to reference.\n");
    938 		goto out_no_lookup;
    939 	}
    940 
    941 	if (unlikely(ttm_base_object_type(base) != VMW_RES_SURFACE)) {
    942 		DRM_ERROR("Referenced object is not a surface.\n");
    943 		goto out_bad_resource;
    944 	}
    945 
    946 	if (handle_type != DRM_VMW_HANDLE_PRIME) {
    947 		user_srf = container_of(base, struct vmw_user_surface,
    948 					prime.base);
    949 
    950 		/*
    951 		 * Make sure the surface creator has the same
    952 		 * authenticating master, or is already registered with us.
    953 		 */
    954 		if (drm_is_primary_client(file_priv) &&
    955 		    user_srf->master != file_priv->master)
    956 			require_exist = true;
    957 
    958 		ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL,
    959 					 require_exist);
    960 		if (unlikely(ret != 0)) {
    961 			DRM_ERROR("Could not add a reference to a surface.\n");
    962 			goto out_bad_resource;
    963 		}
    964 	}
    965 
    966 	*base_p = base;
    967 	return 0;
    968 
    969 out_bad_resource:
    970 	ttm_base_object_unref(&base);
    971 out_no_lookup:
    972 	if (handle_type == DRM_VMW_HANDLE_PRIME)
    973 		(void) ttm_ref_object_base_unref(tfile, handle, TTM_REF_USAGE);
    974 
    975 	return ret;
    976 }
    977 
    978 /**
    979  * vmw_user_surface_define_ioctl - Ioctl function implementing
    980  *                                  the user surface reference functionality.
    981  *
    982  * @dev:            Pointer to a struct drm_device.
    983  * @data:           Pointer to data copied from / to user-space.
    984  * @file_priv:      Pointer to a drm file private structure.
    985  */
    986 int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
    987 				struct drm_file *file_priv)
    988 {
    989 	struct vmw_private *dev_priv = vmw_priv(dev);
    990 	union drm_vmw_surface_reference_arg *arg =
    991 	    (union drm_vmw_surface_reference_arg *)data;
    992 	struct drm_vmw_surface_arg *req = &arg->req;
    993 	struct drm_vmw_surface_create_req *rep = &arg->rep;
    994 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
    995 	struct vmw_surface *srf;
    996 	struct vmw_user_surface *user_srf;
    997 	struct drm_vmw_size __user *user_sizes;
    998 	struct ttm_base_object *base;
    999 	int ret;
   1000 
   1001 	ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid,
   1002 					   req->handle_type, &base);
   1003 	if (unlikely(ret != 0))
   1004 		return ret;
   1005 
   1006 	user_srf = container_of(base, struct vmw_user_surface, prime.base);
   1007 	srf = &user_srf->srf;
   1008 
   1009 	rep->flags = srf->flags;
   1010 	rep->format = srf->format;
   1011 	memcpy(rep->mip_levels, srf->mip_levels, sizeof(srf->mip_levels));
   1012 	user_sizes = (struct drm_vmw_size __user *)(unsigned long)
   1013 	    rep->size_addr;
   1014 
   1015 	if (user_sizes)
   1016 		ret = copy_to_user(user_sizes, &srf->base_size,
   1017 				   sizeof(srf->base_size));
   1018 	if (unlikely(ret != 0)) {
   1019 		DRM_ERROR("copy_to_user failed %p %u\n",
   1020 			  user_sizes, srf->num_sizes);
   1021 		ttm_ref_object_base_unref(tfile, base->hash.key, TTM_REF_USAGE);
   1022 		ret = -EFAULT;
   1023 	}
   1024 
   1025 	ttm_base_object_unref(&base);
   1026 
   1027 	return ret;
   1028 }
   1029 
   1030 /**
   1031  * vmw_surface_define_encode - Encode a surface_define command.
   1032  *
   1033  * @srf: Pointer to a struct vmw_surface object.
   1034  * @cmd_space: Pointer to memory area in which the commands should be encoded.
   1035  */
   1036 static int vmw_gb_surface_create(struct vmw_resource *res)
   1037 {
   1038 	struct vmw_private *dev_priv = res->dev_priv;
   1039 	struct vmw_surface *srf = vmw_res_to_srf(res);
   1040 	uint32_t cmd_len, cmd_id, submit_len;
   1041 	int ret;
   1042 	struct {
   1043 		SVGA3dCmdHeader header;
   1044 		SVGA3dCmdDefineGBSurface body;
   1045 	} *cmd;
   1046 	struct {
   1047 		SVGA3dCmdHeader header;
   1048 		SVGA3dCmdDefineGBSurface_v2 body;
   1049 	} *cmd2;
   1050 
   1051 	if (likely(res->id != -1))
   1052 		return 0;
   1053 
   1054 	vmw_fifo_resource_inc(dev_priv);
   1055 	ret = vmw_resource_alloc_id(res);
   1056 	if (unlikely(ret != 0)) {
   1057 		DRM_ERROR("Failed to allocate a surface id.\n");
   1058 		goto out_no_id;
   1059 	}
   1060 
   1061 	if (unlikely(res->id >= VMWGFX_NUM_GB_SURFACE)) {
   1062 		ret = -EBUSY;
   1063 		goto out_no_fifo;
   1064 	}
   1065 
   1066 	if (srf->array_size > 0) {
   1067 		/* has_dx checked on creation time. */
   1068 		cmd_id = SVGA_3D_CMD_DEFINE_GB_SURFACE_V2;
   1069 		cmd_len = sizeof(cmd2->body);
   1070 		submit_len = sizeof(*cmd2);
   1071 	} else {
   1072 		cmd_id = SVGA_3D_CMD_DEFINE_GB_SURFACE;
   1073 		cmd_len = sizeof(cmd->body);
   1074 		submit_len = sizeof(*cmd);
   1075 	}
   1076 
   1077 	cmd = vmw_fifo_reserve(dev_priv, submit_len);
   1078 	cmd2 = (typeof(cmd2))cmd;
   1079 	if (unlikely(cmd == NULL)) {
   1080 		DRM_ERROR("Failed reserving FIFO space for surface "
   1081 			  "creation.\n");
   1082 		ret = -ENOMEM;
   1083 		goto out_no_fifo;
   1084 	}
   1085 
   1086 	if (srf->array_size > 0) {
   1087 		cmd2->header.id = cmd_id;
   1088 		cmd2->header.size = cmd_len;
   1089 		cmd2->body.sid = srf->res.id;
   1090 		cmd2->body.surfaceFlags = srf->flags;
   1091 		cmd2->body.format = cpu_to_le32(srf->format);
   1092 		cmd2->body.numMipLevels = srf->mip_levels[0];
   1093 		cmd2->body.multisampleCount = srf->multisample_count;
   1094 		cmd2->body.autogenFilter = srf->autogen_filter;
   1095 		cmd2->body.size.width = srf->base_size.width;
   1096 		cmd2->body.size.height = srf->base_size.height;
   1097 		cmd2->body.size.depth = srf->base_size.depth;
   1098 		cmd2->body.arraySize = srf->array_size;
   1099 	} else {
   1100 		cmd->header.id = cmd_id;
   1101 		cmd->header.size = cmd_len;
   1102 		cmd->body.sid = srf->res.id;
   1103 		cmd->body.surfaceFlags = srf->flags;
   1104 		cmd->body.format = cpu_to_le32(srf->format);
   1105 		cmd->body.numMipLevels = srf->mip_levels[0];
   1106 		cmd->body.multisampleCount = srf->multisample_count;
   1107 		cmd->body.autogenFilter = srf->autogen_filter;
   1108 		cmd->body.size.width = srf->base_size.width;
   1109 		cmd->body.size.height = srf->base_size.height;
   1110 		cmd->body.size.depth = srf->base_size.depth;
   1111 	}
   1112 
   1113 	vmw_fifo_commit(dev_priv, submit_len);
   1114 
   1115 	return 0;
   1116 
   1117 out_no_fifo:
   1118 	vmw_resource_release_id(res);
   1119 out_no_id:
   1120 	vmw_fifo_resource_dec(dev_priv);
   1121 	return ret;
   1122 }
   1123 
   1124 
   1125 static int vmw_gb_surface_bind(struct vmw_resource *res,
   1126 			       struct ttm_validate_buffer *val_buf)
   1127 {
   1128 	struct vmw_private *dev_priv = res->dev_priv;
   1129 	struct {
   1130 		SVGA3dCmdHeader header;
   1131 		SVGA3dCmdBindGBSurface body;
   1132 	} *cmd1;
   1133 	struct {
   1134 		SVGA3dCmdHeader header;
   1135 		SVGA3dCmdUpdateGBSurface body;
   1136 	} *cmd2;
   1137 	uint32_t submit_size;
   1138 	struct ttm_buffer_object *bo = val_buf->bo;
   1139 
   1140 	BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
   1141 
   1142 	submit_size = sizeof(*cmd1) + (res->backup_dirty ? sizeof(*cmd2) : 0);
   1143 
   1144 	cmd1 = vmw_fifo_reserve(dev_priv, submit_size);
   1145 	if (unlikely(cmd1 == NULL)) {
   1146 		DRM_ERROR("Failed reserving FIFO space for surface "
   1147 			  "binding.\n");
   1148 		return -ENOMEM;
   1149 	}
   1150 
   1151 	cmd1->header.id = SVGA_3D_CMD_BIND_GB_SURFACE;
   1152 	cmd1->header.size = sizeof(cmd1->body);
   1153 	cmd1->body.sid = res->id;
   1154 	cmd1->body.mobid = bo->mem.start;
   1155 	if (res->backup_dirty) {
   1156 		cmd2 = (void *) &cmd1[1];
   1157 		cmd2->header.id = SVGA_3D_CMD_UPDATE_GB_SURFACE;
   1158 		cmd2->header.size = sizeof(cmd2->body);
   1159 		cmd2->body.sid = res->id;
   1160 		res->backup_dirty = false;
   1161 	}
   1162 	vmw_fifo_commit(dev_priv, submit_size);
   1163 
   1164 	return 0;
   1165 }
   1166 
   1167 static int vmw_gb_surface_unbind(struct vmw_resource *res,
   1168 				 bool readback,
   1169 				 struct ttm_validate_buffer *val_buf)
   1170 {
   1171 	struct vmw_private *dev_priv = res->dev_priv;
   1172 	struct ttm_buffer_object *bo = val_buf->bo;
   1173 	struct vmw_fence_obj *fence;
   1174 
   1175 	struct {
   1176 		SVGA3dCmdHeader header;
   1177 		SVGA3dCmdReadbackGBSurface body;
   1178 	} *cmd1;
   1179 	struct {
   1180 		SVGA3dCmdHeader header;
   1181 		SVGA3dCmdInvalidateGBSurface body;
   1182 	} *cmd2;
   1183 	struct {
   1184 		SVGA3dCmdHeader header;
   1185 		SVGA3dCmdBindGBSurface body;
   1186 	} *cmd3;
   1187 	uint32_t submit_size;
   1188 	uint8_t *cmd;
   1189 
   1190 
   1191 	BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
   1192 
   1193 	submit_size = sizeof(*cmd3) + (readback ? sizeof(*cmd1) : sizeof(*cmd2));
   1194 	cmd = vmw_fifo_reserve(dev_priv, submit_size);
   1195 	if (unlikely(cmd == NULL)) {
   1196 		DRM_ERROR("Failed reserving FIFO space for surface "
   1197 			  "unbinding.\n");
   1198 		return -ENOMEM;
   1199 	}
   1200 
   1201 	if (readback) {
   1202 		cmd1 = (void *) cmd;
   1203 		cmd1->header.id = SVGA_3D_CMD_READBACK_GB_SURFACE;
   1204 		cmd1->header.size = sizeof(cmd1->body);
   1205 		cmd1->body.sid = res->id;
   1206 		cmd3 = (void *) &cmd1[1];
   1207 	} else {
   1208 		cmd2 = (void *) cmd;
   1209 		cmd2->header.id = SVGA_3D_CMD_INVALIDATE_GB_SURFACE;
   1210 		cmd2->header.size = sizeof(cmd2->body);
   1211 		cmd2->body.sid = res->id;
   1212 		cmd3 = (void *) &cmd2[1];
   1213 	}
   1214 
   1215 	cmd3->header.id = SVGA_3D_CMD_BIND_GB_SURFACE;
   1216 	cmd3->header.size = sizeof(cmd3->body);
   1217 	cmd3->body.sid = res->id;
   1218 	cmd3->body.mobid = SVGA3D_INVALID_ID;
   1219 
   1220 	vmw_fifo_commit(dev_priv, submit_size);
   1221 
   1222 	/*
   1223 	 * Create a fence object and fence the backup buffer.
   1224 	 */
   1225 
   1226 	(void) vmw_execbuf_fence_commands(NULL, dev_priv,
   1227 					  &fence, NULL);
   1228 
   1229 	vmw_fence_single_bo(val_buf->bo, fence);
   1230 
   1231 	if (likely(fence != NULL))
   1232 		vmw_fence_obj_unreference(&fence);
   1233 
   1234 	return 0;
   1235 }
   1236 
   1237 static int vmw_gb_surface_destroy(struct vmw_resource *res)
   1238 {
   1239 	struct vmw_private *dev_priv = res->dev_priv;
   1240 	struct vmw_surface *srf = vmw_res_to_srf(res);
   1241 	struct {
   1242 		SVGA3dCmdHeader header;
   1243 		SVGA3dCmdDestroyGBSurface body;
   1244 	} *cmd;
   1245 
   1246 	if (likely(res->id == -1))
   1247 		return 0;
   1248 
   1249 	mutex_lock(&dev_priv->binding_mutex);
   1250 	vmw_view_surface_list_destroy(dev_priv, &srf->view_list);
   1251 	vmw_binding_res_list_scrub(&res->binding_head);
   1252 
   1253 	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
   1254 	if (unlikely(cmd == NULL)) {
   1255 		DRM_ERROR("Failed reserving FIFO space for surface "
   1256 			  "destruction.\n");
   1257 		mutex_unlock(&dev_priv->binding_mutex);
   1258 		return -ENOMEM;
   1259 	}
   1260 
   1261 	cmd->header.id = SVGA_3D_CMD_DESTROY_GB_SURFACE;
   1262 	cmd->header.size = sizeof(cmd->body);
   1263 	cmd->body.sid = res->id;
   1264 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
   1265 	mutex_unlock(&dev_priv->binding_mutex);
   1266 	vmw_resource_release_id(res);
   1267 	vmw_fifo_resource_dec(dev_priv);
   1268 
   1269 	return 0;
   1270 }
   1271 
   1272 
   1273 /**
   1274  * vmw_gb_surface_define_ioctl - Ioctl function implementing
   1275  *                               the user surface define functionality.
   1276  *
   1277  * @dev:            Pointer to a struct drm_device.
   1278  * @data:           Pointer to data copied from / to user-space.
   1279  * @file_priv:      Pointer to a drm file private structure.
   1280  */
   1281 int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
   1282 				struct drm_file *file_priv)
   1283 {
   1284 	struct vmw_private *dev_priv = vmw_priv(dev);
   1285 	struct vmw_user_surface *user_srf;
   1286 	struct vmw_surface *srf;
   1287 	struct vmw_resource *res;
   1288 	struct vmw_resource *tmp;
   1289 	union drm_vmw_gb_surface_create_arg *arg =
   1290 	    (union drm_vmw_gb_surface_create_arg *)data;
   1291 	struct drm_vmw_gb_surface_create_req *req = &arg->req;
   1292 	struct drm_vmw_gb_surface_create_rep *rep = &arg->rep;
   1293 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
   1294 	int ret;
   1295 	uint32_t size;
   1296 	uint32_t backup_handle = 0;
   1297 
   1298 	if (req->multisample_count != 0)
   1299 		return -EINVAL;
   1300 
   1301 	if (req->mip_levels > DRM_VMW_MAX_MIP_LEVELS)
   1302 		return -EINVAL;
   1303 
   1304 	if (unlikely(vmw_user_surface_size == 0))
   1305 		vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
   1306 			128;
   1307 
   1308 	size = vmw_user_surface_size + 128;
   1309 
   1310 	/* Define a surface based on the parameters. */
   1311 	ret = vmw_surface_gb_priv_define(dev,
   1312 			size,
   1313 			req->svga3d_flags,
   1314 			req->format,
   1315 			req->drm_surface_flags & drm_vmw_surface_flag_scanout,
   1316 			req->mip_levels,
   1317 			req->multisample_count,
   1318 			req->array_size,
   1319 			req->base_size,
   1320 			&srf);
   1321 	if (unlikely(ret != 0))
   1322 		return ret;
   1323 
   1324 	user_srf = container_of(srf, struct vmw_user_surface, srf);
   1325 	if (drm_is_primary_client(file_priv))
   1326 		user_srf->master = drm_master_get(file_priv->master);
   1327 
   1328 	ret = ttm_read_lock(&dev_priv->reservation_sem, true);
   1329 	if (unlikely(ret != 0))
   1330 		return ret;
   1331 
   1332 	res = &user_srf->srf.res;
   1333 
   1334 
   1335 	if (req->buffer_handle != SVGA3D_INVALID_ID) {
   1336 		ret = vmw_user_dmabuf_lookup(tfile, req->buffer_handle,
   1337 					     &res->backup,
   1338 					     &user_srf->backup_base);
   1339 		if (ret == 0) {
   1340 			if (res->backup->base.num_pages * PAGE_SIZE <
   1341 			    res->backup_size) {
   1342 				DRM_ERROR("Surface backup buffer is too small.\n");
   1343 				vmw_dmabuf_unreference(&res->backup);
   1344 				ret = -EINVAL;
   1345 				goto out_unlock;
   1346 			} else {
   1347 				backup_handle = req->buffer_handle;
   1348 			}
   1349 		}
   1350 	} else if (req->drm_surface_flags & drm_vmw_surface_flag_create_buffer)
   1351 		ret = vmw_user_dmabuf_alloc(dev_priv, tfile,
   1352 					    res->backup_size,
   1353 					    req->drm_surface_flags &
   1354 					    drm_vmw_surface_flag_shareable,
   1355 					    &backup_handle,
   1356 					    &res->backup,
   1357 					    &user_srf->backup_base);
   1358 
   1359 	if (unlikely(ret != 0)) {
   1360 		vmw_resource_unreference(&res);
   1361 		goto out_unlock;
   1362 	}
   1363 
   1364 	tmp = vmw_resource_reference(res);
   1365 	ret = ttm_prime_object_init(tfile, res->backup_size, &user_srf->prime,
   1366 				    req->drm_surface_flags &
   1367 				    drm_vmw_surface_flag_shareable,
   1368 				    VMW_RES_SURFACE,
   1369 				    &vmw_user_surface_base_release, NULL);
   1370 
   1371 	if (unlikely(ret != 0)) {
   1372 		vmw_resource_unreference(&tmp);
   1373 		vmw_resource_unreference(&res);
   1374 		goto out_unlock;
   1375 	}
   1376 
   1377 	rep->handle      = user_srf->prime.base.hash.key;
   1378 	rep->backup_size = res->backup_size;
   1379 	if (res->backup) {
   1380 		rep->buffer_map_handle =
   1381 			drm_vma_node_offset_addr(&res->backup->base.vma_node);
   1382 		rep->buffer_size = res->backup->base.num_pages * PAGE_SIZE;
   1383 		rep->buffer_handle = backup_handle;
   1384 	} else {
   1385 		rep->buffer_map_handle = 0;
   1386 		rep->buffer_size = 0;
   1387 		rep->buffer_handle = SVGA3D_INVALID_ID;
   1388 	}
   1389 
   1390 	vmw_resource_unreference(&res);
   1391 
   1392 out_unlock:
   1393 	ttm_read_unlock(&dev_priv->reservation_sem);
   1394 	return ret;
   1395 }
   1396 
   1397 /**
   1398  * vmw_gb_surface_reference_ioctl - Ioctl function implementing
   1399  *                                  the user surface reference functionality.
   1400  *
   1401  * @dev:            Pointer to a struct drm_device.
   1402  * @data:           Pointer to data copied from / to user-space.
   1403  * @file_priv:      Pointer to a drm file private structure.
   1404  */
   1405 int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data,
   1406 				   struct drm_file *file_priv)
   1407 {
   1408 	struct vmw_private *dev_priv = vmw_priv(dev);
   1409 	union drm_vmw_gb_surface_reference_arg *arg =
   1410 	    (union drm_vmw_gb_surface_reference_arg *)data;
   1411 	struct drm_vmw_surface_arg *req = &arg->req;
   1412 	struct drm_vmw_gb_surface_ref_rep *rep = &arg->rep;
   1413 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
   1414 	struct vmw_surface *srf;
   1415 	struct vmw_user_surface *user_srf;
   1416 	struct ttm_base_object *base;
   1417 	uint32_t backup_handle;
   1418 	int ret = -EINVAL;
   1419 
   1420 	ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid,
   1421 					   req->handle_type, &base);
   1422 	if (unlikely(ret != 0))
   1423 		return ret;
   1424 
   1425 	user_srf = container_of(base, struct vmw_user_surface, prime.base);
   1426 	srf = &user_srf->srf;
   1427 	if (srf->res.backup == NULL) {
   1428 		DRM_ERROR("Shared GB surface is missing a backup buffer.\n");
   1429 		goto out_bad_resource;
   1430 	}
   1431 
   1432 	mutex_lock(&dev_priv->cmdbuf_mutex); /* Protect res->backup */
   1433 	ret = vmw_user_dmabuf_reference(tfile, srf->res.backup,
   1434 					&backup_handle);
   1435 	mutex_unlock(&dev_priv->cmdbuf_mutex);
   1436 
   1437 	if (unlikely(ret != 0)) {
   1438 		DRM_ERROR("Could not add a reference to a GB surface "
   1439 			  "backup buffer.\n");
   1440 		(void) ttm_ref_object_base_unref(tfile, base->hash.key,
   1441 						 TTM_REF_USAGE);
   1442 		goto out_bad_resource;
   1443 	}
   1444 
   1445 	rep->creq.svga3d_flags = srf->flags;
   1446 	rep->creq.format = srf->format;
   1447 	rep->creq.mip_levels = srf->mip_levels[0];
   1448 	rep->creq.drm_surface_flags = 0;
   1449 	rep->creq.multisample_count = srf->multisample_count;
   1450 	rep->creq.autogen_filter = srf->autogen_filter;
   1451 	rep->creq.array_size = srf->array_size;
   1452 	rep->creq.buffer_handle = backup_handle;
   1453 	rep->creq.base_size = srf->base_size;
   1454 	rep->crep.handle = user_srf->prime.base.hash.key;
   1455 	rep->crep.backup_size = srf->res.backup_size;
   1456 	rep->crep.buffer_handle = backup_handle;
   1457 	rep->crep.buffer_map_handle =
   1458 		drm_vma_node_offset_addr(&srf->res.backup->base.vma_node);
   1459 	rep->crep.buffer_size = srf->res.backup->base.num_pages * PAGE_SIZE;
   1460 
   1461 out_bad_resource:
   1462 	ttm_base_object_unref(&base);
   1463 
   1464 	return ret;
   1465 }
   1466 
   1467 /**
   1468  * vmw_surface_gb_priv_define - Define a private GB surface
   1469  *
   1470  * @dev:  Pointer to a struct drm_device
   1471  * @user_accounting_size:  Used to track user-space memory usage, set
   1472  *                         to 0 for kernel mode only memory
   1473  * @svga3d_flags: SVGA3d surface flags for the device
   1474  * @format: requested surface format
   1475  * @for_scanout: true if inteded to be used for scanout buffer
   1476  * @num_mip_levels:  number of MIP levels
   1477  * @multisample_count:
   1478  * @array_size: Surface array size.
   1479  * @size: width, heigh, depth of the surface requested
   1480  * @user_srf_out: allocated user_srf.  Set to NULL on failure.
   1481  *
   1482  * GB surfaces allocated by this function will not have a user mode handle, and
   1483  * thus will only be visible to vmwgfx.  For optimization reasons the
   1484  * surface may later be given a user mode handle by another function to make
   1485  * it available to user mode drivers.
   1486  */
   1487 int vmw_surface_gb_priv_define(struct drm_device *dev,
   1488 			       uint32_t user_accounting_size,
   1489 			       uint32_t svga3d_flags,
   1490 			       SVGA3dSurfaceFormat format,
   1491 			       bool for_scanout,
   1492 			       uint32_t num_mip_levels,
   1493 			       uint32_t multisample_count,
   1494 			       uint32_t array_size,
   1495 			       struct drm_vmw_size size,
   1496 			       struct vmw_surface **srf_out)
   1497 {
   1498 	struct vmw_private *dev_priv = vmw_priv(dev);
   1499 	struct vmw_user_surface *user_srf;
   1500 	struct vmw_surface *srf;
   1501 	int ret;
   1502 	u32 num_layers;
   1503 
   1504 	*srf_out = NULL;
   1505 
   1506 	if (for_scanout) {
   1507 		if (!svga3dsurface_is_screen_target_format(format)) {
   1508 			DRM_ERROR("Invalid Screen Target surface format.");
   1509 			return -EINVAL;
   1510 		}
   1511 	} else {
   1512 		const struct svga3d_surface_desc *desc;
   1513 
   1514 		desc = svga3dsurface_get_desc(format);
   1515 		if (unlikely(desc->block_desc == SVGA3DBLOCKDESC_NONE)) {
   1516 			DRM_ERROR("Invalid surface format.\n");
   1517 			return -EINVAL;
   1518 		}
   1519 	}
   1520 
   1521 	/* array_size must be null for non-GL3 host. */
   1522 	if (array_size > 0 && !dev_priv->has_dx) {
   1523 		DRM_ERROR("Tried to create DX surface on non-DX host.\n");
   1524 		return -EINVAL;
   1525 	}
   1526 
   1527 	ret = ttm_read_lock(&dev_priv->reservation_sem, true);
   1528 	if (unlikely(ret != 0))
   1529 		return ret;
   1530 
   1531 	ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
   1532 				   user_accounting_size, false, true);
   1533 	if (unlikely(ret != 0)) {
   1534 		if (ret != -ERESTARTSYS)
   1535 			DRM_ERROR("Out of graphics memory for surface"
   1536 				  " creation.\n");
   1537 		goto out_unlock;
   1538 	}
   1539 
   1540 	user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL);
   1541 	if (unlikely(user_srf == NULL)) {
   1542 		ret = -ENOMEM;
   1543 		goto out_no_user_srf;
   1544 	}
   1545 
   1546 	*srf_out  = &user_srf->srf;
   1547 	user_srf->size = user_accounting_size;
   1548 	user_srf->prime.base.shareable = false;
   1549 	user_srf->prime.base.tfile     = NULL;
   1550 
   1551 	srf = &user_srf->srf;
   1552 	srf->flags             = svga3d_flags;
   1553 	srf->format            = format;
   1554 	srf->scanout           = for_scanout;
   1555 	srf->mip_levels[0]     = num_mip_levels;
   1556 	srf->num_sizes         = 1;
   1557 	srf->sizes             = NULL;
   1558 	srf->offsets           = NULL;
   1559 	srf->base_size         = size;
   1560 	srf->autogen_filter    = SVGA3D_TEX_FILTER_NONE;
   1561 	srf->array_size        = array_size;
   1562 	srf->multisample_count = multisample_count;
   1563 
   1564 	if (array_size)
   1565 		num_layers = array_size;
   1566 	else if (svga3d_flags & SVGA3D_SURFACE_CUBEMAP)
   1567 		num_layers = SVGA3D_MAX_SURFACE_FACES;
   1568 	else
   1569 		num_layers = 1;
   1570 
   1571 	srf->res.backup_size   =
   1572 		svga3dsurface_get_serialized_size(srf->format,
   1573 						  srf->base_size,
   1574 						  srf->mip_levels[0],
   1575 						  num_layers);
   1576 
   1577 	if (srf->flags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT)
   1578 		srf->res.backup_size += sizeof(SVGA3dDXSOState);
   1579 
   1580 	if (dev_priv->active_display_unit == vmw_du_screen_target &&
   1581 	    for_scanout)
   1582 		srf->flags |= SVGA3D_SURFACE_SCREENTARGET;
   1583 
   1584 	/*
   1585 	 * From this point, the generic resource management functions
   1586 	 * destroy the object on failure.
   1587 	 */
   1588 	ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free);
   1589 
   1590 	ttm_read_unlock(&dev_priv->reservation_sem);
   1591 	return ret;
   1592 
   1593 out_no_user_srf:
   1594 	ttm_mem_global_free(vmw_mem_glob(dev_priv), user_accounting_size);
   1595 
   1596 out_unlock:
   1597 	ttm_read_unlock(&dev_priv->reservation_sem);
   1598 	return ret;
   1599 }
   1600