Home | History | Annotate | Line # | Download | only in vmwgfx
      1  1.2  riastrad /*	$NetBSD: vmwgfx_surface.c,v 1.3 2021/12/18 23:45:45 riastradh Exp $	*/
      2  1.2  riastrad 
      3  1.3  riastrad // SPDX-License-Identifier: GPL-2.0 OR MIT
      4  1.1  riastrad /**************************************************************************
      5  1.1  riastrad  *
      6  1.3  riastrad  * Copyright 2009-2015 VMware, Inc., Palo Alto, CA., USA
      7  1.1  riastrad  *
      8  1.1  riastrad  * Permission is hereby granted, free of charge, to any person obtaining a
      9  1.1  riastrad  * copy of this software and associated documentation files (the
     10  1.1  riastrad  * "Software"), to deal in the Software without restriction, including
     11  1.1  riastrad  * without limitation the rights to use, copy, modify, merge, publish,
     12  1.1  riastrad  * distribute, sub license, and/or sell copies of the Software, and to
     13  1.1  riastrad  * permit persons to whom the Software is furnished to do so, subject to
     14  1.1  riastrad  * the following conditions:
     15  1.1  riastrad  *
     16  1.1  riastrad  * The above copyright notice and this permission notice (including the
     17  1.1  riastrad  * next paragraph) shall be included in all copies or substantial portions
     18  1.1  riastrad  * of the Software.
     19  1.1  riastrad  *
     20  1.1  riastrad  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     21  1.1  riastrad  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     22  1.1  riastrad  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
     23  1.1  riastrad  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
     24  1.1  riastrad  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     25  1.1  riastrad  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     26  1.1  riastrad  * USE OR OTHER DEALINGS IN THE SOFTWARE.
     27  1.1  riastrad  *
     28  1.1  riastrad  **************************************************************************/
     29  1.1  riastrad 
     30  1.2  riastrad #include <sys/cdefs.h>
     31  1.2  riastrad __KERNEL_RCSID(0, "$NetBSD: vmwgfx_surface.c,v 1.3 2021/12/18 23:45:45 riastradh Exp $");
     32  1.2  riastrad 
     33  1.3  riastrad #include <drm/ttm/ttm_placement.h>
     34  1.3  riastrad 
     35  1.1  riastrad #include "vmwgfx_drv.h"
     36  1.1  riastrad #include "vmwgfx_resource_priv.h"
     37  1.2  riastrad #include "vmwgfx_so.h"
     38  1.2  riastrad #include "vmwgfx_binding.h"
     39  1.2  riastrad #include "device_include/svga3d_surfacedefs.h"
     40  1.2  riastrad 
     41  1.3  riastrad #define SVGA3D_FLAGS_64(upper32, lower32) (((uint64_t)upper32 << 32) | lower32)
     42  1.3  riastrad #define SVGA3D_FLAGS_UPPER_32(svga3d_flags) (svga3d_flags >> 32)
     43  1.3  riastrad #define SVGA3D_FLAGS_LOWER_32(svga3d_flags) \
     44  1.3  riastrad 	(svga3d_flags & ((uint64_t)U32_MAX))
     45  1.1  riastrad 
     46  1.1  riastrad /**
     47  1.1  riastrad  * struct vmw_user_surface - User-space visible surface resource
     48  1.1  riastrad  *
     49  1.1  riastrad  * @base:           The TTM base object handling user-space visibility.
     50  1.1  riastrad  * @srf:            The surface metadata.
     51  1.1  riastrad  * @size:           TTM accounting size for the surface.
     52  1.2  riastrad  * @master: master of the creating client. Used for security check.
     53  1.1  riastrad  */
     54  1.1  riastrad struct vmw_user_surface {
     55  1.2  riastrad 	struct ttm_prime_object prime;
     56  1.1  riastrad 	struct vmw_surface srf;
     57  1.1  riastrad 	uint32_t size;
     58  1.2  riastrad 	struct drm_master *master;
     59  1.2  riastrad 	struct ttm_base_object *backup_base;
     60  1.1  riastrad };
     61  1.1  riastrad 
     62  1.1  riastrad /**
     63  1.1  riastrad  * struct vmw_surface_offset - Backing store mip level offset info
     64  1.1  riastrad  *
     65  1.1  riastrad  * @face:           Surface face.
     66  1.1  riastrad  * @mip:            Mip level.
     67  1.1  riastrad  * @bo_offset:      Offset into backing store of this mip level.
     68  1.1  riastrad  *
     69  1.1  riastrad  */
     70  1.1  riastrad struct vmw_surface_offset {
     71  1.1  riastrad 	uint32_t face;
     72  1.1  riastrad 	uint32_t mip;
     73  1.1  riastrad 	uint32_t bo_offset;
     74  1.1  riastrad };
     75  1.1  riastrad 
     76  1.3  riastrad /**
     77  1.3  riastrad  * vmw_surface_dirty - Surface dirty-tracker
     78  1.3  riastrad  * @cache: Cached layout information of the surface.
     79  1.3  riastrad  * @size: Accounting size for the struct vmw_surface_dirty.
     80  1.3  riastrad  * @num_subres: Number of subresources.
     81  1.3  riastrad  * @boxes: Array of SVGA3dBoxes indicating dirty regions. One per subresource.
     82  1.3  riastrad  */
     83  1.3  riastrad struct vmw_surface_dirty {
     84  1.3  riastrad 	struct svga3dsurface_cache cache;
     85  1.3  riastrad 	size_t size;
     86  1.3  riastrad 	u32 num_subres;
     87  1.3  riastrad 	SVGA3dBox boxes[0];
     88  1.3  riastrad };
     89  1.3  riastrad 
     90  1.1  riastrad static void vmw_user_surface_free(struct vmw_resource *res);
     91  1.1  riastrad static struct vmw_resource *
     92  1.1  riastrad vmw_user_surface_base_to_res(struct ttm_base_object *base);
     93  1.1  riastrad static int vmw_legacy_srf_bind(struct vmw_resource *res,
     94  1.1  riastrad 			       struct ttm_validate_buffer *val_buf);
     95  1.1  riastrad static int vmw_legacy_srf_unbind(struct vmw_resource *res,
     96  1.1  riastrad 				 bool readback,
     97  1.1  riastrad 				 struct ttm_validate_buffer *val_buf);
     98  1.1  riastrad static int vmw_legacy_srf_create(struct vmw_resource *res);
     99  1.1  riastrad static int vmw_legacy_srf_destroy(struct vmw_resource *res);
    100  1.2  riastrad static int vmw_gb_surface_create(struct vmw_resource *res);
    101  1.2  riastrad static int vmw_gb_surface_bind(struct vmw_resource *res,
    102  1.2  riastrad 			       struct ttm_validate_buffer *val_buf);
    103  1.2  riastrad static int vmw_gb_surface_unbind(struct vmw_resource *res,
    104  1.2  riastrad 				 bool readback,
    105  1.2  riastrad 				 struct ttm_validate_buffer *val_buf);
    106  1.2  riastrad static int vmw_gb_surface_destroy(struct vmw_resource *res);
    107  1.3  riastrad static int
    108  1.3  riastrad vmw_gb_surface_define_internal(struct drm_device *dev,
    109  1.3  riastrad 			       struct drm_vmw_gb_surface_create_ext_req *req,
    110  1.3  riastrad 			       struct drm_vmw_gb_surface_create_rep *rep,
    111  1.3  riastrad 			       struct drm_file *file_priv);
    112  1.3  riastrad static int
    113  1.3  riastrad vmw_gb_surface_reference_internal(struct drm_device *dev,
    114  1.3  riastrad 				  struct drm_vmw_surface_arg *req,
    115  1.3  riastrad 				  struct drm_vmw_gb_surface_ref_ext_rep *rep,
    116  1.3  riastrad 				  struct drm_file *file_priv);
    117  1.3  riastrad 
    118  1.3  riastrad static void vmw_surface_dirty_free(struct vmw_resource *res);
    119  1.3  riastrad static int vmw_surface_dirty_alloc(struct vmw_resource *res);
    120  1.3  riastrad static int vmw_surface_dirty_sync(struct vmw_resource *res);
    121  1.3  riastrad static void vmw_surface_dirty_range_add(struct vmw_resource *res, size_t start,
    122  1.3  riastrad 					size_t end);
    123  1.3  riastrad static int vmw_surface_clean(struct vmw_resource *res);
    124  1.1  riastrad 
    125  1.1  riastrad static const struct vmw_user_resource_conv user_surface_conv = {
    126  1.1  riastrad 	.object_type = VMW_RES_SURFACE,
    127  1.1  riastrad 	.base_obj_to_res = vmw_user_surface_base_to_res,
    128  1.1  riastrad 	.res_free = vmw_user_surface_free
    129  1.1  riastrad };
    130  1.1  riastrad 
    131  1.1  riastrad const struct vmw_user_resource_conv *user_surface_converter =
    132  1.1  riastrad 	&user_surface_conv;
    133  1.1  riastrad 
    134  1.1  riastrad 
    135  1.1  riastrad static uint64_t vmw_user_surface_size;
    136  1.1  riastrad 
    137  1.1  riastrad static const struct vmw_res_func vmw_legacy_surface_func = {
    138  1.1  riastrad 	.res_type = vmw_res_surface,
    139  1.1  riastrad 	.needs_backup = false,
    140  1.1  riastrad 	.may_evict = true,
    141  1.3  riastrad 	.prio = 1,
    142  1.3  riastrad 	.dirty_prio = 1,
    143  1.1  riastrad 	.type_name = "legacy surfaces",
    144  1.1  riastrad 	.backup_placement = &vmw_srf_placement,
    145  1.1  riastrad 	.create = &vmw_legacy_srf_create,
    146  1.1  riastrad 	.destroy = &vmw_legacy_srf_destroy,
    147  1.1  riastrad 	.bind = &vmw_legacy_srf_bind,
    148  1.1  riastrad 	.unbind = &vmw_legacy_srf_unbind
    149  1.1  riastrad };
    150  1.1  riastrad 
    151  1.2  riastrad static const struct vmw_res_func vmw_gb_surface_func = {
    152  1.2  riastrad 	.res_type = vmw_res_surface,
    153  1.2  riastrad 	.needs_backup = true,
    154  1.2  riastrad 	.may_evict = true,
    155  1.3  riastrad 	.prio = 1,
    156  1.3  riastrad 	.dirty_prio = 2,
    157  1.2  riastrad 	.type_name = "guest backed surfaces",
    158  1.2  riastrad 	.backup_placement = &vmw_mob_placement,
    159  1.2  riastrad 	.create = vmw_gb_surface_create,
    160  1.2  riastrad 	.destroy = vmw_gb_surface_destroy,
    161  1.2  riastrad 	.bind = vmw_gb_surface_bind,
    162  1.3  riastrad 	.unbind = vmw_gb_surface_unbind,
    163  1.3  riastrad 	.dirty_alloc = vmw_surface_dirty_alloc,
    164  1.3  riastrad 	.dirty_free = vmw_surface_dirty_free,
    165  1.3  riastrad 	.dirty_sync = vmw_surface_dirty_sync,
    166  1.3  riastrad 	.dirty_range_add = vmw_surface_dirty_range_add,
    167  1.3  riastrad 	.clean = vmw_surface_clean,
    168  1.2  riastrad };
    169  1.2  riastrad 
    170  1.1  riastrad /**
    171  1.1  riastrad  * struct vmw_surface_dma - SVGA3D DMA command
    172  1.1  riastrad  */
    173  1.1  riastrad struct vmw_surface_dma {
    174  1.1  riastrad 	SVGA3dCmdHeader header;
    175  1.1  riastrad 	SVGA3dCmdSurfaceDMA body;
    176  1.1  riastrad 	SVGA3dCopyBox cb;
    177  1.1  riastrad 	SVGA3dCmdSurfaceDMASuffix suffix;
    178  1.1  riastrad };
    179  1.1  riastrad 
    180  1.1  riastrad /**
    181  1.1  riastrad  * struct vmw_surface_define - SVGA3D Surface Define command
    182  1.1  riastrad  */
    183  1.1  riastrad struct vmw_surface_define {
    184  1.1  riastrad 	SVGA3dCmdHeader header;
    185  1.1  riastrad 	SVGA3dCmdDefineSurface body;
    186  1.1  riastrad };
    187  1.1  riastrad 
    188  1.1  riastrad /**
    189  1.1  riastrad  * struct vmw_surface_destroy - SVGA3D Surface Destroy command
    190  1.1  riastrad  */
    191  1.1  riastrad struct vmw_surface_destroy {
    192  1.1  riastrad 	SVGA3dCmdHeader header;
    193  1.1  riastrad 	SVGA3dCmdDestroySurface body;
    194  1.1  riastrad };
    195  1.1  riastrad 
    196  1.1  riastrad 
    197  1.1  riastrad /**
    198  1.1  riastrad  * vmw_surface_dma_size - Compute fifo size for a dma command.
    199  1.1  riastrad  *
    200  1.1  riastrad  * @srf: Pointer to a struct vmw_surface
    201  1.1  riastrad  *
    202  1.1  riastrad  * Computes the required size for a surface dma command for backup or
    203  1.1  riastrad  * restoration of the surface represented by @srf.
    204  1.1  riastrad  */
    205  1.1  riastrad static inline uint32_t vmw_surface_dma_size(const struct vmw_surface *srf)
    206  1.1  riastrad {
    207  1.1  riastrad 	return srf->num_sizes * sizeof(struct vmw_surface_dma);
    208  1.1  riastrad }
    209  1.1  riastrad 
    210  1.1  riastrad 
    211  1.1  riastrad /**
    212  1.1  riastrad  * vmw_surface_define_size - Compute fifo size for a surface define command.
    213  1.1  riastrad  *
    214  1.1  riastrad  * @srf: Pointer to a struct vmw_surface
    215  1.1  riastrad  *
    216  1.1  riastrad  * Computes the required size for a surface define command for the definition
    217  1.1  riastrad  * of the surface represented by @srf.
    218  1.1  riastrad  */
    219  1.1  riastrad static inline uint32_t vmw_surface_define_size(const struct vmw_surface *srf)
    220  1.1  riastrad {
    221  1.1  riastrad 	return sizeof(struct vmw_surface_define) + srf->num_sizes *
    222  1.1  riastrad 		sizeof(SVGA3dSize);
    223  1.1  riastrad }
    224  1.1  riastrad 
    225  1.1  riastrad 
    226  1.1  riastrad /**
    227  1.1  riastrad  * vmw_surface_destroy_size - Compute fifo size for a surface destroy command.
    228  1.1  riastrad  *
    229  1.1  riastrad  * Computes the required size for a surface destroy command for the destruction
    230  1.1  riastrad  * of a hw surface.
    231  1.1  riastrad  */
    232  1.1  riastrad static inline uint32_t vmw_surface_destroy_size(void)
    233  1.1  riastrad {
    234  1.1  riastrad 	return sizeof(struct vmw_surface_destroy);
    235  1.1  riastrad }
    236  1.1  riastrad 
    237  1.1  riastrad /**
    238  1.1  riastrad  * vmw_surface_destroy_encode - Encode a surface_destroy command.
    239  1.1  riastrad  *
    240  1.1  riastrad  * @id: The surface id
    241  1.1  riastrad  * @cmd_space: Pointer to memory area in which the commands should be encoded.
    242  1.1  riastrad  */
    243  1.1  riastrad static void vmw_surface_destroy_encode(uint32_t id,
    244  1.1  riastrad 				       void *cmd_space)
    245  1.1  riastrad {
    246  1.1  riastrad 	struct vmw_surface_destroy *cmd = (struct vmw_surface_destroy *)
    247  1.1  riastrad 		cmd_space;
    248  1.1  riastrad 
    249  1.1  riastrad 	cmd->header.id = SVGA_3D_CMD_SURFACE_DESTROY;
    250  1.1  riastrad 	cmd->header.size = sizeof(cmd->body);
    251  1.1  riastrad 	cmd->body.sid = id;
    252  1.1  riastrad }
    253  1.1  riastrad 
    254  1.1  riastrad /**
    255  1.1  riastrad  * vmw_surface_define_encode - Encode a surface_define command.
    256  1.1  riastrad  *
    257  1.1  riastrad  * @srf: Pointer to a struct vmw_surface object.
    258  1.1  riastrad  * @cmd_space: Pointer to memory area in which the commands should be encoded.
    259  1.1  riastrad  */
    260  1.1  riastrad static void vmw_surface_define_encode(const struct vmw_surface *srf,
    261  1.1  riastrad 				      void *cmd_space)
    262  1.1  riastrad {
    263  1.1  riastrad 	struct vmw_surface_define *cmd = (struct vmw_surface_define *)
    264  1.1  riastrad 		cmd_space;
    265  1.1  riastrad 	struct drm_vmw_size *src_size;
    266  1.1  riastrad 	SVGA3dSize *cmd_size;
    267  1.1  riastrad 	uint32_t cmd_len;
    268  1.1  riastrad 	int i;
    269  1.1  riastrad 
    270  1.1  riastrad 	cmd_len = sizeof(cmd->body) + srf->num_sizes * sizeof(SVGA3dSize);
    271  1.1  riastrad 
    272  1.1  riastrad 	cmd->header.id = SVGA_3D_CMD_SURFACE_DEFINE;
    273  1.1  riastrad 	cmd->header.size = cmd_len;
    274  1.1  riastrad 	cmd->body.sid = srf->res.id;
    275  1.3  riastrad 	/*
    276  1.3  riastrad 	 * Downcast of surfaceFlags, was upcasted when received from user-space,
    277  1.3  riastrad 	 * since driver internally stores as 64 bit.
    278  1.3  riastrad 	 * For legacy surface define only 32 bit flag is supported.
    279  1.3  riastrad 	 */
    280  1.3  riastrad 	cmd->body.surfaceFlags = (SVGA3dSurface1Flags)srf->flags;
    281  1.2  riastrad 	cmd->body.format = srf->format;
    282  1.1  riastrad 	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i)
    283  1.1  riastrad 		cmd->body.face[i].numMipLevels = srf->mip_levels[i];
    284  1.1  riastrad 
    285  1.1  riastrad 	cmd += 1;
    286  1.1  riastrad 	cmd_size = (SVGA3dSize *) cmd;
    287  1.1  riastrad 	src_size = srf->sizes;
    288  1.1  riastrad 
    289  1.1  riastrad 	for (i = 0; i < srf->num_sizes; ++i, cmd_size++, src_size++) {
    290  1.1  riastrad 		cmd_size->width = src_size->width;
    291  1.1  riastrad 		cmd_size->height = src_size->height;
    292  1.1  riastrad 		cmd_size->depth = src_size->depth;
    293  1.1  riastrad 	}
    294  1.1  riastrad }
    295  1.1  riastrad 
    296  1.1  riastrad /**
    297  1.1  riastrad  * vmw_surface_dma_encode - Encode a surface_dma command.
    298  1.1  riastrad  *
    299  1.1  riastrad  * @srf: Pointer to a struct vmw_surface object.
    300  1.1  riastrad  * @cmd_space: Pointer to memory area in which the commands should be encoded.
    301  1.1  riastrad  * @ptr: Pointer to an SVGAGuestPtr indicating where the surface contents
    302  1.1  riastrad  * should be placed or read from.
    303  1.1  riastrad  * @to_surface: Boolean whether to DMA to the surface or from the surface.
    304  1.1  riastrad  */
    305  1.1  riastrad static void vmw_surface_dma_encode(struct vmw_surface *srf,
    306  1.1  riastrad 				   void *cmd_space,
    307  1.1  riastrad 				   const SVGAGuestPtr *ptr,
    308  1.1  riastrad 				   bool to_surface)
    309  1.1  riastrad {
    310  1.1  riastrad 	uint32_t i;
    311  1.1  riastrad 	struct vmw_surface_dma *cmd = (struct vmw_surface_dma *)cmd_space;
    312  1.1  riastrad 	const struct svga3d_surface_desc *desc =
    313  1.1  riastrad 		svga3dsurface_get_desc(srf->format);
    314  1.1  riastrad 
    315  1.1  riastrad 	for (i = 0; i < srf->num_sizes; ++i) {
    316  1.1  riastrad 		SVGA3dCmdHeader *header = &cmd->header;
    317  1.1  riastrad 		SVGA3dCmdSurfaceDMA *body = &cmd->body;
    318  1.1  riastrad 		SVGA3dCopyBox *cb = &cmd->cb;
    319  1.1  riastrad 		SVGA3dCmdSurfaceDMASuffix *suffix = &cmd->suffix;
    320  1.1  riastrad 		const struct vmw_surface_offset *cur_offset = &srf->offsets[i];
    321  1.1  riastrad 		const struct drm_vmw_size *cur_size = &srf->sizes[i];
    322  1.1  riastrad 
    323  1.1  riastrad 		header->id = SVGA_3D_CMD_SURFACE_DMA;
    324  1.1  riastrad 		header->size = sizeof(*body) + sizeof(*cb) + sizeof(*suffix);
    325  1.1  riastrad 
    326  1.1  riastrad 		body->guest.ptr = *ptr;
    327  1.1  riastrad 		body->guest.ptr.offset += cur_offset->bo_offset;
    328  1.1  riastrad 		body->guest.pitch = svga3dsurface_calculate_pitch(desc,
    329  1.1  riastrad 								  cur_size);
    330  1.1  riastrad 		body->host.sid = srf->res.id;
    331  1.1  riastrad 		body->host.face = cur_offset->face;
    332  1.1  riastrad 		body->host.mipmap = cur_offset->mip;
    333  1.1  riastrad 		body->transfer = ((to_surface) ?  SVGA3D_WRITE_HOST_VRAM :
    334  1.1  riastrad 				  SVGA3D_READ_HOST_VRAM);
    335  1.1  riastrad 		cb->x = 0;
    336  1.1  riastrad 		cb->y = 0;
    337  1.1  riastrad 		cb->z = 0;
    338  1.1  riastrad 		cb->srcx = 0;
    339  1.1  riastrad 		cb->srcy = 0;
    340  1.1  riastrad 		cb->srcz = 0;
    341  1.1  riastrad 		cb->w = cur_size->width;
    342  1.1  riastrad 		cb->h = cur_size->height;
    343  1.1  riastrad 		cb->d = cur_size->depth;
    344  1.1  riastrad 
    345  1.1  riastrad 		suffix->suffixSize = sizeof(*suffix);
    346  1.1  riastrad 		suffix->maximumOffset =
    347  1.1  riastrad 			svga3dsurface_get_image_buffer_size(desc, cur_size,
    348  1.1  riastrad 							    body->guest.pitch);
    349  1.1  riastrad 		suffix->flags.discard = 0;
    350  1.1  riastrad 		suffix->flags.unsynchronized = 0;
    351  1.1  riastrad 		suffix->flags.reserved = 0;
    352  1.1  riastrad 		++cmd;
    353  1.1  riastrad 	}
    354  1.1  riastrad };
    355  1.1  riastrad 
    356  1.1  riastrad 
    357  1.1  riastrad /**
    358  1.1  riastrad  * vmw_hw_surface_destroy - destroy a Device surface
    359  1.1  riastrad  *
    360  1.1  riastrad  * @res:        Pointer to a struct vmw_resource embedded in a struct
    361  1.1  riastrad  *              vmw_surface.
    362  1.1  riastrad  *
    363  1.1  riastrad  * Destroys a the device surface associated with a struct vmw_surface if
    364  1.1  riastrad  * any, and adjusts accounting and resource count accordingly.
    365  1.1  riastrad  */
    366  1.1  riastrad static void vmw_hw_surface_destroy(struct vmw_resource *res)
    367  1.1  riastrad {
    368  1.1  riastrad 
    369  1.1  riastrad 	struct vmw_private *dev_priv = res->dev_priv;
    370  1.1  riastrad 	void *cmd;
    371  1.1  riastrad 
    372  1.2  riastrad 	if (res->func->destroy == vmw_gb_surface_destroy) {
    373  1.2  riastrad 		(void) vmw_gb_surface_destroy(res);
    374  1.2  riastrad 		return;
    375  1.2  riastrad 	}
    376  1.2  riastrad 
    377  1.1  riastrad 	if (res->id != -1) {
    378  1.1  riastrad 
    379  1.3  riastrad 		cmd = VMW_FIFO_RESERVE(dev_priv, vmw_surface_destroy_size());
    380  1.3  riastrad 		if (unlikely(!cmd))
    381  1.1  riastrad 			return;
    382  1.1  riastrad 
    383  1.1  riastrad 		vmw_surface_destroy_encode(res->id, cmd);
    384  1.1  riastrad 		vmw_fifo_commit(dev_priv, vmw_surface_destroy_size());
    385  1.1  riastrad 
    386  1.1  riastrad 		/*
    387  1.1  riastrad 		 * used_memory_size_atomic, or separate lock
    388  1.1  riastrad 		 * to avoid taking dev_priv::cmdbuf_mutex in
    389  1.1  riastrad 		 * the destroy path.
    390  1.1  riastrad 		 */
    391  1.1  riastrad 
    392  1.1  riastrad 		mutex_lock(&dev_priv->cmdbuf_mutex);
    393  1.1  riastrad 		dev_priv->used_memory_size -= res->backup_size;
    394  1.1  riastrad 		mutex_unlock(&dev_priv->cmdbuf_mutex);
    395  1.1  riastrad 	}
    396  1.1  riastrad }
    397  1.1  riastrad 
    398  1.1  riastrad /**
    399  1.1  riastrad  * vmw_legacy_srf_create - Create a device surface as part of the
    400  1.1  riastrad  * resource validation process.
    401  1.1  riastrad  *
    402  1.1  riastrad  * @res: Pointer to a struct vmw_surface.
    403  1.1  riastrad  *
    404  1.1  riastrad  * If the surface doesn't have a hw id.
    405  1.1  riastrad  *
    406  1.1  riastrad  * Returns -EBUSY if there wasn't sufficient device resources to
    407  1.1  riastrad  * complete the validation. Retry after freeing up resources.
    408  1.1  riastrad  *
    409  1.1  riastrad  * May return other errors if the kernel is out of guest resources.
    410  1.1  riastrad  */
    411  1.1  riastrad static int vmw_legacy_srf_create(struct vmw_resource *res)
    412  1.1  riastrad {
    413  1.1  riastrad 	struct vmw_private *dev_priv = res->dev_priv;
    414  1.1  riastrad 	struct vmw_surface *srf;
    415  1.1  riastrad 	uint32_t submit_size;
    416  1.1  riastrad 	uint8_t *cmd;
    417  1.1  riastrad 	int ret;
    418  1.1  riastrad 
    419  1.1  riastrad 	if (likely(res->id != -1))
    420  1.1  riastrad 		return 0;
    421  1.1  riastrad 
    422  1.1  riastrad 	srf = vmw_res_to_srf(res);
    423  1.1  riastrad 	if (unlikely(dev_priv->used_memory_size + res->backup_size >=
    424  1.1  riastrad 		     dev_priv->memory_size))
    425  1.1  riastrad 		return -EBUSY;
    426  1.1  riastrad 
    427  1.1  riastrad 	/*
    428  1.1  riastrad 	 * Alloc id for the resource.
    429  1.1  riastrad 	 */
    430  1.1  riastrad 
    431  1.1  riastrad 	ret = vmw_resource_alloc_id(res);
    432  1.1  riastrad 	if (unlikely(ret != 0)) {
    433  1.1  riastrad 		DRM_ERROR("Failed to allocate a surface id.\n");
    434  1.1  riastrad 		goto out_no_id;
    435  1.1  riastrad 	}
    436  1.1  riastrad 
    437  1.1  riastrad 	if (unlikely(res->id >= SVGA3D_MAX_SURFACE_IDS)) {
    438  1.1  riastrad 		ret = -EBUSY;
    439  1.1  riastrad 		goto out_no_fifo;
    440  1.1  riastrad 	}
    441  1.1  riastrad 
    442  1.1  riastrad 	/*
    443  1.1  riastrad 	 * Encode surface define- commands.
    444  1.1  riastrad 	 */
    445  1.1  riastrad 
    446  1.1  riastrad 	submit_size = vmw_surface_define_size(srf);
    447  1.3  riastrad 	cmd = VMW_FIFO_RESERVE(dev_priv, submit_size);
    448  1.3  riastrad 	if (unlikely(!cmd)) {
    449  1.1  riastrad 		ret = -ENOMEM;
    450  1.1  riastrad 		goto out_no_fifo;
    451  1.1  riastrad 	}
    452  1.1  riastrad 
    453  1.1  riastrad 	vmw_surface_define_encode(srf, cmd);
    454  1.1  riastrad 	vmw_fifo_commit(dev_priv, submit_size);
    455  1.3  riastrad 	vmw_fifo_resource_inc(dev_priv);
    456  1.3  riastrad 
    457  1.1  riastrad 	/*
    458  1.1  riastrad 	 * Surface memory usage accounting.
    459  1.1  riastrad 	 */
    460  1.1  riastrad 
    461  1.1  riastrad 	dev_priv->used_memory_size += res->backup_size;
    462  1.1  riastrad 	return 0;
    463  1.1  riastrad 
    464  1.1  riastrad out_no_fifo:
    465  1.1  riastrad 	vmw_resource_release_id(res);
    466  1.1  riastrad out_no_id:
    467  1.1  riastrad 	return ret;
    468  1.1  riastrad }
    469  1.1  riastrad 
    470  1.1  riastrad /**
    471  1.1  riastrad  * vmw_legacy_srf_dma - Copy backup data to or from a legacy surface.
    472  1.1  riastrad  *
    473  1.1  riastrad  * @res:            Pointer to a struct vmw_res embedded in a struct
    474  1.1  riastrad  *                  vmw_surface.
    475  1.1  riastrad  * @val_buf:        Pointer to a struct ttm_validate_buffer containing
    476  1.1  riastrad  *                  information about the backup buffer.
    477  1.1  riastrad  * @bind:           Boolean wether to DMA to the surface.
    478  1.1  riastrad  *
    479  1.1  riastrad  * Transfer backup data to or from a legacy surface as part of the
    480  1.1  riastrad  * validation process.
    481  1.1  riastrad  * May return other errors if the kernel is out of guest resources.
    482  1.1  riastrad  * The backup buffer will be fenced or idle upon successful completion,
    483  1.1  riastrad  * and if the surface needs persistent backup storage, the backup buffer
    484  1.1  riastrad  * will also be returned reserved iff @bind is true.
    485  1.1  riastrad  */
    486  1.1  riastrad static int vmw_legacy_srf_dma(struct vmw_resource *res,
    487  1.1  riastrad 			      struct ttm_validate_buffer *val_buf,
    488  1.1  riastrad 			      bool bind)
    489  1.1  riastrad {
    490  1.1  riastrad 	SVGAGuestPtr ptr;
    491  1.1  riastrad 	struct vmw_fence_obj *fence;
    492  1.1  riastrad 	uint32_t submit_size;
    493  1.1  riastrad 	struct vmw_surface *srf = vmw_res_to_srf(res);
    494  1.1  riastrad 	uint8_t *cmd;
    495  1.1  riastrad 	struct vmw_private *dev_priv = res->dev_priv;
    496  1.1  riastrad 
    497  1.3  riastrad 	BUG_ON(!val_buf->bo);
    498  1.1  riastrad 	submit_size = vmw_surface_dma_size(srf);
    499  1.3  riastrad 	cmd = VMW_FIFO_RESERVE(dev_priv, submit_size);
    500  1.3  riastrad 	if (unlikely(!cmd))
    501  1.1  riastrad 		return -ENOMEM;
    502  1.3  riastrad 
    503  1.1  riastrad 	vmw_bo_get_guest_ptr(val_buf->bo, &ptr);
    504  1.1  riastrad 	vmw_surface_dma_encode(srf, cmd, &ptr, bind);
    505  1.1  riastrad 
    506  1.1  riastrad 	vmw_fifo_commit(dev_priv, submit_size);
    507  1.1  riastrad 
    508  1.1  riastrad 	/*
    509  1.1  riastrad 	 * Create a fence object and fence the backup buffer.
    510  1.1  riastrad 	 */
    511  1.1  riastrad 
    512  1.1  riastrad 	(void) vmw_execbuf_fence_commands(NULL, dev_priv,
    513  1.1  riastrad 					  &fence, NULL);
    514  1.1  riastrad 
    515  1.3  riastrad 	vmw_bo_fence_single(val_buf->bo, fence);
    516  1.1  riastrad 
    517  1.1  riastrad 	if (likely(fence != NULL))
    518  1.1  riastrad 		vmw_fence_obj_unreference(&fence);
    519  1.1  riastrad 
    520  1.1  riastrad 	return 0;
    521  1.1  riastrad }
    522  1.1  riastrad 
    523  1.1  riastrad /**
    524  1.1  riastrad  * vmw_legacy_srf_bind - Perform a legacy surface bind as part of the
    525  1.1  riastrad  *                       surface validation process.
    526  1.1  riastrad  *
    527  1.1  riastrad  * @res:            Pointer to a struct vmw_res embedded in a struct
    528  1.1  riastrad  *                  vmw_surface.
    529  1.1  riastrad  * @val_buf:        Pointer to a struct ttm_validate_buffer containing
    530  1.1  riastrad  *                  information about the backup buffer.
    531  1.1  riastrad  *
    532  1.1  riastrad  * This function will copy backup data to the surface if the
    533  1.1  riastrad  * backup buffer is dirty.
    534  1.1  riastrad  */
    535  1.1  riastrad static int vmw_legacy_srf_bind(struct vmw_resource *res,
    536  1.1  riastrad 			       struct ttm_validate_buffer *val_buf)
    537  1.1  riastrad {
    538  1.1  riastrad 	if (!res->backup_dirty)
    539  1.1  riastrad 		return 0;
    540  1.1  riastrad 
    541  1.1  riastrad 	return vmw_legacy_srf_dma(res, val_buf, true);
    542  1.1  riastrad }
    543  1.1  riastrad 
    544  1.1  riastrad 
    545  1.1  riastrad /**
    546  1.1  riastrad  * vmw_legacy_srf_unbind - Perform a legacy surface unbind as part of the
    547  1.1  riastrad  *                         surface eviction process.
    548  1.1  riastrad  *
    549  1.1  riastrad  * @res:            Pointer to a struct vmw_res embedded in a struct
    550  1.1  riastrad  *                  vmw_surface.
    551  1.1  riastrad  * @val_buf:        Pointer to a struct ttm_validate_buffer containing
    552  1.1  riastrad  *                  information about the backup buffer.
    553  1.1  riastrad  *
    554  1.1  riastrad  * This function will copy backup data from the surface.
    555  1.1  riastrad  */
    556  1.1  riastrad static int vmw_legacy_srf_unbind(struct vmw_resource *res,
    557  1.1  riastrad 				 bool readback,
    558  1.1  riastrad 				 struct ttm_validate_buffer *val_buf)
    559  1.1  riastrad {
    560  1.1  riastrad 	if (unlikely(readback))
    561  1.1  riastrad 		return vmw_legacy_srf_dma(res, val_buf, false);
    562  1.1  riastrad 	return 0;
    563  1.1  riastrad }
    564  1.1  riastrad 
    565  1.1  riastrad /**
    566  1.1  riastrad  * vmw_legacy_srf_destroy - Destroy a device surface as part of a
    567  1.1  riastrad  *                          resource eviction process.
    568  1.1  riastrad  *
    569  1.1  riastrad  * @res:            Pointer to a struct vmw_res embedded in a struct
    570  1.1  riastrad  *                  vmw_surface.
    571  1.1  riastrad  */
    572  1.1  riastrad static int vmw_legacy_srf_destroy(struct vmw_resource *res)
    573  1.1  riastrad {
    574  1.1  riastrad 	struct vmw_private *dev_priv = res->dev_priv;
    575  1.1  riastrad 	uint32_t submit_size;
    576  1.1  riastrad 	uint8_t *cmd;
    577  1.1  riastrad 
    578  1.1  riastrad 	BUG_ON(res->id == -1);
    579  1.1  riastrad 
    580  1.1  riastrad 	/*
    581  1.1  riastrad 	 * Encode the dma- and surface destroy commands.
    582  1.1  riastrad 	 */
    583  1.1  riastrad 
    584  1.1  riastrad 	submit_size = vmw_surface_destroy_size();
    585  1.3  riastrad 	cmd = VMW_FIFO_RESERVE(dev_priv, submit_size);
    586  1.3  riastrad 	if (unlikely(!cmd))
    587  1.1  riastrad 		return -ENOMEM;
    588  1.1  riastrad 
    589  1.1  riastrad 	vmw_surface_destroy_encode(res->id, cmd);
    590  1.1  riastrad 	vmw_fifo_commit(dev_priv, submit_size);
    591  1.1  riastrad 
    592  1.1  riastrad 	/*
    593  1.1  riastrad 	 * Surface memory usage accounting.
    594  1.1  riastrad 	 */
    595  1.1  riastrad 
    596  1.1  riastrad 	dev_priv->used_memory_size -= res->backup_size;
    597  1.1  riastrad 
    598  1.1  riastrad 	/*
    599  1.1  riastrad 	 * Release the surface ID.
    600  1.1  riastrad 	 */
    601  1.1  riastrad 
    602  1.1  riastrad 	vmw_resource_release_id(res);
    603  1.3  riastrad 	vmw_fifo_resource_dec(dev_priv);
    604  1.1  riastrad 
    605  1.1  riastrad 	return 0;
    606  1.1  riastrad }
    607  1.1  riastrad 
    608  1.1  riastrad 
    609  1.1  riastrad /**
    610  1.1  riastrad  * vmw_surface_init - initialize a struct vmw_surface
    611  1.1  riastrad  *
    612  1.1  riastrad  * @dev_priv:       Pointer to a device private struct.
    613  1.1  riastrad  * @srf:            Pointer to the struct vmw_surface to initialize.
    614  1.1  riastrad  * @res_free:       Pointer to a resource destructor used to free
    615  1.1  riastrad  *                  the object.
    616  1.1  riastrad  */
    617  1.1  riastrad static int vmw_surface_init(struct vmw_private *dev_priv,
    618  1.1  riastrad 			    struct vmw_surface *srf,
    619  1.1  riastrad 			    void (*res_free) (struct vmw_resource *res))
    620  1.1  riastrad {
    621  1.1  riastrad 	int ret;
    622  1.1  riastrad 	struct vmw_resource *res = &srf->res;
    623  1.1  riastrad 
    624  1.3  riastrad 	BUG_ON(!res_free);
    625  1.1  riastrad 	ret = vmw_resource_init(dev_priv, res, true, res_free,
    626  1.2  riastrad 				(dev_priv->has_mob) ? &vmw_gb_surface_func :
    627  1.1  riastrad 				&vmw_legacy_surface_func);
    628  1.1  riastrad 
    629  1.1  riastrad 	if (unlikely(ret != 0)) {
    630  1.1  riastrad 		res_free(res);
    631  1.1  riastrad 		return ret;
    632  1.1  riastrad 	}
    633  1.1  riastrad 
    634  1.1  riastrad 	/*
    635  1.1  riastrad 	 * The surface won't be visible to hardware until a
    636  1.1  riastrad 	 * surface validate.
    637  1.1  riastrad 	 */
    638  1.1  riastrad 
    639  1.2  riastrad 	INIT_LIST_HEAD(&srf->view_list);
    640  1.3  riastrad 	res->hw_destroy = vmw_hw_surface_destroy;
    641  1.1  riastrad 	return ret;
    642  1.1  riastrad }
    643  1.1  riastrad 
    644  1.1  riastrad /**
    645  1.1  riastrad  * vmw_user_surface_base_to_res - TTM base object to resource converter for
    646  1.1  riastrad  *                                user visible surfaces
    647  1.1  riastrad  *
    648  1.1  riastrad  * @base:           Pointer to a TTM base object
    649  1.1  riastrad  *
    650  1.1  riastrad  * Returns the struct vmw_resource embedded in a struct vmw_surface
    651  1.1  riastrad  * for the user-visible object identified by the TTM base object @base.
    652  1.1  riastrad  */
    653  1.1  riastrad static struct vmw_resource *
    654  1.1  riastrad vmw_user_surface_base_to_res(struct ttm_base_object *base)
    655  1.1  riastrad {
    656  1.2  riastrad 	return &(container_of(base, struct vmw_user_surface,
    657  1.2  riastrad 			      prime.base)->srf.res);
    658  1.1  riastrad }
    659  1.1  riastrad 
    660  1.1  riastrad /**
    661  1.1  riastrad  * vmw_user_surface_free - User visible surface resource destructor
    662  1.1  riastrad  *
    663  1.1  riastrad  * @res:            A struct vmw_resource embedded in a struct vmw_surface.
    664  1.1  riastrad  */
    665  1.1  riastrad static void vmw_user_surface_free(struct vmw_resource *res)
    666  1.1  riastrad {
    667  1.1  riastrad 	struct vmw_surface *srf = vmw_res_to_srf(res);
    668  1.1  riastrad 	struct vmw_user_surface *user_srf =
    669  1.1  riastrad 	    container_of(srf, struct vmw_user_surface, srf);
    670  1.1  riastrad 	struct vmw_private *dev_priv = srf->res.dev_priv;
    671  1.1  riastrad 	uint32_t size = user_srf->size;
    672  1.1  riastrad 
    673  1.3  riastrad 	WARN_ON_ONCE(res->dirty);
    674  1.2  riastrad 	if (user_srf->master)
    675  1.2  riastrad 		drm_master_put(&user_srf->master);
    676  1.1  riastrad 	kfree(srf->offsets);
    677  1.1  riastrad 	kfree(srf->sizes);
    678  1.1  riastrad 	kfree(srf->snooper.image);
    679  1.2  riastrad 	ttm_prime_object_kfree(user_srf, prime);
    680  1.1  riastrad 	ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
    681  1.1  riastrad }
    682  1.1  riastrad 
    683  1.1  riastrad /**
    684  1.1  riastrad  * vmw_user_surface_free - User visible surface TTM base object destructor
    685  1.1  riastrad  *
    686  1.1  riastrad  * @p_base:         Pointer to a pointer to a TTM base object
    687  1.1  riastrad  *                  embedded in a struct vmw_user_surface.
    688  1.1  riastrad  *
    689  1.1  riastrad  * Drops the base object's reference on its resource, and the
    690  1.1  riastrad  * pointer pointed to by *p_base is set to NULL.
    691  1.1  riastrad  */
    692  1.1  riastrad static void vmw_user_surface_base_release(struct ttm_base_object **p_base)
    693  1.1  riastrad {
    694  1.1  riastrad 	struct ttm_base_object *base = *p_base;
    695  1.1  riastrad 	struct vmw_user_surface *user_srf =
    696  1.2  riastrad 	    container_of(base, struct vmw_user_surface, prime.base);
    697  1.1  riastrad 	struct vmw_resource *res = &user_srf->srf.res;
    698  1.1  riastrad 
    699  1.1  riastrad 	*p_base = NULL;
    700  1.2  riastrad 	if (user_srf->backup_base)
    701  1.2  riastrad 		ttm_base_object_unref(&user_srf->backup_base);
    702  1.1  riastrad 	vmw_resource_unreference(&res);
    703  1.1  riastrad }
    704  1.1  riastrad 
    705  1.1  riastrad /**
    706  1.1  riastrad  * vmw_user_surface_destroy_ioctl - Ioctl function implementing
    707  1.1  riastrad  *                                  the user surface destroy functionality.
    708  1.1  riastrad  *
    709  1.1  riastrad  * @dev:            Pointer to a struct drm_device.
    710  1.1  riastrad  * @data:           Pointer to data copied from / to user-space.
    711  1.1  riastrad  * @file_priv:      Pointer to a drm file private structure.
    712  1.1  riastrad  */
    713  1.1  riastrad int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
    714  1.1  riastrad 			      struct drm_file *file_priv)
    715  1.1  riastrad {
    716  1.1  riastrad 	struct drm_vmw_surface_arg *arg = (struct drm_vmw_surface_arg *)data;
    717  1.1  riastrad 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
    718  1.1  riastrad 
    719  1.1  riastrad 	return ttm_ref_object_base_unref(tfile, arg->sid, TTM_REF_USAGE);
    720  1.1  riastrad }
    721  1.1  riastrad 
    722  1.1  riastrad /**
    723  1.1  riastrad  * vmw_user_surface_define_ioctl - Ioctl function implementing
    724  1.1  riastrad  *                                  the user surface define functionality.
    725  1.1  riastrad  *
    726  1.1  riastrad  * @dev:            Pointer to a struct drm_device.
    727  1.1  riastrad  * @data:           Pointer to data copied from / to user-space.
    728  1.1  riastrad  * @file_priv:      Pointer to a drm file private structure.
    729  1.1  riastrad  */
    730  1.1  riastrad int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
    731  1.1  riastrad 			     struct drm_file *file_priv)
    732  1.1  riastrad {
    733  1.1  riastrad 	struct vmw_private *dev_priv = vmw_priv(dev);
    734  1.1  riastrad 	struct vmw_user_surface *user_srf;
    735  1.1  riastrad 	struct vmw_surface *srf;
    736  1.1  riastrad 	struct vmw_resource *res;
    737  1.1  riastrad 	struct vmw_resource *tmp;
    738  1.1  riastrad 	union drm_vmw_surface_create_arg *arg =
    739  1.1  riastrad 	    (union drm_vmw_surface_create_arg *)data;
    740  1.1  riastrad 	struct drm_vmw_surface_create_req *req = &arg->req;
    741  1.1  riastrad 	struct drm_vmw_surface_arg *rep = &arg->rep;
    742  1.1  riastrad 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
    743  1.3  riastrad 	struct ttm_operation_ctx ctx = {
    744  1.3  riastrad 		.interruptible = true,
    745  1.3  riastrad 		.no_wait_gpu = false
    746  1.3  riastrad 	};
    747  1.1  riastrad 	int ret;
    748  1.1  riastrad 	int i, j;
    749  1.1  riastrad 	uint32_t cur_bo_offset;
    750  1.1  riastrad 	struct drm_vmw_size *cur_size;
    751  1.1  riastrad 	struct vmw_surface_offset *cur_offset;
    752  1.1  riastrad 	uint32_t num_sizes;
    753  1.1  riastrad 	uint32_t size;
    754  1.1  riastrad 	const struct svga3d_surface_desc *desc;
    755  1.1  riastrad 
    756  1.1  riastrad 	if (unlikely(vmw_user_surface_size == 0))
    757  1.1  riastrad 		vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
    758  1.3  riastrad 			VMW_IDA_ACC_SIZE + TTM_OBJ_EXTRA_SIZE;
    759  1.1  riastrad 
    760  1.1  riastrad 	num_sizes = 0;
    761  1.2  riastrad 	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
    762  1.2  riastrad 		if (req->mip_levels[i] > DRM_VMW_MAX_MIP_LEVELS)
    763  1.2  riastrad 			return -EINVAL;
    764  1.1  riastrad 		num_sizes += req->mip_levels[i];
    765  1.2  riastrad 	}
    766  1.1  riastrad 
    767  1.2  riastrad 	if (num_sizes > DRM_VMW_MAX_SURFACE_FACES * DRM_VMW_MAX_MIP_LEVELS ||
    768  1.2  riastrad 	    num_sizes == 0)
    769  1.1  riastrad 		return -EINVAL;
    770  1.1  riastrad 
    771  1.3  riastrad 	size = vmw_user_surface_size +
    772  1.1  riastrad 		ttm_round_pot(num_sizes * sizeof(struct drm_vmw_size)) +
    773  1.1  riastrad 		ttm_round_pot(num_sizes * sizeof(struct vmw_surface_offset));
    774  1.1  riastrad 
    775  1.1  riastrad 	desc = svga3dsurface_get_desc(req->format);
    776  1.1  riastrad 	if (unlikely(desc->block_desc == SVGA3DBLOCKDESC_NONE)) {
    777  1.3  riastrad 		VMW_DEBUG_USER("Invalid format %d for surface creation.\n",
    778  1.3  riastrad 			       req->format);
    779  1.1  riastrad 		return -EINVAL;
    780  1.1  riastrad 	}
    781  1.1  riastrad 
    782  1.2  riastrad 	ret = ttm_read_lock(&dev_priv->reservation_sem, true);
    783  1.1  riastrad 	if (unlikely(ret != 0))
    784  1.1  riastrad 		return ret;
    785  1.1  riastrad 
    786  1.1  riastrad 	ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
    787  1.3  riastrad 				   size, &ctx);
    788  1.1  riastrad 	if (unlikely(ret != 0)) {
    789  1.1  riastrad 		if (ret != -ERESTARTSYS)
    790  1.3  riastrad 			DRM_ERROR("Out of graphics memory for surface.\n");
    791  1.1  riastrad 		goto out_unlock;
    792  1.1  riastrad 	}
    793  1.1  riastrad 
    794  1.1  riastrad 	user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL);
    795  1.3  riastrad 	if (unlikely(!user_srf)) {
    796  1.1  riastrad 		ret = -ENOMEM;
    797  1.1  riastrad 		goto out_no_user_srf;
    798  1.1  riastrad 	}
    799  1.1  riastrad 
    800  1.1  riastrad 	srf = &user_srf->srf;
    801  1.1  riastrad 	res = &srf->res;
    802  1.1  riastrad 
    803  1.3  riastrad 	/* Driver internally stores as 64-bit flags */
    804  1.3  riastrad 	srf->flags = (SVGA3dSurfaceAllFlags)req->flags;
    805  1.1  riastrad 	srf->format = req->format;
    806  1.1  riastrad 	srf->scanout = req->scanout;
    807  1.1  riastrad 
    808  1.1  riastrad 	memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels));
    809  1.1  riastrad 	srf->num_sizes = num_sizes;
    810  1.1  riastrad 	user_srf->size = size;
    811  1.3  riastrad 	srf->sizes = memdup_user((struct drm_vmw_size __user *)(unsigned long)
    812  1.3  riastrad 				 req->size_addr,
    813  1.3  riastrad 				 sizeof(*srf->sizes) * srf->num_sizes);
    814  1.3  riastrad 	if (IS_ERR(srf->sizes)) {
    815  1.3  riastrad 		ret = PTR_ERR(srf->sizes);
    816  1.1  riastrad 		goto out_no_sizes;
    817  1.1  riastrad 	}
    818  1.3  riastrad 	srf->offsets = kmalloc_array(srf->num_sizes,
    819  1.3  riastrad 				     sizeof(*srf->offsets),
    820  1.3  riastrad 				     GFP_KERNEL);
    821  1.3  riastrad 	if (unlikely(!srf->offsets)) {
    822  1.1  riastrad 		ret = -ENOMEM;
    823  1.1  riastrad 		goto out_no_offsets;
    824  1.1  riastrad 	}
    825  1.1  riastrad 
    826  1.1  riastrad 	srf->base_size = *srf->sizes;
    827  1.1  riastrad 	srf->autogen_filter = SVGA3D_TEX_FILTER_NONE;
    828  1.2  riastrad 	srf->multisample_count = 0;
    829  1.3  riastrad 	srf->multisample_pattern = SVGA3D_MS_PATTERN_NONE;
    830  1.3  riastrad 	srf->quality_level = SVGA3D_MS_QUALITY_NONE;
    831  1.1  riastrad 
    832  1.1  riastrad 	cur_bo_offset = 0;
    833  1.1  riastrad 	cur_offset = srf->offsets;
    834  1.1  riastrad 	cur_size = srf->sizes;
    835  1.1  riastrad 
    836  1.1  riastrad 	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
    837  1.1  riastrad 		for (j = 0; j < srf->mip_levels[i]; ++j) {
    838  1.1  riastrad 			uint32_t stride = svga3dsurface_calculate_pitch
    839  1.1  riastrad 				(desc, cur_size);
    840  1.1  riastrad 
    841  1.1  riastrad 			cur_offset->face = i;
    842  1.1  riastrad 			cur_offset->mip = j;
    843  1.1  riastrad 			cur_offset->bo_offset = cur_bo_offset;
    844  1.1  riastrad 			cur_bo_offset += svga3dsurface_get_image_buffer_size
    845  1.1  riastrad 				(desc, cur_size, stride);
    846  1.1  riastrad 			++cur_offset;
    847  1.1  riastrad 			++cur_size;
    848  1.1  riastrad 		}
    849  1.1  riastrad 	}
    850  1.1  riastrad 	res->backup_size = cur_bo_offset;
    851  1.1  riastrad 	if (srf->scanout &&
    852  1.1  riastrad 	    srf->num_sizes == 1 &&
    853  1.1  riastrad 	    srf->sizes[0].width == 64 &&
    854  1.1  riastrad 	    srf->sizes[0].height == 64 &&
    855  1.1  riastrad 	    srf->format == SVGA3D_A8R8G8B8) {
    856  1.1  riastrad 
    857  1.3  riastrad 		srf->snooper.image = kzalloc(64 * 64 * 4, GFP_KERNEL);
    858  1.3  riastrad 		if (!srf->snooper.image) {
    859  1.1  riastrad 			DRM_ERROR("Failed to allocate cursor_image\n");
    860  1.1  riastrad 			ret = -ENOMEM;
    861  1.1  riastrad 			goto out_no_copy;
    862  1.1  riastrad 		}
    863  1.1  riastrad 	} else {
    864  1.1  riastrad 		srf->snooper.image = NULL;
    865  1.1  riastrad 	}
    866  1.1  riastrad 
    867  1.2  riastrad 	user_srf->prime.base.shareable = false;
    868  1.2  riastrad 	user_srf->prime.base.tfile = NULL;
    869  1.2  riastrad 	if (drm_is_primary_client(file_priv))
    870  1.2  riastrad 		user_srf->master = drm_master_get(file_priv->master);
    871  1.1  riastrad 
    872  1.1  riastrad 	/**
    873  1.1  riastrad 	 * From this point, the generic resource management functions
    874  1.1  riastrad 	 * destroy the object on failure.
    875  1.1  riastrad 	 */
    876  1.1  riastrad 
    877  1.1  riastrad 	ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free);
    878  1.1  riastrad 	if (unlikely(ret != 0))
    879  1.1  riastrad 		goto out_unlock;
    880  1.1  riastrad 
    881  1.2  riastrad 	/*
    882  1.2  riastrad 	 * A gb-aware client referencing a shared surface will
    883  1.2  riastrad 	 * expect a backup buffer to be present.
    884  1.2  riastrad 	 */
    885  1.2  riastrad 	if (dev_priv->has_mob && req->shareable) {
    886  1.2  riastrad 		uint32_t backup_handle;
    887  1.2  riastrad 
    888  1.3  riastrad 		ret = vmw_user_bo_alloc(dev_priv, tfile,
    889  1.3  riastrad 					res->backup_size,
    890  1.3  riastrad 					true,
    891  1.3  riastrad 					&backup_handle,
    892  1.3  riastrad 					&res->backup,
    893  1.3  riastrad 					&user_srf->backup_base);
    894  1.2  riastrad 		if (unlikely(ret != 0)) {
    895  1.2  riastrad 			vmw_resource_unreference(&res);
    896  1.2  riastrad 			goto out_unlock;
    897  1.2  riastrad 		}
    898  1.2  riastrad 	}
    899  1.2  riastrad 
    900  1.1  riastrad 	tmp = vmw_resource_reference(&srf->res);
    901  1.2  riastrad 	ret = ttm_prime_object_init(tfile, res->backup_size, &user_srf->prime,
    902  1.2  riastrad 				    req->shareable, VMW_RES_SURFACE,
    903  1.2  riastrad 				    &vmw_user_surface_base_release, NULL);
    904  1.1  riastrad 
    905  1.1  riastrad 	if (unlikely(ret != 0)) {
    906  1.1  riastrad 		vmw_resource_unreference(&tmp);
    907  1.1  riastrad 		vmw_resource_unreference(&res);
    908  1.1  riastrad 		goto out_unlock;
    909  1.1  riastrad 	}
    910  1.1  riastrad 
    911  1.3  riastrad 	rep->sid = user_srf->prime.base.handle;
    912  1.1  riastrad 	vmw_resource_unreference(&res);
    913  1.1  riastrad 
    914  1.2  riastrad 	ttm_read_unlock(&dev_priv->reservation_sem);
    915  1.1  riastrad 	return 0;
    916  1.1  riastrad out_no_copy:
    917  1.1  riastrad 	kfree(srf->offsets);
    918  1.1  riastrad out_no_offsets:
    919  1.1  riastrad 	kfree(srf->sizes);
    920  1.1  riastrad out_no_sizes:
    921  1.2  riastrad 	ttm_prime_object_kfree(user_srf, prime);
    922  1.1  riastrad out_no_user_srf:
    923  1.1  riastrad 	ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
    924  1.1  riastrad out_unlock:
    925  1.2  riastrad 	ttm_read_unlock(&dev_priv->reservation_sem);
    926  1.2  riastrad 	return ret;
    927  1.2  riastrad }
    928  1.2  riastrad 
    929  1.2  riastrad 
    930  1.2  riastrad static int
    931  1.2  riastrad vmw_surface_handle_reference(struct vmw_private *dev_priv,
    932  1.2  riastrad 			     struct drm_file *file_priv,
    933  1.2  riastrad 			     uint32_t u_handle,
    934  1.2  riastrad 			     enum drm_vmw_handle_type handle_type,
    935  1.2  riastrad 			     struct ttm_base_object **base_p)
    936  1.2  riastrad {
    937  1.2  riastrad 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
    938  1.2  riastrad 	struct vmw_user_surface *user_srf;
    939  1.2  riastrad 	uint32_t handle;
    940  1.2  riastrad 	struct ttm_base_object *base;
    941  1.2  riastrad 	int ret;
    942  1.2  riastrad 
    943  1.2  riastrad 	if (handle_type == DRM_VMW_HANDLE_PRIME) {
    944  1.2  riastrad 		ret = ttm_prime_fd_to_handle(tfile, u_handle, &handle);
    945  1.2  riastrad 		if (unlikely(ret != 0))
    946  1.2  riastrad 			return ret;
    947  1.2  riastrad 	} else {
    948  1.2  riastrad 		handle = u_handle;
    949  1.2  riastrad 	}
    950  1.2  riastrad 
    951  1.2  riastrad 	ret = -EINVAL;
    952  1.2  riastrad 	base = ttm_base_object_lookup_for_ref(dev_priv->tdev, handle);
    953  1.3  riastrad 	if (unlikely(!base)) {
    954  1.3  riastrad 		VMW_DEBUG_USER("Could not find surface to reference.\n");
    955  1.2  riastrad 		goto out_no_lookup;
    956  1.2  riastrad 	}
    957  1.2  riastrad 
    958  1.2  riastrad 	if (unlikely(ttm_base_object_type(base) != VMW_RES_SURFACE)) {
    959  1.3  riastrad 		VMW_DEBUG_USER("Referenced object is not a surface.\n");
    960  1.2  riastrad 		goto out_bad_resource;
    961  1.2  riastrad 	}
    962  1.2  riastrad 
    963  1.2  riastrad 	if (handle_type != DRM_VMW_HANDLE_PRIME) {
    964  1.3  riastrad 		bool require_exist = false;
    965  1.3  riastrad 
    966  1.2  riastrad 		user_srf = container_of(base, struct vmw_user_surface,
    967  1.2  riastrad 					prime.base);
    968  1.2  riastrad 
    969  1.3  riastrad 		/* Error out if we are unauthenticated primary */
    970  1.3  riastrad 		if (drm_is_primary_client(file_priv) &&
    971  1.3  riastrad 		    !file_priv->authenticated) {
    972  1.3  riastrad 			ret = -EACCES;
    973  1.3  riastrad 			goto out_bad_resource;
    974  1.3  riastrad 		}
    975  1.3  riastrad 
    976  1.2  riastrad 		/*
    977  1.2  riastrad 		 * Make sure the surface creator has the same
    978  1.2  riastrad 		 * authenticating master, or is already registered with us.
    979  1.2  riastrad 		 */
    980  1.2  riastrad 		if (drm_is_primary_client(file_priv) &&
    981  1.2  riastrad 		    user_srf->master != file_priv->master)
    982  1.2  riastrad 			require_exist = true;
    983  1.2  riastrad 
    984  1.3  riastrad 		if (unlikely(drm_is_render_client(file_priv)))
    985  1.3  riastrad 			require_exist = true;
    986  1.3  riastrad 
    987  1.2  riastrad 		ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL,
    988  1.2  riastrad 					 require_exist);
    989  1.2  riastrad 		if (unlikely(ret != 0)) {
    990  1.2  riastrad 			DRM_ERROR("Could not add a reference to a surface.\n");
    991  1.2  riastrad 			goto out_bad_resource;
    992  1.2  riastrad 		}
    993  1.2  riastrad 	}
    994  1.2  riastrad 
    995  1.2  riastrad 	*base_p = base;
    996  1.2  riastrad 	return 0;
    997  1.2  riastrad 
    998  1.2  riastrad out_bad_resource:
    999  1.2  riastrad 	ttm_base_object_unref(&base);
   1000  1.2  riastrad out_no_lookup:
   1001  1.2  riastrad 	if (handle_type == DRM_VMW_HANDLE_PRIME)
   1002  1.2  riastrad 		(void) ttm_ref_object_base_unref(tfile, handle, TTM_REF_USAGE);
   1003  1.2  riastrad 
   1004  1.1  riastrad 	return ret;
   1005  1.1  riastrad }
   1006  1.1  riastrad 
   1007  1.1  riastrad /**
   1008  1.1  riastrad  * vmw_user_surface_define_ioctl - Ioctl function implementing
   1009  1.1  riastrad  *                                  the user surface reference functionality.
   1010  1.1  riastrad  *
   1011  1.1  riastrad  * @dev:            Pointer to a struct drm_device.
   1012  1.1  riastrad  * @data:           Pointer to data copied from / to user-space.
   1013  1.1  riastrad  * @file_priv:      Pointer to a drm file private structure.
   1014  1.1  riastrad  */
   1015  1.1  riastrad int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
   1016  1.1  riastrad 				struct drm_file *file_priv)
   1017  1.1  riastrad {
   1018  1.2  riastrad 	struct vmw_private *dev_priv = vmw_priv(dev);
   1019  1.1  riastrad 	union drm_vmw_surface_reference_arg *arg =
   1020  1.1  riastrad 	    (union drm_vmw_surface_reference_arg *)data;
   1021  1.1  riastrad 	struct drm_vmw_surface_arg *req = &arg->req;
   1022  1.1  riastrad 	struct drm_vmw_surface_create_req *rep = &arg->rep;
   1023  1.1  riastrad 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
   1024  1.1  riastrad 	struct vmw_surface *srf;
   1025  1.1  riastrad 	struct vmw_user_surface *user_srf;
   1026  1.1  riastrad 	struct drm_vmw_size __user *user_sizes;
   1027  1.1  riastrad 	struct ttm_base_object *base;
   1028  1.2  riastrad 	int ret;
   1029  1.1  riastrad 
   1030  1.2  riastrad 	ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid,
   1031  1.2  riastrad 					   req->handle_type, &base);
   1032  1.2  riastrad 	if (unlikely(ret != 0))
   1033  1.2  riastrad 		return ret;
   1034  1.1  riastrad 
   1035  1.2  riastrad 	user_srf = container_of(base, struct vmw_user_surface, prime.base);
   1036  1.1  riastrad 	srf = &user_srf->srf;
   1037  1.1  riastrad 
   1038  1.3  riastrad 	/* Downcast of flags when sending back to user space */
   1039  1.3  riastrad 	rep->flags = (uint32_t)srf->flags;
   1040  1.1  riastrad 	rep->format = srf->format;
   1041  1.1  riastrad 	memcpy(rep->mip_levels, srf->mip_levels, sizeof(srf->mip_levels));
   1042  1.1  riastrad 	user_sizes = (struct drm_vmw_size __user *)(unsigned long)
   1043  1.1  riastrad 	    rep->size_addr;
   1044  1.1  riastrad 
   1045  1.1  riastrad 	if (user_sizes)
   1046  1.2  riastrad 		ret = copy_to_user(user_sizes, &srf->base_size,
   1047  1.2  riastrad 				   sizeof(srf->base_size));
   1048  1.1  riastrad 	if (unlikely(ret != 0)) {
   1049  1.3  riastrad 		VMW_DEBUG_USER("copy_to_user failed %p %u\n", user_sizes,
   1050  1.3  riastrad 			       srf->num_sizes);
   1051  1.3  riastrad 		ttm_ref_object_base_unref(tfile, base->handle, TTM_REF_USAGE);
   1052  1.1  riastrad 		ret = -EFAULT;
   1053  1.1  riastrad 	}
   1054  1.2  riastrad 
   1055  1.2  riastrad 	ttm_base_object_unref(&base);
   1056  1.2  riastrad 
   1057  1.2  riastrad 	return ret;
   1058  1.2  riastrad }
   1059  1.2  riastrad 
   1060  1.2  riastrad /**
   1061  1.2  riastrad  * vmw_surface_define_encode - Encode a surface_define command.
   1062  1.2  riastrad  *
   1063  1.2  riastrad  * @srf: Pointer to a struct vmw_surface object.
   1064  1.2  riastrad  * @cmd_space: Pointer to memory area in which the commands should be encoded.
   1065  1.2  riastrad  */
   1066  1.2  riastrad static int vmw_gb_surface_create(struct vmw_resource *res)
   1067  1.2  riastrad {
   1068  1.2  riastrad 	struct vmw_private *dev_priv = res->dev_priv;
   1069  1.2  riastrad 	struct vmw_surface *srf = vmw_res_to_srf(res);
   1070  1.2  riastrad 	uint32_t cmd_len, cmd_id, submit_len;
   1071  1.2  riastrad 	int ret;
   1072  1.2  riastrad 	struct {
   1073  1.2  riastrad 		SVGA3dCmdHeader header;
   1074  1.2  riastrad 		SVGA3dCmdDefineGBSurface body;
   1075  1.2  riastrad 	} *cmd;
   1076  1.2  riastrad 	struct {
   1077  1.2  riastrad 		SVGA3dCmdHeader header;
   1078  1.2  riastrad 		SVGA3dCmdDefineGBSurface_v2 body;
   1079  1.2  riastrad 	} *cmd2;
   1080  1.3  riastrad 	struct {
   1081  1.3  riastrad 		SVGA3dCmdHeader header;
   1082  1.3  riastrad 		SVGA3dCmdDefineGBSurface_v3 body;
   1083  1.3  riastrad 	} *cmd3;
   1084  1.2  riastrad 
   1085  1.2  riastrad 	if (likely(res->id != -1))
   1086  1.2  riastrad 		return 0;
   1087  1.2  riastrad 
   1088  1.2  riastrad 	vmw_fifo_resource_inc(dev_priv);
   1089  1.2  riastrad 	ret = vmw_resource_alloc_id(res);
   1090  1.2  riastrad 	if (unlikely(ret != 0)) {
   1091  1.2  riastrad 		DRM_ERROR("Failed to allocate a surface id.\n");
   1092  1.2  riastrad 		goto out_no_id;
   1093  1.2  riastrad 	}
   1094  1.2  riastrad 
   1095  1.2  riastrad 	if (unlikely(res->id >= VMWGFX_NUM_GB_SURFACE)) {
   1096  1.2  riastrad 		ret = -EBUSY;
   1097  1.2  riastrad 		goto out_no_fifo;
   1098  1.2  riastrad 	}
   1099  1.2  riastrad 
   1100  1.3  riastrad 	if (dev_priv->has_sm4_1 && srf->array_size > 0) {
   1101  1.3  riastrad 		cmd_id = SVGA_3D_CMD_DEFINE_GB_SURFACE_V3;
   1102  1.3  riastrad 		cmd_len = sizeof(cmd3->body);
   1103  1.3  riastrad 		submit_len = sizeof(*cmd3);
   1104  1.3  riastrad 	} else if (srf->array_size > 0) {
   1105  1.2  riastrad 		/* has_dx checked on creation time. */
   1106  1.2  riastrad 		cmd_id = SVGA_3D_CMD_DEFINE_GB_SURFACE_V2;
   1107  1.2  riastrad 		cmd_len = sizeof(cmd2->body);
   1108  1.2  riastrad 		submit_len = sizeof(*cmd2);
   1109  1.2  riastrad 	} else {
   1110  1.2  riastrad 		cmd_id = SVGA_3D_CMD_DEFINE_GB_SURFACE;
   1111  1.2  riastrad 		cmd_len = sizeof(cmd->body);
   1112  1.2  riastrad 		submit_len = sizeof(*cmd);
   1113  1.2  riastrad 	}
   1114  1.2  riastrad 
   1115  1.3  riastrad 	cmd = VMW_FIFO_RESERVE(dev_priv, submit_len);
   1116  1.2  riastrad 	cmd2 = (typeof(cmd2))cmd;
   1117  1.3  riastrad 	cmd3 = (typeof(cmd3))cmd;
   1118  1.3  riastrad 	if (unlikely(!cmd)) {
   1119  1.2  riastrad 		ret = -ENOMEM;
   1120  1.2  riastrad 		goto out_no_fifo;
   1121  1.2  riastrad 	}
   1122  1.2  riastrad 
   1123  1.3  riastrad 	if (dev_priv->has_sm4_1 && srf->array_size > 0) {
   1124  1.3  riastrad 		cmd3->header.id = cmd_id;
   1125  1.3  riastrad 		cmd3->header.size = cmd_len;
   1126  1.3  riastrad 		cmd3->body.sid = srf->res.id;
   1127  1.3  riastrad 		cmd3->body.surfaceFlags = srf->flags;
   1128  1.3  riastrad 		cmd3->body.format = srf->format;
   1129  1.3  riastrad 		cmd3->body.numMipLevels = srf->mip_levels[0];
   1130  1.3  riastrad 		cmd3->body.multisampleCount = srf->multisample_count;
   1131  1.3  riastrad 		cmd3->body.multisamplePattern = srf->multisample_pattern;
   1132  1.3  riastrad 		cmd3->body.qualityLevel = srf->quality_level;
   1133  1.3  riastrad 		cmd3->body.autogenFilter = srf->autogen_filter;
   1134  1.3  riastrad 		cmd3->body.size.width = srf->base_size.width;
   1135  1.3  riastrad 		cmd3->body.size.height = srf->base_size.height;
   1136  1.3  riastrad 		cmd3->body.size.depth = srf->base_size.depth;
   1137  1.3  riastrad 		cmd3->body.arraySize = srf->array_size;
   1138  1.3  riastrad 	} else if (srf->array_size > 0) {
   1139  1.2  riastrad 		cmd2->header.id = cmd_id;
   1140  1.2  riastrad 		cmd2->header.size = cmd_len;
   1141  1.2  riastrad 		cmd2->body.sid = srf->res.id;
   1142  1.2  riastrad 		cmd2->body.surfaceFlags = srf->flags;
   1143  1.3  riastrad 		cmd2->body.format = srf->format;
   1144  1.2  riastrad 		cmd2->body.numMipLevels = srf->mip_levels[0];
   1145  1.2  riastrad 		cmd2->body.multisampleCount = srf->multisample_count;
   1146  1.2  riastrad 		cmd2->body.autogenFilter = srf->autogen_filter;
   1147  1.2  riastrad 		cmd2->body.size.width = srf->base_size.width;
   1148  1.2  riastrad 		cmd2->body.size.height = srf->base_size.height;
   1149  1.2  riastrad 		cmd2->body.size.depth = srf->base_size.depth;
   1150  1.2  riastrad 		cmd2->body.arraySize = srf->array_size;
   1151  1.2  riastrad 	} else {
   1152  1.2  riastrad 		cmd->header.id = cmd_id;
   1153  1.2  riastrad 		cmd->header.size = cmd_len;
   1154  1.2  riastrad 		cmd->body.sid = srf->res.id;
   1155  1.2  riastrad 		cmd->body.surfaceFlags = srf->flags;
   1156  1.3  riastrad 		cmd->body.format = srf->format;
   1157  1.2  riastrad 		cmd->body.numMipLevels = srf->mip_levels[0];
   1158  1.2  riastrad 		cmd->body.multisampleCount = srf->multisample_count;
   1159  1.2  riastrad 		cmd->body.autogenFilter = srf->autogen_filter;
   1160  1.2  riastrad 		cmd->body.size.width = srf->base_size.width;
   1161  1.2  riastrad 		cmd->body.size.height = srf->base_size.height;
   1162  1.2  riastrad 		cmd->body.size.depth = srf->base_size.depth;
   1163  1.2  riastrad 	}
   1164  1.2  riastrad 
   1165  1.2  riastrad 	vmw_fifo_commit(dev_priv, submit_len);
   1166  1.2  riastrad 
   1167  1.2  riastrad 	return 0;
   1168  1.2  riastrad 
   1169  1.2  riastrad out_no_fifo:
   1170  1.2  riastrad 	vmw_resource_release_id(res);
   1171  1.2  riastrad out_no_id:
   1172  1.2  riastrad 	vmw_fifo_resource_dec(dev_priv);
   1173  1.2  riastrad 	return ret;
   1174  1.2  riastrad }
   1175  1.2  riastrad 
   1176  1.2  riastrad 
   1177  1.2  riastrad static int vmw_gb_surface_bind(struct vmw_resource *res,
   1178  1.2  riastrad 			       struct ttm_validate_buffer *val_buf)
   1179  1.2  riastrad {
   1180  1.2  riastrad 	struct vmw_private *dev_priv = res->dev_priv;
   1181  1.2  riastrad 	struct {
   1182  1.2  riastrad 		SVGA3dCmdHeader header;
   1183  1.2  riastrad 		SVGA3dCmdBindGBSurface body;
   1184  1.2  riastrad 	} *cmd1;
   1185  1.2  riastrad 	struct {
   1186  1.2  riastrad 		SVGA3dCmdHeader header;
   1187  1.2  riastrad 		SVGA3dCmdUpdateGBSurface body;
   1188  1.2  riastrad 	} *cmd2;
   1189  1.2  riastrad 	uint32_t submit_size;
   1190  1.2  riastrad 	struct ttm_buffer_object *bo = val_buf->bo;
   1191  1.2  riastrad 
   1192  1.2  riastrad 	BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
   1193  1.2  riastrad 
   1194  1.2  riastrad 	submit_size = sizeof(*cmd1) + (res->backup_dirty ? sizeof(*cmd2) : 0);
   1195  1.2  riastrad 
   1196  1.3  riastrad 	cmd1 = VMW_FIFO_RESERVE(dev_priv, submit_size);
   1197  1.3  riastrad 	if (unlikely(!cmd1))
   1198  1.2  riastrad 		return -ENOMEM;
   1199  1.2  riastrad 
   1200  1.2  riastrad 	cmd1->header.id = SVGA_3D_CMD_BIND_GB_SURFACE;
   1201  1.2  riastrad 	cmd1->header.size = sizeof(cmd1->body);
   1202  1.2  riastrad 	cmd1->body.sid = res->id;
   1203  1.2  riastrad 	cmd1->body.mobid = bo->mem.start;
   1204  1.2  riastrad 	if (res->backup_dirty) {
   1205  1.2  riastrad 		cmd2 = (void *) &cmd1[1];
   1206  1.2  riastrad 		cmd2->header.id = SVGA_3D_CMD_UPDATE_GB_SURFACE;
   1207  1.2  riastrad 		cmd2->header.size = sizeof(cmd2->body);
   1208  1.2  riastrad 		cmd2->body.sid = res->id;
   1209  1.2  riastrad 	}
   1210  1.2  riastrad 	vmw_fifo_commit(dev_priv, submit_size);
   1211  1.2  riastrad 
   1212  1.3  riastrad 	if (res->backup->dirty && res->backup_dirty) {
   1213  1.3  riastrad 		/* We've just made a full upload. Cear dirty regions. */
   1214  1.3  riastrad 		vmw_bo_dirty_clear_res(res);
   1215  1.3  riastrad 	}
   1216  1.3  riastrad 
   1217  1.3  riastrad 	res->backup_dirty = false;
   1218  1.3  riastrad 
   1219  1.2  riastrad 	return 0;
   1220  1.2  riastrad }
   1221  1.2  riastrad 
   1222  1.2  riastrad static int vmw_gb_surface_unbind(struct vmw_resource *res,
   1223  1.2  riastrad 				 bool readback,
   1224  1.2  riastrad 				 struct ttm_validate_buffer *val_buf)
   1225  1.2  riastrad {
   1226  1.2  riastrad 	struct vmw_private *dev_priv = res->dev_priv;
   1227  1.2  riastrad 	struct ttm_buffer_object *bo = val_buf->bo;
   1228  1.2  riastrad 	struct vmw_fence_obj *fence;
   1229  1.2  riastrad 
   1230  1.2  riastrad 	struct {
   1231  1.2  riastrad 		SVGA3dCmdHeader header;
   1232  1.2  riastrad 		SVGA3dCmdReadbackGBSurface body;
   1233  1.2  riastrad 	} *cmd1;
   1234  1.2  riastrad 	struct {
   1235  1.2  riastrad 		SVGA3dCmdHeader header;
   1236  1.2  riastrad 		SVGA3dCmdInvalidateGBSurface body;
   1237  1.2  riastrad 	} *cmd2;
   1238  1.2  riastrad 	struct {
   1239  1.2  riastrad 		SVGA3dCmdHeader header;
   1240  1.2  riastrad 		SVGA3dCmdBindGBSurface body;
   1241  1.2  riastrad 	} *cmd3;
   1242  1.2  riastrad 	uint32_t submit_size;
   1243  1.2  riastrad 	uint8_t *cmd;
   1244  1.2  riastrad 
   1245  1.2  riastrad 
   1246  1.2  riastrad 	BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
   1247  1.2  riastrad 
   1248  1.2  riastrad 	submit_size = sizeof(*cmd3) + (readback ? sizeof(*cmd1) : sizeof(*cmd2));
   1249  1.3  riastrad 	cmd = VMW_FIFO_RESERVE(dev_priv, submit_size);
   1250  1.3  riastrad 	if (unlikely(!cmd))
   1251  1.2  riastrad 		return -ENOMEM;
   1252  1.2  riastrad 
   1253  1.2  riastrad 	if (readback) {
   1254  1.2  riastrad 		cmd1 = (void *) cmd;
   1255  1.2  riastrad 		cmd1->header.id = SVGA_3D_CMD_READBACK_GB_SURFACE;
   1256  1.2  riastrad 		cmd1->header.size = sizeof(cmd1->body);
   1257  1.2  riastrad 		cmd1->body.sid = res->id;
   1258  1.2  riastrad 		cmd3 = (void *) &cmd1[1];
   1259  1.2  riastrad 	} else {
   1260  1.2  riastrad 		cmd2 = (void *) cmd;
   1261  1.2  riastrad 		cmd2->header.id = SVGA_3D_CMD_INVALIDATE_GB_SURFACE;
   1262  1.2  riastrad 		cmd2->header.size = sizeof(cmd2->body);
   1263  1.2  riastrad 		cmd2->body.sid = res->id;
   1264  1.2  riastrad 		cmd3 = (void *) &cmd2[1];
   1265  1.2  riastrad 	}
   1266  1.2  riastrad 
   1267  1.2  riastrad 	cmd3->header.id = SVGA_3D_CMD_BIND_GB_SURFACE;
   1268  1.2  riastrad 	cmd3->header.size = sizeof(cmd3->body);
   1269  1.2  riastrad 	cmd3->body.sid = res->id;
   1270  1.2  riastrad 	cmd3->body.mobid = SVGA3D_INVALID_ID;
   1271  1.2  riastrad 
   1272  1.2  riastrad 	vmw_fifo_commit(dev_priv, submit_size);
   1273  1.2  riastrad 
   1274  1.2  riastrad 	/*
   1275  1.2  riastrad 	 * Create a fence object and fence the backup buffer.
   1276  1.2  riastrad 	 */
   1277  1.2  riastrad 
   1278  1.2  riastrad 	(void) vmw_execbuf_fence_commands(NULL, dev_priv,
   1279  1.2  riastrad 					  &fence, NULL);
   1280  1.2  riastrad 
   1281  1.3  riastrad 	vmw_bo_fence_single(val_buf->bo, fence);
   1282  1.2  riastrad 
   1283  1.2  riastrad 	if (likely(fence != NULL))
   1284  1.2  riastrad 		vmw_fence_obj_unreference(&fence);
   1285  1.2  riastrad 
   1286  1.2  riastrad 	return 0;
   1287  1.2  riastrad }
   1288  1.2  riastrad 
   1289  1.2  riastrad static int vmw_gb_surface_destroy(struct vmw_resource *res)
   1290  1.2  riastrad {
   1291  1.2  riastrad 	struct vmw_private *dev_priv = res->dev_priv;
   1292  1.2  riastrad 	struct vmw_surface *srf = vmw_res_to_srf(res);
   1293  1.2  riastrad 	struct {
   1294  1.2  riastrad 		SVGA3dCmdHeader header;
   1295  1.2  riastrad 		SVGA3dCmdDestroyGBSurface body;
   1296  1.2  riastrad 	} *cmd;
   1297  1.2  riastrad 
   1298  1.2  riastrad 	if (likely(res->id == -1))
   1299  1.2  riastrad 		return 0;
   1300  1.2  riastrad 
   1301  1.2  riastrad 	mutex_lock(&dev_priv->binding_mutex);
   1302  1.2  riastrad 	vmw_view_surface_list_destroy(dev_priv, &srf->view_list);
   1303  1.2  riastrad 	vmw_binding_res_list_scrub(&res->binding_head);
   1304  1.2  riastrad 
   1305  1.3  riastrad 	cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
   1306  1.3  riastrad 	if (unlikely(!cmd)) {
   1307  1.2  riastrad 		mutex_unlock(&dev_priv->binding_mutex);
   1308  1.2  riastrad 		return -ENOMEM;
   1309  1.2  riastrad 	}
   1310  1.2  riastrad 
   1311  1.2  riastrad 	cmd->header.id = SVGA_3D_CMD_DESTROY_GB_SURFACE;
   1312  1.2  riastrad 	cmd->header.size = sizeof(cmd->body);
   1313  1.2  riastrad 	cmd->body.sid = res->id;
   1314  1.2  riastrad 	vmw_fifo_commit(dev_priv, sizeof(*cmd));
   1315  1.2  riastrad 	mutex_unlock(&dev_priv->binding_mutex);
   1316  1.2  riastrad 	vmw_resource_release_id(res);
   1317  1.2  riastrad 	vmw_fifo_resource_dec(dev_priv);
   1318  1.2  riastrad 
   1319  1.2  riastrad 	return 0;
   1320  1.2  riastrad }
   1321  1.2  riastrad 
   1322  1.2  riastrad 
   1323  1.2  riastrad /**
   1324  1.2  riastrad  * vmw_gb_surface_define_ioctl - Ioctl function implementing
   1325  1.3  riastrad  * the user surface define functionality.
   1326  1.2  riastrad  *
   1327  1.3  riastrad  * @dev: Pointer to a struct drm_device.
   1328  1.3  riastrad  * @data: Pointer to data copied from / to user-space.
   1329  1.3  riastrad  * @file_priv: Pointer to a drm file private structure.
   1330  1.2  riastrad  */
   1331  1.2  riastrad int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
   1332  1.2  riastrad 				struct drm_file *file_priv)
   1333  1.2  riastrad {
   1334  1.3  riastrad 	union drm_vmw_gb_surface_create_arg *arg =
   1335  1.3  riastrad 	    (union drm_vmw_gb_surface_create_arg *)data;
   1336  1.3  riastrad 	struct drm_vmw_gb_surface_create_rep *rep = &arg->rep;
   1337  1.3  riastrad 	struct drm_vmw_gb_surface_create_ext_req req_ext;
   1338  1.3  riastrad 
   1339  1.3  riastrad 	req_ext.base = arg->req;
   1340  1.3  riastrad 	req_ext.version = drm_vmw_gb_surface_v1;
   1341  1.3  riastrad 	req_ext.svga3d_flags_upper_32_bits = 0;
   1342  1.3  riastrad 	req_ext.multisample_pattern = SVGA3D_MS_PATTERN_NONE;
   1343  1.3  riastrad 	req_ext.quality_level = SVGA3D_MS_QUALITY_NONE;
   1344  1.3  riastrad 	req_ext.must_be_zero = 0;
   1345  1.3  riastrad 
   1346  1.3  riastrad 	return vmw_gb_surface_define_internal(dev, &req_ext, rep, file_priv);
   1347  1.3  riastrad }
   1348  1.3  riastrad 
   1349  1.3  riastrad /**
   1350  1.3  riastrad  * vmw_gb_surface_reference_ioctl - Ioctl function implementing
   1351  1.3  riastrad  * the user surface reference functionality.
   1352  1.3  riastrad  *
   1353  1.3  riastrad  * @dev: Pointer to a struct drm_device.
   1354  1.3  riastrad  * @data: Pointer to data copied from / to user-space.
   1355  1.3  riastrad  * @file_priv: Pointer to a drm file private structure.
   1356  1.3  riastrad  */
   1357  1.3  riastrad int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data,
   1358  1.3  riastrad 				   struct drm_file *file_priv)
   1359  1.3  riastrad {
   1360  1.3  riastrad 	union drm_vmw_gb_surface_reference_arg *arg =
   1361  1.3  riastrad 	    (union drm_vmw_gb_surface_reference_arg *)data;
   1362  1.3  riastrad 	struct drm_vmw_surface_arg *req = &arg->req;
   1363  1.3  riastrad 	struct drm_vmw_gb_surface_ref_rep *rep = &arg->rep;
   1364  1.3  riastrad 	struct drm_vmw_gb_surface_ref_ext_rep rep_ext;
   1365  1.3  riastrad 	int ret;
   1366  1.3  riastrad 
   1367  1.3  riastrad 	ret = vmw_gb_surface_reference_internal(dev, req, &rep_ext, file_priv);
   1368  1.3  riastrad 
   1369  1.3  riastrad 	if (unlikely(ret != 0))
   1370  1.3  riastrad 		return ret;
   1371  1.3  riastrad 
   1372  1.3  riastrad 	rep->creq = rep_ext.creq.base;
   1373  1.3  riastrad 	rep->crep = rep_ext.crep;
   1374  1.3  riastrad 
   1375  1.3  riastrad 	return ret;
   1376  1.3  riastrad }
   1377  1.3  riastrad 
   1378  1.3  riastrad /**
   1379  1.3  riastrad  * vmw_surface_gb_priv_define - Define a private GB surface
   1380  1.3  riastrad  *
   1381  1.3  riastrad  * @dev:  Pointer to a struct drm_device
   1382  1.3  riastrad  * @user_accounting_size:  Used to track user-space memory usage, set
   1383  1.3  riastrad  *                         to 0 for kernel mode only memory
   1384  1.3  riastrad  * @svga3d_flags: SVGA3d surface flags for the device
   1385  1.3  riastrad  * @format: requested surface format
   1386  1.3  riastrad  * @for_scanout: true if inteded to be used for scanout buffer
   1387  1.3  riastrad  * @num_mip_levels:  number of MIP levels
   1388  1.3  riastrad  * @multisample_count:
   1389  1.3  riastrad  * @array_size: Surface array size.
   1390  1.3  riastrad  * @size: width, heigh, depth of the surface requested
   1391  1.3  riastrad  * @multisample_pattern: Multisampling pattern when msaa is supported
   1392  1.3  riastrad  * @quality_level: Precision settings
   1393  1.3  riastrad  * @user_srf_out: allocated user_srf.  Set to NULL on failure.
   1394  1.3  riastrad  *
   1395  1.3  riastrad  * GB surfaces allocated by this function will not have a user mode handle, and
   1396  1.3  riastrad  * thus will only be visible to vmwgfx.  For optimization reasons the
   1397  1.3  riastrad  * surface may later be given a user mode handle by another function to make
   1398  1.3  riastrad  * it available to user mode drivers.
   1399  1.3  riastrad  */
   1400  1.3  riastrad int vmw_surface_gb_priv_define(struct drm_device *dev,
   1401  1.3  riastrad 			       uint32_t user_accounting_size,
   1402  1.3  riastrad 			       SVGA3dSurfaceAllFlags svga3d_flags,
   1403  1.3  riastrad 			       SVGA3dSurfaceFormat format,
   1404  1.3  riastrad 			       bool for_scanout,
   1405  1.3  riastrad 			       uint32_t num_mip_levels,
   1406  1.3  riastrad 			       uint32_t multisample_count,
   1407  1.3  riastrad 			       uint32_t array_size,
   1408  1.3  riastrad 			       struct drm_vmw_size size,
   1409  1.3  riastrad 			       SVGA3dMSPattern multisample_pattern,
   1410  1.3  riastrad 			       SVGA3dMSQualityLevel quality_level,
   1411  1.3  riastrad 			       struct vmw_surface **srf_out)
   1412  1.3  riastrad {
   1413  1.3  riastrad 	struct vmw_private *dev_priv = vmw_priv(dev);
   1414  1.3  riastrad 	struct vmw_user_surface *user_srf;
   1415  1.3  riastrad 	struct ttm_operation_ctx ctx = {
   1416  1.3  riastrad 		.interruptible = true,
   1417  1.3  riastrad 		.no_wait_gpu = false
   1418  1.3  riastrad 	};
   1419  1.3  riastrad 	struct vmw_surface *srf;
   1420  1.3  riastrad 	int ret;
   1421  1.3  riastrad 	u32 num_layers = 1;
   1422  1.3  riastrad 	u32 sample_count = 1;
   1423  1.3  riastrad 
   1424  1.3  riastrad 	*srf_out = NULL;
   1425  1.3  riastrad 
   1426  1.3  riastrad 	if (for_scanout) {
   1427  1.3  riastrad 		if (!svga3dsurface_is_screen_target_format(format)) {
   1428  1.3  riastrad 			VMW_DEBUG_USER("Invalid Screen Target surface format.");
   1429  1.3  riastrad 			return -EINVAL;
   1430  1.3  riastrad 		}
   1431  1.3  riastrad 
   1432  1.3  riastrad 		if (size.width > dev_priv->texture_max_width ||
   1433  1.3  riastrad 		    size.height > dev_priv->texture_max_height) {
   1434  1.3  riastrad 			VMW_DEBUG_USER("%ux%u\n, exceeds max surface size %ux%u",
   1435  1.3  riastrad 				       size.width, size.height,
   1436  1.3  riastrad 				       dev_priv->texture_max_width,
   1437  1.3  riastrad 				       dev_priv->texture_max_height);
   1438  1.3  riastrad 			return -EINVAL;
   1439  1.3  riastrad 		}
   1440  1.3  riastrad 	} else {
   1441  1.3  riastrad 		const struct svga3d_surface_desc *desc;
   1442  1.3  riastrad 
   1443  1.3  riastrad 		desc = svga3dsurface_get_desc(format);
   1444  1.3  riastrad 		if (unlikely(desc->block_desc == SVGA3DBLOCKDESC_NONE)) {
   1445  1.3  riastrad 			VMW_DEBUG_USER("Invalid surface format.\n");
   1446  1.3  riastrad 			return -EINVAL;
   1447  1.3  riastrad 		}
   1448  1.3  riastrad 	}
   1449  1.3  riastrad 
   1450  1.3  riastrad 	/* array_size must be null for non-GL3 host. */
   1451  1.3  riastrad 	if (array_size > 0 && !dev_priv->has_dx) {
   1452  1.3  riastrad 		VMW_DEBUG_USER("Tried to create DX surface on non-DX host.\n");
   1453  1.3  riastrad 		return -EINVAL;
   1454  1.3  riastrad 	}
   1455  1.3  riastrad 
   1456  1.3  riastrad 	ret = ttm_read_lock(&dev_priv->reservation_sem, true);
   1457  1.3  riastrad 	if (unlikely(ret != 0))
   1458  1.3  riastrad 		return ret;
   1459  1.3  riastrad 
   1460  1.3  riastrad 	ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
   1461  1.3  riastrad 				   user_accounting_size, &ctx);
   1462  1.3  riastrad 	if (unlikely(ret != 0)) {
   1463  1.3  riastrad 		if (ret != -ERESTARTSYS)
   1464  1.3  riastrad 			DRM_ERROR("Out of graphics memory for surface"
   1465  1.3  riastrad 				  " creation.\n");
   1466  1.3  riastrad 		goto out_unlock;
   1467  1.3  riastrad 	}
   1468  1.3  riastrad 
   1469  1.3  riastrad 	user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL);
   1470  1.3  riastrad 	if (unlikely(!user_srf)) {
   1471  1.3  riastrad 		ret = -ENOMEM;
   1472  1.3  riastrad 		goto out_no_user_srf;
   1473  1.3  riastrad 	}
   1474  1.3  riastrad 
   1475  1.3  riastrad 	*srf_out  = &user_srf->srf;
   1476  1.3  riastrad 	user_srf->size = user_accounting_size;
   1477  1.3  riastrad 	user_srf->prime.base.shareable = false;
   1478  1.3  riastrad 	user_srf->prime.base.tfile     = NULL;
   1479  1.3  riastrad 
   1480  1.3  riastrad 	srf = &user_srf->srf;
   1481  1.3  riastrad 	srf->flags             = svga3d_flags;
   1482  1.3  riastrad 	srf->format            = format;
   1483  1.3  riastrad 	srf->scanout           = for_scanout;
   1484  1.3  riastrad 	srf->mip_levels[0]     = num_mip_levels;
   1485  1.3  riastrad 	srf->num_sizes         = 1;
   1486  1.3  riastrad 	srf->sizes             = NULL;
   1487  1.3  riastrad 	srf->offsets           = NULL;
   1488  1.3  riastrad 	srf->base_size         = size;
   1489  1.3  riastrad 	srf->autogen_filter    = SVGA3D_TEX_FILTER_NONE;
   1490  1.3  riastrad 	srf->array_size        = array_size;
   1491  1.3  riastrad 	srf->multisample_count = multisample_count;
   1492  1.3  riastrad 	srf->multisample_pattern = multisample_pattern;
   1493  1.3  riastrad 	srf->quality_level = quality_level;
   1494  1.3  riastrad 
   1495  1.3  riastrad 	if (array_size)
   1496  1.3  riastrad 		num_layers = array_size;
   1497  1.3  riastrad 	else if (svga3d_flags & SVGA3D_SURFACE_CUBEMAP)
   1498  1.3  riastrad 		num_layers = SVGA3D_MAX_SURFACE_FACES;
   1499  1.3  riastrad 
   1500  1.3  riastrad 	if (srf->flags & SVGA3D_SURFACE_MULTISAMPLE)
   1501  1.3  riastrad 		sample_count = srf->multisample_count;
   1502  1.3  riastrad 
   1503  1.3  riastrad 	srf->res.backup_size   =
   1504  1.3  riastrad 		svga3dsurface_get_serialized_size_extended(srf->format,
   1505  1.3  riastrad 							   srf->base_size,
   1506  1.3  riastrad 							   srf->mip_levels[0],
   1507  1.3  riastrad 							   num_layers,
   1508  1.3  riastrad 							   sample_count);
   1509  1.3  riastrad 
   1510  1.3  riastrad 	if (srf->flags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT)
   1511  1.3  riastrad 		srf->res.backup_size += sizeof(SVGA3dDXSOState);
   1512  1.3  riastrad 
   1513  1.3  riastrad 	/*
   1514  1.3  riastrad 	 * Don't set SVGA3D_SURFACE_SCREENTARGET flag for a scanout surface with
   1515  1.3  riastrad 	 * size greater than STDU max width/height. This is really a workaround
   1516  1.3  riastrad 	 * to support creation of big framebuffer requested by some user-space
   1517  1.3  riastrad 	 * for whole topology. That big framebuffer won't really be used for
   1518  1.3  riastrad 	 * binding with screen target as during prepare_fb a separate surface is
   1519  1.3  riastrad 	 * created so it's safe to ignore SVGA3D_SURFACE_SCREENTARGET flag.
   1520  1.3  riastrad 	 */
   1521  1.3  riastrad 	if (dev_priv->active_display_unit == vmw_du_screen_target &&
   1522  1.3  riastrad 	    for_scanout && size.width <= dev_priv->stdu_max_width &&
   1523  1.3  riastrad 	    size.height <= dev_priv->stdu_max_height)
   1524  1.3  riastrad 		srf->flags |= SVGA3D_SURFACE_SCREENTARGET;
   1525  1.3  riastrad 
   1526  1.3  riastrad 	/*
   1527  1.3  riastrad 	 * From this point, the generic resource management functions
   1528  1.3  riastrad 	 * destroy the object on failure.
   1529  1.3  riastrad 	 */
   1530  1.3  riastrad 	ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free);
   1531  1.3  riastrad 
   1532  1.3  riastrad 	ttm_read_unlock(&dev_priv->reservation_sem);
   1533  1.3  riastrad 	return ret;
   1534  1.3  riastrad 
   1535  1.3  riastrad out_no_user_srf:
   1536  1.3  riastrad 	ttm_mem_global_free(vmw_mem_glob(dev_priv), user_accounting_size);
   1537  1.3  riastrad 
   1538  1.3  riastrad out_unlock:
   1539  1.3  riastrad 	ttm_read_unlock(&dev_priv->reservation_sem);
   1540  1.3  riastrad 	return ret;
   1541  1.3  riastrad }
   1542  1.3  riastrad 
   1543  1.3  riastrad /**
   1544  1.3  riastrad  * vmw_gb_surface_define_ext_ioctl - Ioctl function implementing
   1545  1.3  riastrad  * the user surface define functionality.
   1546  1.3  riastrad  *
   1547  1.3  riastrad  * @dev: Pointer to a struct drm_device.
   1548  1.3  riastrad  * @data: Pointer to data copied from / to user-space.
   1549  1.3  riastrad  * @file_priv: Pointer to a drm file private structure.
   1550  1.3  riastrad  */
   1551  1.3  riastrad int vmw_gb_surface_define_ext_ioctl(struct drm_device *dev, void *data,
   1552  1.3  riastrad 				struct drm_file *file_priv)
   1553  1.3  riastrad {
   1554  1.3  riastrad 	union drm_vmw_gb_surface_create_ext_arg *arg =
   1555  1.3  riastrad 	    (union drm_vmw_gb_surface_create_ext_arg *)data;
   1556  1.3  riastrad 	struct drm_vmw_gb_surface_create_ext_req *req = &arg->req;
   1557  1.3  riastrad 	struct drm_vmw_gb_surface_create_rep *rep = &arg->rep;
   1558  1.3  riastrad 
   1559  1.3  riastrad 	return vmw_gb_surface_define_internal(dev, req, rep, file_priv);
   1560  1.3  riastrad }
   1561  1.3  riastrad 
   1562  1.3  riastrad /**
   1563  1.3  riastrad  * vmw_gb_surface_reference_ext_ioctl - Ioctl function implementing
   1564  1.3  riastrad  * the user surface reference functionality.
   1565  1.3  riastrad  *
   1566  1.3  riastrad  * @dev: Pointer to a struct drm_device.
   1567  1.3  riastrad  * @data: Pointer to data copied from / to user-space.
   1568  1.3  riastrad  * @file_priv: Pointer to a drm file private structure.
   1569  1.3  riastrad  */
   1570  1.3  riastrad int vmw_gb_surface_reference_ext_ioctl(struct drm_device *dev, void *data,
   1571  1.3  riastrad 				   struct drm_file *file_priv)
   1572  1.3  riastrad {
   1573  1.3  riastrad 	union drm_vmw_gb_surface_reference_ext_arg *arg =
   1574  1.3  riastrad 	    (union drm_vmw_gb_surface_reference_ext_arg *)data;
   1575  1.3  riastrad 	struct drm_vmw_surface_arg *req = &arg->req;
   1576  1.3  riastrad 	struct drm_vmw_gb_surface_ref_ext_rep *rep = &arg->rep;
   1577  1.3  riastrad 
   1578  1.3  riastrad 	return vmw_gb_surface_reference_internal(dev, req, rep, file_priv);
   1579  1.3  riastrad }
   1580  1.3  riastrad 
   1581  1.3  riastrad /**
   1582  1.3  riastrad  * vmw_gb_surface_define_internal - Ioctl function implementing
   1583  1.3  riastrad  * the user surface define functionality.
   1584  1.3  riastrad  *
   1585  1.3  riastrad  * @dev: Pointer to a struct drm_device.
   1586  1.3  riastrad  * @req: Request argument from user-space.
   1587  1.3  riastrad  * @rep: Response argument to user-space.
   1588  1.3  riastrad  * @file_priv: Pointer to a drm file private structure.
   1589  1.3  riastrad  */
   1590  1.3  riastrad static int
   1591  1.3  riastrad vmw_gb_surface_define_internal(struct drm_device *dev,
   1592  1.3  riastrad 			       struct drm_vmw_gb_surface_create_ext_req *req,
   1593  1.3  riastrad 			       struct drm_vmw_gb_surface_create_rep *rep,
   1594  1.3  riastrad 			       struct drm_file *file_priv)
   1595  1.3  riastrad {
   1596  1.2  riastrad 	struct vmw_private *dev_priv = vmw_priv(dev);
   1597  1.2  riastrad 	struct vmw_user_surface *user_srf;
   1598  1.2  riastrad 	struct vmw_surface *srf;
   1599  1.2  riastrad 	struct vmw_resource *res;
   1600  1.2  riastrad 	struct vmw_resource *tmp;
   1601  1.2  riastrad 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
   1602  1.2  riastrad 	int ret;
   1603  1.2  riastrad 	uint32_t size;
   1604  1.2  riastrad 	uint32_t backup_handle = 0;
   1605  1.3  riastrad 	SVGA3dSurfaceAllFlags svga3d_flags_64 =
   1606  1.3  riastrad 		SVGA3D_FLAGS_64(req->svga3d_flags_upper_32_bits,
   1607  1.3  riastrad 				req->base.svga3d_flags);
   1608  1.3  riastrad 
   1609  1.3  riastrad 	if (!dev_priv->has_sm4_1) {
   1610  1.3  riastrad 		/*
   1611  1.3  riastrad 		 * If SM4_1 is not support then cannot send 64-bit flag to
   1612  1.3  riastrad 		 * device.
   1613  1.3  riastrad 		 */
   1614  1.3  riastrad 		if (req->svga3d_flags_upper_32_bits != 0)
   1615  1.3  riastrad 			return -EINVAL;
   1616  1.3  riastrad 
   1617  1.3  riastrad 		if (req->base.multisample_count != 0)
   1618  1.3  riastrad 			return -EINVAL;
   1619  1.3  riastrad 
   1620  1.3  riastrad 		if (req->multisample_pattern != SVGA3D_MS_PATTERN_NONE)
   1621  1.3  riastrad 			return -EINVAL;
   1622  1.2  riastrad 
   1623  1.3  riastrad 		if (req->quality_level != SVGA3D_MS_QUALITY_NONE)
   1624  1.3  riastrad 			return -EINVAL;
   1625  1.3  riastrad 	}
   1626  1.3  riastrad 
   1627  1.3  riastrad 	if ((svga3d_flags_64 & SVGA3D_SURFACE_MULTISAMPLE) &&
   1628  1.3  riastrad 	    req->base.multisample_count == 0)
   1629  1.2  riastrad 		return -EINVAL;
   1630  1.2  riastrad 
   1631  1.3  riastrad 	if (req->base.mip_levels > DRM_VMW_MAX_MIP_LEVELS)
   1632  1.2  riastrad 		return -EINVAL;
   1633  1.2  riastrad 
   1634  1.2  riastrad 	if (unlikely(vmw_user_surface_size == 0))
   1635  1.2  riastrad 		vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
   1636  1.3  riastrad 			VMW_IDA_ACC_SIZE + TTM_OBJ_EXTRA_SIZE;
   1637  1.2  riastrad 
   1638  1.3  riastrad 	size = vmw_user_surface_size;
   1639  1.2  riastrad 
   1640  1.2  riastrad 	/* Define a surface based on the parameters. */
   1641  1.2  riastrad 	ret = vmw_surface_gb_priv_define(dev,
   1642  1.3  riastrad 					 size,
   1643  1.3  riastrad 					 svga3d_flags_64,
   1644  1.3  riastrad 					 req->base.format,
   1645  1.3  riastrad 					 req->base.drm_surface_flags &
   1646  1.3  riastrad 					 drm_vmw_surface_flag_scanout,
   1647  1.3  riastrad 					 req->base.mip_levels,
   1648  1.3  riastrad 					 req->base.multisample_count,
   1649  1.3  riastrad 					 req->base.array_size,
   1650  1.3  riastrad 					 req->base.base_size,
   1651  1.3  riastrad 					 req->multisample_pattern,
   1652  1.3  riastrad 					 req->quality_level,
   1653  1.3  riastrad 					 &srf);
   1654  1.2  riastrad 	if (unlikely(ret != 0))
   1655  1.2  riastrad 		return ret;
   1656  1.2  riastrad 
   1657  1.2  riastrad 	user_srf = container_of(srf, struct vmw_user_surface, srf);
   1658  1.2  riastrad 	if (drm_is_primary_client(file_priv))
   1659  1.2  riastrad 		user_srf->master = drm_master_get(file_priv->master);
   1660  1.2  riastrad 
   1661  1.2  riastrad 	ret = ttm_read_lock(&dev_priv->reservation_sem, true);
   1662  1.2  riastrad 	if (unlikely(ret != 0))
   1663  1.2  riastrad 		return ret;
   1664  1.2  riastrad 
   1665  1.2  riastrad 	res = &user_srf->srf.res;
   1666  1.2  riastrad 
   1667  1.3  riastrad 	if (req->base.buffer_handle != SVGA3D_INVALID_ID) {
   1668  1.3  riastrad 		ret = vmw_user_bo_lookup(tfile, req->base.buffer_handle,
   1669  1.3  riastrad 					 &res->backup,
   1670  1.3  riastrad 					 &user_srf->backup_base);
   1671  1.2  riastrad 		if (ret == 0) {
   1672  1.2  riastrad 			if (res->backup->base.num_pages * PAGE_SIZE <
   1673  1.2  riastrad 			    res->backup_size) {
   1674  1.3  riastrad 				VMW_DEBUG_USER("Surface backup buffer too small.\n");
   1675  1.3  riastrad 				vmw_bo_unreference(&res->backup);
   1676  1.2  riastrad 				ret = -EINVAL;
   1677  1.2  riastrad 				goto out_unlock;
   1678  1.2  riastrad 			} else {
   1679  1.3  riastrad 				backup_handle = req->base.buffer_handle;
   1680  1.2  riastrad 			}
   1681  1.2  riastrad 		}
   1682  1.3  riastrad 	} else if (req->base.drm_surface_flags &
   1683  1.3  riastrad 		   (drm_vmw_surface_flag_create_buffer |
   1684  1.3  riastrad 		    drm_vmw_surface_flag_coherent))
   1685  1.3  riastrad 		ret = vmw_user_bo_alloc(dev_priv, tfile,
   1686  1.3  riastrad 					res->backup_size,
   1687  1.3  riastrad 					req->base.drm_surface_flags &
   1688  1.3  riastrad 					drm_vmw_surface_flag_shareable,
   1689  1.3  riastrad 					&backup_handle,
   1690  1.3  riastrad 					&res->backup,
   1691  1.3  riastrad 					&user_srf->backup_base);
   1692  1.2  riastrad 
   1693  1.2  riastrad 	if (unlikely(ret != 0)) {
   1694  1.2  riastrad 		vmw_resource_unreference(&res);
   1695  1.2  riastrad 		goto out_unlock;
   1696  1.2  riastrad 	}
   1697  1.2  riastrad 
   1698  1.3  riastrad 	if (req->base.drm_surface_flags & drm_vmw_surface_flag_coherent) {
   1699  1.3  riastrad 		struct vmw_buffer_object *backup = res->backup;
   1700  1.3  riastrad 
   1701  1.3  riastrad 		ttm_bo_reserve(&backup->base, false, false, NULL);
   1702  1.3  riastrad 		if (!res->func->dirty_alloc)
   1703  1.3  riastrad 			ret = -EINVAL;
   1704  1.3  riastrad 		if (!ret)
   1705  1.3  riastrad 			ret = vmw_bo_dirty_add(backup);
   1706  1.3  riastrad 		if (!ret) {
   1707  1.3  riastrad 			res->coherent = true;
   1708  1.3  riastrad 			ret = res->func->dirty_alloc(res);
   1709  1.3  riastrad 		}
   1710  1.3  riastrad 		ttm_bo_unreserve(&backup->base);
   1711  1.3  riastrad 		if (ret) {
   1712  1.3  riastrad 			vmw_resource_unreference(&res);
   1713  1.3  riastrad 			goto out_unlock;
   1714  1.3  riastrad 		}
   1715  1.3  riastrad 
   1716  1.3  riastrad 	}
   1717  1.3  riastrad 
   1718  1.2  riastrad 	tmp = vmw_resource_reference(res);
   1719  1.2  riastrad 	ret = ttm_prime_object_init(tfile, res->backup_size, &user_srf->prime,
   1720  1.3  riastrad 				    req->base.drm_surface_flags &
   1721  1.2  riastrad 				    drm_vmw_surface_flag_shareable,
   1722  1.2  riastrad 				    VMW_RES_SURFACE,
   1723  1.2  riastrad 				    &vmw_user_surface_base_release, NULL);
   1724  1.2  riastrad 
   1725  1.2  riastrad 	if (unlikely(ret != 0)) {
   1726  1.2  riastrad 		vmw_resource_unreference(&tmp);
   1727  1.2  riastrad 		vmw_resource_unreference(&res);
   1728  1.2  riastrad 		goto out_unlock;
   1729  1.2  riastrad 	}
   1730  1.2  riastrad 
   1731  1.3  riastrad 	rep->handle      = user_srf->prime.base.handle;
   1732  1.2  riastrad 	rep->backup_size = res->backup_size;
   1733  1.2  riastrad 	if (res->backup) {
   1734  1.2  riastrad 		rep->buffer_map_handle =
   1735  1.3  riastrad 			drm_vma_node_offset_addr(&res->backup->base.base.vma_node);
   1736  1.2  riastrad 		rep->buffer_size = res->backup->base.num_pages * PAGE_SIZE;
   1737  1.2  riastrad 		rep->buffer_handle = backup_handle;
   1738  1.2  riastrad 	} else {
   1739  1.2  riastrad 		rep->buffer_map_handle = 0;
   1740  1.2  riastrad 		rep->buffer_size = 0;
   1741  1.2  riastrad 		rep->buffer_handle = SVGA3D_INVALID_ID;
   1742  1.2  riastrad 	}
   1743  1.2  riastrad 
   1744  1.2  riastrad 	vmw_resource_unreference(&res);
   1745  1.2  riastrad 
   1746  1.2  riastrad out_unlock:
   1747  1.2  riastrad 	ttm_read_unlock(&dev_priv->reservation_sem);
   1748  1.2  riastrad 	return ret;
   1749  1.2  riastrad }
   1750  1.2  riastrad 
   1751  1.2  riastrad /**
   1752  1.3  riastrad  * vmw_gb_surface_reference_internal - Ioctl function implementing
   1753  1.3  riastrad  * the user surface reference functionality.
   1754  1.2  riastrad  *
   1755  1.3  riastrad  * @dev: Pointer to a struct drm_device.
   1756  1.3  riastrad  * @req: Pointer to user-space request surface arg.
   1757  1.3  riastrad  * @rep: Pointer to response to user-space.
   1758  1.3  riastrad  * @file_priv: Pointer to a drm file private structure.
   1759  1.2  riastrad  */
   1760  1.3  riastrad static int
   1761  1.3  riastrad vmw_gb_surface_reference_internal(struct drm_device *dev,
   1762  1.3  riastrad 				  struct drm_vmw_surface_arg *req,
   1763  1.3  riastrad 				  struct drm_vmw_gb_surface_ref_ext_rep *rep,
   1764  1.3  riastrad 				  struct drm_file *file_priv)
   1765  1.2  riastrad {
   1766  1.2  riastrad 	struct vmw_private *dev_priv = vmw_priv(dev);
   1767  1.2  riastrad 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
   1768  1.2  riastrad 	struct vmw_surface *srf;
   1769  1.2  riastrad 	struct vmw_user_surface *user_srf;
   1770  1.2  riastrad 	struct ttm_base_object *base;
   1771  1.2  riastrad 	uint32_t backup_handle;
   1772  1.2  riastrad 	int ret = -EINVAL;
   1773  1.2  riastrad 
   1774  1.2  riastrad 	ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid,
   1775  1.2  riastrad 					   req->handle_type, &base);
   1776  1.2  riastrad 	if (unlikely(ret != 0))
   1777  1.2  riastrad 		return ret;
   1778  1.2  riastrad 
   1779  1.2  riastrad 	user_srf = container_of(base, struct vmw_user_surface, prime.base);
   1780  1.2  riastrad 	srf = &user_srf->srf;
   1781  1.3  riastrad 	if (!srf->res.backup) {
   1782  1.2  riastrad 		DRM_ERROR("Shared GB surface is missing a backup buffer.\n");
   1783  1.2  riastrad 		goto out_bad_resource;
   1784  1.2  riastrad 	}
   1785  1.2  riastrad 
   1786  1.2  riastrad 	mutex_lock(&dev_priv->cmdbuf_mutex); /* Protect res->backup */
   1787  1.3  riastrad 	ret = vmw_user_bo_reference(tfile, srf->res.backup, &backup_handle);
   1788  1.2  riastrad 	mutex_unlock(&dev_priv->cmdbuf_mutex);
   1789  1.2  riastrad 
   1790  1.2  riastrad 	if (unlikely(ret != 0)) {
   1791  1.2  riastrad 		DRM_ERROR("Could not add a reference to a GB surface "
   1792  1.2  riastrad 			  "backup buffer.\n");
   1793  1.3  riastrad 		(void) ttm_ref_object_base_unref(tfile, base->handle,
   1794  1.2  riastrad 						 TTM_REF_USAGE);
   1795  1.2  riastrad 		goto out_bad_resource;
   1796  1.2  riastrad 	}
   1797  1.2  riastrad 
   1798  1.3  riastrad 	rep->creq.base.svga3d_flags = SVGA3D_FLAGS_LOWER_32(srf->flags);
   1799  1.3  riastrad 	rep->creq.base.format = srf->format;
   1800  1.3  riastrad 	rep->creq.base.mip_levels = srf->mip_levels[0];
   1801  1.3  riastrad 	rep->creq.base.drm_surface_flags = 0;
   1802  1.3  riastrad 	rep->creq.base.multisample_count = srf->multisample_count;
   1803  1.3  riastrad 	rep->creq.base.autogen_filter = srf->autogen_filter;
   1804  1.3  riastrad 	rep->creq.base.array_size = srf->array_size;
   1805  1.3  riastrad 	rep->creq.base.buffer_handle = backup_handle;
   1806  1.3  riastrad 	rep->creq.base.base_size = srf->base_size;
   1807  1.3  riastrad 	rep->crep.handle = user_srf->prime.base.handle;
   1808  1.2  riastrad 	rep->crep.backup_size = srf->res.backup_size;
   1809  1.2  riastrad 	rep->crep.buffer_handle = backup_handle;
   1810  1.2  riastrad 	rep->crep.buffer_map_handle =
   1811  1.3  riastrad 		drm_vma_node_offset_addr(&srf->res.backup->base.base.vma_node);
   1812  1.2  riastrad 	rep->crep.buffer_size = srf->res.backup->base.num_pages * PAGE_SIZE;
   1813  1.2  riastrad 
   1814  1.3  riastrad 	rep->creq.version = drm_vmw_gb_surface_v1;
   1815  1.3  riastrad 	rep->creq.svga3d_flags_upper_32_bits =
   1816  1.3  riastrad 		SVGA3D_FLAGS_UPPER_32(srf->flags);
   1817  1.3  riastrad 	rep->creq.multisample_pattern = srf->multisample_pattern;
   1818  1.3  riastrad 	rep->creq.quality_level = srf->quality_level;
   1819  1.3  riastrad 	rep->creq.must_be_zero = 0;
   1820  1.3  riastrad 
   1821  1.1  riastrad out_bad_resource:
   1822  1.1  riastrad 	ttm_base_object_unref(&base);
   1823  1.1  riastrad 
   1824  1.1  riastrad 	return ret;
   1825  1.1  riastrad }
   1826  1.2  riastrad 
   1827  1.2  riastrad /**
   1828  1.3  riastrad  * vmw_subres_dirty_add - Add a dirty region to a subresource
   1829  1.3  riastrad  * @dirty: The surfaces's dirty tracker.
   1830  1.3  riastrad  * @loc_start: The location corresponding to the start of the region.
   1831  1.3  riastrad  * @loc_end: The location corresponding to the end of the region.
   1832  1.3  riastrad  *
   1833  1.3  riastrad  * As we are assuming that @loc_start and @loc_end represent a sequential
   1834  1.3  riastrad  * range of backing store memory, if the region spans multiple lines then
   1835  1.3  riastrad  * regardless of the x coordinate, the full lines are dirtied.
   1836  1.3  riastrad  * Correspondingly if the region spans multiple z slices, then full rather
   1837  1.3  riastrad  * than partial z slices are dirtied.
   1838  1.3  riastrad  */
   1839  1.3  riastrad static void vmw_subres_dirty_add(struct vmw_surface_dirty *dirty,
   1840  1.3  riastrad 				 const struct svga3dsurface_loc *loc_start,
   1841  1.3  riastrad 				 const struct svga3dsurface_loc *loc_end)
   1842  1.3  riastrad {
   1843  1.3  riastrad 	const struct svga3dsurface_cache *cache = &dirty->cache;
   1844  1.3  riastrad 	SVGA3dBox *box = &dirty->boxes[loc_start->sub_resource];
   1845  1.3  riastrad 	u32 mip = loc_start->sub_resource % cache->num_mip_levels;
   1846  1.3  riastrad 	const struct drm_vmw_size *size = &cache->mip[mip].size;
   1847  1.3  riastrad 	u32 box_c2 = box->z + box->d;
   1848  1.3  riastrad 
   1849  1.3  riastrad 	if (WARN_ON(loc_start->sub_resource >= dirty->num_subres))
   1850  1.3  riastrad 		return;
   1851  1.3  riastrad 
   1852  1.3  riastrad 	if (box->d == 0 || box->z > loc_start->z)
   1853  1.3  riastrad 		box->z = loc_start->z;
   1854  1.3  riastrad 	if (box_c2 < loc_end->z)
   1855  1.3  riastrad 		box->d = loc_end->z - box->z;
   1856  1.3  riastrad 
   1857  1.3  riastrad 	if (loc_start->z + 1 == loc_end->z) {
   1858  1.3  riastrad 		box_c2 = box->y + box->h;
   1859  1.3  riastrad 		if (box->h == 0 || box->y > loc_start->y)
   1860  1.3  riastrad 			box->y = loc_start->y;
   1861  1.3  riastrad 		if (box_c2 < loc_end->y)
   1862  1.3  riastrad 			box->h = loc_end->y - box->y;
   1863  1.3  riastrad 
   1864  1.3  riastrad 		if (loc_start->y + 1 == loc_end->y) {
   1865  1.3  riastrad 			box_c2 = box->x + box->w;
   1866  1.3  riastrad 			if (box->w == 0 || box->x > loc_start->x)
   1867  1.3  riastrad 				box->x = loc_start->x;
   1868  1.3  riastrad 			if (box_c2 < loc_end->x)
   1869  1.3  riastrad 				box->w = loc_end->x - box->x;
   1870  1.3  riastrad 		} else {
   1871  1.3  riastrad 			box->x = 0;
   1872  1.3  riastrad 			box->w = size->width;
   1873  1.3  riastrad 		}
   1874  1.3  riastrad 	} else {
   1875  1.3  riastrad 		box->y = 0;
   1876  1.3  riastrad 		box->h = size->height;
   1877  1.3  riastrad 		box->x = 0;
   1878  1.3  riastrad 		box->w = size->width;
   1879  1.3  riastrad 	}
   1880  1.3  riastrad }
   1881  1.3  riastrad 
   1882  1.3  riastrad /**
   1883  1.3  riastrad  * vmw_subres_dirty_full - Mark a full subresource as dirty
   1884  1.3  riastrad  * @dirty: The surface's dirty tracker.
   1885  1.3  riastrad  * @subres: The subresource
   1886  1.3  riastrad  */
   1887  1.3  riastrad static void vmw_subres_dirty_full(struct vmw_surface_dirty *dirty, u32 subres)
   1888  1.3  riastrad {
   1889  1.3  riastrad 	const struct svga3dsurface_cache *cache = &dirty->cache;
   1890  1.3  riastrad 	u32 mip = subres % cache->num_mip_levels;
   1891  1.3  riastrad 	const struct drm_vmw_size *size = &cache->mip[mip].size;
   1892  1.3  riastrad 	SVGA3dBox *box = &dirty->boxes[subres];
   1893  1.3  riastrad 
   1894  1.3  riastrad 	box->x = 0;
   1895  1.3  riastrad 	box->y = 0;
   1896  1.3  riastrad 	box->z = 0;
   1897  1.3  riastrad 	box->w = size->width;
   1898  1.3  riastrad 	box->h = size->height;
   1899  1.3  riastrad 	box->d = size->depth;
   1900  1.3  riastrad }
   1901  1.3  riastrad 
   1902  1.3  riastrad /*
   1903  1.3  riastrad  * vmw_surface_tex_dirty_add_range - The dirty_add_range callback for texture
   1904  1.3  riastrad  * surfaces.
   1905  1.2  riastrad  */
   1906  1.3  riastrad static void vmw_surface_tex_dirty_range_add(struct vmw_resource *res,
   1907  1.3  riastrad 					    size_t start, size_t end)
   1908  1.2  riastrad {
   1909  1.3  riastrad 	struct vmw_surface_dirty *dirty =
   1910  1.3  riastrad 		(struct vmw_surface_dirty *) res->dirty;
   1911  1.3  riastrad 	size_t backup_end = res->backup_offset + res->backup_size;
   1912  1.3  riastrad 	struct svga3dsurface_loc loc1, loc2;
   1913  1.3  riastrad 	const struct svga3dsurface_cache *cache;
   1914  1.2  riastrad 
   1915  1.3  riastrad 	start = max_t(size_t, start, res->backup_offset) - res->backup_offset;
   1916  1.3  riastrad 	end = min(end, backup_end) - res->backup_offset;
   1917  1.3  riastrad 	cache = &dirty->cache;
   1918  1.3  riastrad 	svga3dsurface_get_loc(cache, &loc1, start);
   1919  1.3  riastrad 	svga3dsurface_get_loc(cache, &loc2, end - 1);
   1920  1.3  riastrad 	svga3dsurface_inc_loc(cache, &loc2);
   1921  1.2  riastrad 
   1922  1.3  riastrad 	if (loc1.sub_resource + 1 == loc2.sub_resource) {
   1923  1.3  riastrad 		/* Dirty range covers a single sub-resource */
   1924  1.3  riastrad 		vmw_subres_dirty_add(dirty, &loc1, &loc2);
   1925  1.2  riastrad 	} else {
   1926  1.3  riastrad 		/* Dirty range covers multiple sub-resources */
   1927  1.3  riastrad 		struct svga3dsurface_loc loc_min, loc_max;
   1928  1.3  riastrad 		u32 sub_res;
   1929  1.3  riastrad 
   1930  1.3  riastrad 		svga3dsurface_max_loc(cache, loc1.sub_resource, &loc_max);
   1931  1.3  riastrad 		vmw_subres_dirty_add(dirty, &loc1, &loc_max);
   1932  1.3  riastrad 		svga3dsurface_min_loc(cache, loc2.sub_resource - 1, &loc_min);
   1933  1.3  riastrad 		vmw_subres_dirty_add(dirty, &loc_min, &loc2);
   1934  1.3  riastrad 		for (sub_res = loc1.sub_resource + 1;
   1935  1.3  riastrad 		     sub_res < loc2.sub_resource - 1; ++sub_res)
   1936  1.3  riastrad 			vmw_subres_dirty_full(dirty, sub_res);
   1937  1.3  riastrad 	}
   1938  1.3  riastrad }
   1939  1.3  riastrad 
   1940  1.3  riastrad /*
   1941  1.3  riastrad  * vmw_surface_tex_dirty_add_range - The dirty_add_range callback for buffer
   1942  1.3  riastrad  * surfaces.
   1943  1.3  riastrad  */
   1944  1.3  riastrad static void vmw_surface_buf_dirty_range_add(struct vmw_resource *res,
   1945  1.3  riastrad 					    size_t start, size_t end)
   1946  1.3  riastrad {
   1947  1.3  riastrad 	struct vmw_surface_dirty *dirty =
   1948  1.3  riastrad 		(struct vmw_surface_dirty *) res->dirty;
   1949  1.3  riastrad 	const struct svga3dsurface_cache *cache = &dirty->cache;
   1950  1.3  riastrad 	size_t backup_end = res->backup_offset + cache->mip_chain_bytes;
   1951  1.3  riastrad 	SVGA3dBox *box = &dirty->boxes[0];
   1952  1.3  riastrad 	u32 box_c2;
   1953  1.3  riastrad 
   1954  1.3  riastrad 	box->h = box->d = 1;
   1955  1.3  riastrad 	start = max_t(size_t, start, res->backup_offset) - res->backup_offset;
   1956  1.3  riastrad 	end = min(end, backup_end) - res->backup_offset;
   1957  1.3  riastrad 	box_c2 = box->x + box->w;
   1958  1.3  riastrad 	if (box->w == 0 || box->x > start)
   1959  1.3  riastrad 		box->x = start;
   1960  1.3  riastrad 	if (box_c2 < end)
   1961  1.3  riastrad 		box->w = end - box->x;
   1962  1.3  riastrad }
   1963  1.3  riastrad 
   1964  1.3  riastrad /*
   1965  1.3  riastrad  * vmw_surface_tex_dirty_add_range - The dirty_add_range callback for surfaces
   1966  1.3  riastrad  */
   1967  1.3  riastrad static void vmw_surface_dirty_range_add(struct vmw_resource *res, size_t start,
   1968  1.3  riastrad 					size_t end)
   1969  1.3  riastrad {
   1970  1.3  riastrad 	struct vmw_surface *srf = vmw_res_to_srf(res);
   1971  1.3  riastrad 
   1972  1.3  riastrad 	if (WARN_ON(end <= res->backup_offset ||
   1973  1.3  riastrad 		    start >= res->backup_offset + res->backup_size))
   1974  1.3  riastrad 		return;
   1975  1.3  riastrad 
   1976  1.3  riastrad 	if (srf->format == SVGA3D_BUFFER)
   1977  1.3  riastrad 		vmw_surface_buf_dirty_range_add(res, start, end);
   1978  1.3  riastrad 	else
   1979  1.3  riastrad 		vmw_surface_tex_dirty_range_add(res, start, end);
   1980  1.3  riastrad }
   1981  1.3  riastrad 
   1982  1.3  riastrad /*
   1983  1.3  riastrad  * vmw_surface_dirty_sync - The surface's dirty_sync callback.
   1984  1.3  riastrad  */
   1985  1.3  riastrad static int vmw_surface_dirty_sync(struct vmw_resource *res)
   1986  1.3  riastrad {
   1987  1.3  riastrad 	struct vmw_private *dev_priv = res->dev_priv;
   1988  1.3  riastrad 	bool has_dx = 0;
   1989  1.3  riastrad 	u32 i, num_dirty;
   1990  1.3  riastrad 	struct vmw_surface_dirty *dirty =
   1991  1.3  riastrad 		(struct vmw_surface_dirty *) res->dirty;
   1992  1.3  riastrad 	size_t alloc_size;
   1993  1.3  riastrad 	const struct svga3dsurface_cache *cache = &dirty->cache;
   1994  1.3  riastrad 	struct {
   1995  1.3  riastrad 		SVGA3dCmdHeader header;
   1996  1.3  riastrad 		SVGA3dCmdDXUpdateSubResource body;
   1997  1.3  riastrad 	} *cmd1;
   1998  1.3  riastrad 	struct {
   1999  1.3  riastrad 		SVGA3dCmdHeader header;
   2000  1.3  riastrad 		SVGA3dCmdUpdateGBImage body;
   2001  1.3  riastrad 	} *cmd2;
   2002  1.3  riastrad 	void *cmd;
   2003  1.3  riastrad 
   2004  1.3  riastrad 	num_dirty = 0;
   2005  1.3  riastrad 	for (i = 0; i < dirty->num_subres; ++i) {
   2006  1.3  riastrad 		const SVGA3dBox *box = &dirty->boxes[i];
   2007  1.3  riastrad 
   2008  1.3  riastrad 		if (box->d)
   2009  1.3  riastrad 			num_dirty++;
   2010  1.3  riastrad 	}
   2011  1.3  riastrad 
   2012  1.3  riastrad 	if (!num_dirty)
   2013  1.3  riastrad 		goto out;
   2014  1.3  riastrad 
   2015  1.3  riastrad 	alloc_size = num_dirty * ((has_dx) ? sizeof(*cmd1) : sizeof(*cmd2));
   2016  1.3  riastrad 	cmd = VMW_FIFO_RESERVE(dev_priv, alloc_size);
   2017  1.3  riastrad 	if (!cmd)
   2018  1.3  riastrad 		return -ENOMEM;
   2019  1.3  riastrad 
   2020  1.3  riastrad 	cmd1 = cmd;
   2021  1.3  riastrad 	cmd2 = cmd;
   2022  1.3  riastrad 
   2023  1.3  riastrad 	for (i = 0; i < dirty->num_subres; ++i) {
   2024  1.3  riastrad 		const SVGA3dBox *box = &dirty->boxes[i];
   2025  1.3  riastrad 
   2026  1.3  riastrad 		if (!box->d)
   2027  1.3  riastrad 			continue;
   2028  1.2  riastrad 
   2029  1.3  riastrad 		/*
   2030  1.3  riastrad 		 * DX_UPDATE_SUBRESOURCE is aware of array surfaces.
   2031  1.3  riastrad 		 * UPDATE_GB_IMAGE is not.
   2032  1.3  riastrad 		 */
   2033  1.3  riastrad 		if (has_dx) {
   2034  1.3  riastrad 			cmd1->header.id = SVGA_3D_CMD_DX_UPDATE_SUBRESOURCE;
   2035  1.3  riastrad 			cmd1->header.size = sizeof(cmd1->body);
   2036  1.3  riastrad 			cmd1->body.sid = res->id;
   2037  1.3  riastrad 			cmd1->body.subResource = i;
   2038  1.3  riastrad 			cmd1->body.box = *box;
   2039  1.3  riastrad 			cmd1++;
   2040  1.3  riastrad 		} else {
   2041  1.3  riastrad 			cmd2->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE;
   2042  1.3  riastrad 			cmd2->header.size = sizeof(cmd2->body);
   2043  1.3  riastrad 			cmd2->body.image.sid = res->id;
   2044  1.3  riastrad 			cmd2->body.image.face = i / cache->num_mip_levels;
   2045  1.3  riastrad 			cmd2->body.image.mipmap = i -
   2046  1.3  riastrad 				(cache->num_mip_levels * cmd2->body.image.face);
   2047  1.3  riastrad 			cmd2->body.box = *box;
   2048  1.3  riastrad 			cmd2++;
   2049  1.2  riastrad 		}
   2050  1.3  riastrad 
   2051  1.2  riastrad 	}
   2052  1.3  riastrad 	vmw_fifo_commit(dev_priv, alloc_size);
   2053  1.3  riastrad  out:
   2054  1.3  riastrad 	memset(&dirty->boxes[0], 0, sizeof(dirty->boxes[0]) *
   2055  1.3  riastrad 	       dirty->num_subres);
   2056  1.2  riastrad 
   2057  1.3  riastrad 	return 0;
   2058  1.3  riastrad }
   2059  1.3  riastrad 
   2060  1.3  riastrad /*
   2061  1.3  riastrad  * vmw_surface_dirty_alloc - The surface's dirty_alloc callback.
   2062  1.3  riastrad  */
   2063  1.3  riastrad static int vmw_surface_dirty_alloc(struct vmw_resource *res)
   2064  1.3  riastrad {
   2065  1.3  riastrad 	struct vmw_surface *srf = vmw_res_to_srf(res);
   2066  1.3  riastrad 	struct vmw_surface_dirty *dirty;
   2067  1.3  riastrad 	u32 num_layers = 1;
   2068  1.3  riastrad 	u32 num_mip;
   2069  1.3  riastrad 	u32 num_subres;
   2070  1.3  riastrad 	u32 num_samples;
   2071  1.3  riastrad 	size_t dirty_size, acc_size;
   2072  1.3  riastrad 	static struct ttm_operation_ctx ctx = {
   2073  1.3  riastrad 		.interruptible = false,
   2074  1.3  riastrad 		.no_wait_gpu = false
   2075  1.3  riastrad 	};
   2076  1.3  riastrad 	int ret;
   2077  1.2  riastrad 
   2078  1.3  riastrad 	if (srf->array_size)
   2079  1.3  riastrad 		num_layers = srf->array_size;
   2080  1.3  riastrad 	else if (srf->flags & SVGA3D_SURFACE_CUBEMAP)
   2081  1.3  riastrad 		num_layers *= SVGA3D_MAX_SURFACE_FACES;
   2082  1.3  riastrad 
   2083  1.3  riastrad 	num_mip = srf->mip_levels[0];
   2084  1.3  riastrad 	if (!num_mip)
   2085  1.3  riastrad 		num_mip = 1;
   2086  1.3  riastrad 
   2087  1.3  riastrad 	num_subres = num_layers * num_mip;
   2088  1.3  riastrad 	dirty_size = sizeof(*dirty) + num_subres * sizeof(dirty->boxes[0]);
   2089  1.3  riastrad 	acc_size = ttm_round_pot(dirty_size);
   2090  1.3  riastrad 	ret = ttm_mem_global_alloc(vmw_mem_glob(res->dev_priv),
   2091  1.3  riastrad 				   acc_size, &ctx);
   2092  1.3  riastrad 	if (ret) {
   2093  1.3  riastrad 		VMW_DEBUG_USER("Out of graphics memory for surface "
   2094  1.3  riastrad 			       "dirty tracker.\n");
   2095  1.2  riastrad 		return ret;
   2096  1.2  riastrad 	}
   2097  1.2  riastrad 
   2098  1.3  riastrad 	dirty = kvzalloc(dirty_size, GFP_KERNEL);
   2099  1.3  riastrad 	if (!dirty) {
   2100  1.2  riastrad 		ret = -ENOMEM;
   2101  1.3  riastrad 		goto out_no_dirty;
   2102  1.2  riastrad 	}
   2103  1.2  riastrad 
   2104  1.3  riastrad 	num_samples = max_t(u32, 1, srf->multisample_count);
   2105  1.3  riastrad 	ret = svga3dsurface_setup_cache(&srf->base_size, srf->format, num_mip,
   2106  1.3  riastrad 					num_layers, num_samples, &dirty->cache);
   2107  1.3  riastrad 	if (ret)
   2108  1.3  riastrad 		goto out_no_cache;
   2109  1.3  riastrad 
   2110  1.3  riastrad 	dirty->num_subres = num_subres;
   2111  1.3  riastrad 	dirty->size = acc_size;
   2112  1.3  riastrad 	res->dirty = (struct vmw_resource_dirty *) dirty;
   2113  1.2  riastrad 
   2114  1.3  riastrad 	return 0;
   2115  1.2  riastrad 
   2116  1.3  riastrad out_no_cache:
   2117  1.3  riastrad 	kvfree(dirty);
   2118  1.3  riastrad out_no_dirty:
   2119  1.3  riastrad 	ttm_mem_global_free(vmw_mem_glob(res->dev_priv), acc_size);
   2120  1.3  riastrad 	return ret;
   2121  1.3  riastrad }
   2122  1.2  riastrad 
   2123  1.3  riastrad /*
   2124  1.3  riastrad  * vmw_surface_dirty_free - The surface's dirty_free callback
   2125  1.3  riastrad  */
   2126  1.3  riastrad static void vmw_surface_dirty_free(struct vmw_resource *res)
   2127  1.3  riastrad {
   2128  1.3  riastrad 	struct vmw_surface_dirty *dirty =
   2129  1.3  riastrad 		(struct vmw_surface_dirty *) res->dirty;
   2130  1.3  riastrad 	size_t acc_size = dirty->size;
   2131  1.2  riastrad 
   2132  1.3  riastrad 	kvfree(dirty);
   2133  1.3  riastrad 	ttm_mem_global_free(vmw_mem_glob(res->dev_priv), acc_size);
   2134  1.3  riastrad 	res->dirty = NULL;
   2135  1.3  riastrad }
   2136  1.2  riastrad 
   2137  1.3  riastrad /*
   2138  1.3  riastrad  * vmw_surface_clean - The surface's clean callback
   2139  1.3  riastrad  */
   2140  1.3  riastrad static int vmw_surface_clean(struct vmw_resource *res)
   2141  1.3  riastrad {
   2142  1.3  riastrad 	struct vmw_private *dev_priv = res->dev_priv;
   2143  1.3  riastrad 	size_t alloc_size;
   2144  1.3  riastrad 	struct {
   2145  1.3  riastrad 		SVGA3dCmdHeader header;
   2146  1.3  riastrad 		SVGA3dCmdReadbackGBSurface body;
   2147  1.3  riastrad 	} *cmd;
   2148  1.2  riastrad 
   2149  1.3  riastrad 	alloc_size = sizeof(*cmd);
   2150  1.3  riastrad 	cmd = VMW_FIFO_RESERVE(dev_priv, alloc_size);
   2151  1.3  riastrad 	if (!cmd)
   2152  1.3  riastrad 		return -ENOMEM;
   2153  1.2  riastrad 
   2154  1.3  riastrad 	cmd->header.id = SVGA_3D_CMD_READBACK_GB_SURFACE;
   2155  1.3  riastrad 	cmd->header.size = sizeof(cmd->body);
   2156  1.3  riastrad 	cmd->body.sid = res->id;
   2157  1.3  riastrad 	vmw_fifo_commit(dev_priv, alloc_size);
   2158  1.2  riastrad 
   2159  1.3  riastrad 	return 0;
   2160  1.2  riastrad }
   2161