1 // SPDX-License-Identifier: GPL-2.0 OR MIT
2 /**************************************************************************
4 * Copyright 2009-2015 VMware, Inc., Palo Alto, CA., USA
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
28 #include <drm/ttm/ttm_placement.h>
30 #include "vmwgfx_drv.h"
31 #include "vmwgfx_resource_priv.h"
32 #include "vmwgfx_so.h"
33 #include "vmwgfx_binding.h"
34 #include "device_include/svga3d_surfacedefs.h"
36 #define SVGA3D_FLAGS_64(upper32, lower32) (((uint64_t)upper32 << 32) | lower32)
37 #define SVGA3D_FLAGS_UPPER_32(svga3d_flags) (svga3d_flags >> 32)
38 #define SVGA3D_FLAGS_LOWER_32(svga3d_flags) \
39 (svga3d_flags & ((uint64_t)U32_MAX))
42 * struct vmw_user_surface - User-space visible surface resource
44 * @base: The TTM base object handling user-space visibility.
45 * @srf: The surface metadata.
46 * @size: TTM accounting size for the surface.
47 * @master: master of the creating client. Used for security check.
49 struct vmw_user_surface {
50 struct ttm_prime_object prime;
51 struct vmw_surface srf;
53 struct drm_master *master;
54 struct ttm_base_object *backup_base;
58 * struct vmw_surface_offset - Backing store mip level offset info
60 * @face: Surface face.
62 * @bo_offset: Offset into backing store of this mip level.
65 struct vmw_surface_offset {
71 static void vmw_user_surface_free(struct vmw_resource *res);
72 static struct vmw_resource *
73 vmw_user_surface_base_to_res(struct ttm_base_object *base);
74 static int vmw_legacy_srf_bind(struct vmw_resource *res,
75 struct ttm_validate_buffer *val_buf);
76 static int vmw_legacy_srf_unbind(struct vmw_resource *res,
78 struct ttm_validate_buffer *val_buf);
79 static int vmw_legacy_srf_create(struct vmw_resource *res);
80 static int vmw_legacy_srf_destroy(struct vmw_resource *res);
81 static int vmw_gb_surface_create(struct vmw_resource *res);
82 static int vmw_gb_surface_bind(struct vmw_resource *res,
83 struct ttm_validate_buffer *val_buf);
84 static int vmw_gb_surface_unbind(struct vmw_resource *res,
86 struct ttm_validate_buffer *val_buf);
87 static int vmw_gb_surface_destroy(struct vmw_resource *res);
89 vmw_gb_surface_define_internal(struct drm_device *dev,
90 struct drm_vmw_gb_surface_create_ext_req *req,
91 struct drm_vmw_gb_surface_create_rep *rep,
92 struct drm_file *file_priv);
94 vmw_gb_surface_reference_internal(struct drm_device *dev,
95 struct drm_vmw_surface_arg *req,
96 struct drm_vmw_gb_surface_ref_ext_rep *rep,
97 struct drm_file *file_priv);
99 static const struct vmw_user_resource_conv user_surface_conv = {
100 .object_type = VMW_RES_SURFACE,
101 .base_obj_to_res = vmw_user_surface_base_to_res,
102 .res_free = vmw_user_surface_free
105 const struct vmw_user_resource_conv *user_surface_converter =
109 static uint64_t vmw_user_surface_size;
111 static const struct vmw_res_func vmw_legacy_surface_func = {
112 .res_type = vmw_res_surface,
113 .needs_backup = false,
115 .type_name = "legacy surfaces",
116 .backup_placement = &vmw_srf_placement,
117 .create = &vmw_legacy_srf_create,
118 .destroy = &vmw_legacy_srf_destroy,
119 .bind = &vmw_legacy_srf_bind,
120 .unbind = &vmw_legacy_srf_unbind
123 static const struct vmw_res_func vmw_gb_surface_func = {
124 .res_type = vmw_res_surface,
125 .needs_backup = true,
127 .type_name = "guest backed surfaces",
128 .backup_placement = &vmw_mob_placement,
129 .create = vmw_gb_surface_create,
130 .destroy = vmw_gb_surface_destroy,
131 .bind = vmw_gb_surface_bind,
132 .unbind = vmw_gb_surface_unbind
136 * struct vmw_surface_dma - SVGA3D DMA command
138 struct vmw_surface_dma {
139 SVGA3dCmdHeader header;
140 SVGA3dCmdSurfaceDMA body;
142 SVGA3dCmdSurfaceDMASuffix suffix;
146 * struct vmw_surface_define - SVGA3D Surface Define command
148 struct vmw_surface_define {
149 SVGA3dCmdHeader header;
150 SVGA3dCmdDefineSurface body;
154 * struct vmw_surface_destroy - SVGA3D Surface Destroy command
156 struct vmw_surface_destroy {
157 SVGA3dCmdHeader header;
158 SVGA3dCmdDestroySurface body;
163 * vmw_surface_dma_size - Compute fifo size for a dma command.
165 * @srf: Pointer to a struct vmw_surface
167 * Computes the required size for a surface dma command for backup or
168 * restoration of the surface represented by @srf.
170 static inline uint32_t vmw_surface_dma_size(const struct vmw_surface *srf)
172 return srf->num_sizes * sizeof(struct vmw_surface_dma);
177 * vmw_surface_define_size - Compute fifo size for a surface define command.
179 * @srf: Pointer to a struct vmw_surface
181 * Computes the required size for a surface define command for the definition
182 * of the surface represented by @srf.
184 static inline uint32_t vmw_surface_define_size(const struct vmw_surface *srf)
186 return sizeof(struct vmw_surface_define) + srf->num_sizes *
192 * vmw_surface_destroy_size - Compute fifo size for a surface destroy command.
194 * Computes the required size for a surface destroy command for the destruction
197 static inline uint32_t vmw_surface_destroy_size(void)
199 return sizeof(struct vmw_surface_destroy);
203 * vmw_surface_destroy_encode - Encode a surface_destroy command.
205 * @id: The surface id
206 * @cmd_space: Pointer to memory area in which the commands should be encoded.
208 static void vmw_surface_destroy_encode(uint32_t id,
211 struct vmw_surface_destroy *cmd = (struct vmw_surface_destroy *)
214 cmd->header.id = SVGA_3D_CMD_SURFACE_DESTROY;
215 cmd->header.size = sizeof(cmd->body);
220 * vmw_surface_define_encode - Encode a surface_define command.
222 * @srf: Pointer to a struct vmw_surface object.
223 * @cmd_space: Pointer to memory area in which the commands should be encoded.
225 static void vmw_surface_define_encode(const struct vmw_surface *srf,
228 struct vmw_surface_define *cmd = (struct vmw_surface_define *)
230 struct drm_vmw_size *src_size;
231 SVGA3dSize *cmd_size;
235 cmd_len = sizeof(cmd->body) + srf->num_sizes * sizeof(SVGA3dSize);
237 cmd->header.id = SVGA_3D_CMD_SURFACE_DEFINE;
238 cmd->header.size = cmd_len;
239 cmd->body.sid = srf->res.id;
241 * Downcast of surfaceFlags, was upcasted when received from user-space,
242 * since driver internally stores as 64 bit.
243 * For legacy surface define only 32 bit flag is supported.
245 cmd->body.surfaceFlags = (SVGA3dSurface1Flags)srf->flags;
246 cmd->body.format = srf->format;
247 for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i)
248 cmd->body.face[i].numMipLevels = srf->mip_levels[i];
251 cmd_size = (SVGA3dSize *) cmd;
252 src_size = srf->sizes;
254 for (i = 0; i < srf->num_sizes; ++i, cmd_size++, src_size++) {
255 cmd_size->width = src_size->width;
256 cmd_size->height = src_size->height;
257 cmd_size->depth = src_size->depth;
262 * vmw_surface_dma_encode - Encode a surface_dma command.
264 * @srf: Pointer to a struct vmw_surface object.
265 * @cmd_space: Pointer to memory area in which the commands should be encoded.
266 * @ptr: Pointer to an SVGAGuestPtr indicating where the surface contents
267 * should be placed or read from.
268 * @to_surface: Boolean whether to DMA to the surface or from the surface.
270 static void vmw_surface_dma_encode(struct vmw_surface *srf,
272 const SVGAGuestPtr *ptr,
276 struct vmw_surface_dma *cmd = (struct vmw_surface_dma *)cmd_space;
277 const struct svga3d_surface_desc *desc =
278 svga3dsurface_get_desc(srf->format);
280 for (i = 0; i < srf->num_sizes; ++i) {
281 SVGA3dCmdHeader *header = &cmd->header;
282 SVGA3dCmdSurfaceDMA *body = &cmd->body;
283 SVGA3dCopyBox *cb = &cmd->cb;
284 SVGA3dCmdSurfaceDMASuffix *suffix = &cmd->suffix;
285 const struct vmw_surface_offset *cur_offset = &srf->offsets[i];
286 const struct drm_vmw_size *cur_size = &srf->sizes[i];
288 header->id = SVGA_3D_CMD_SURFACE_DMA;
289 header->size = sizeof(*body) + sizeof(*cb) + sizeof(*suffix);
291 body->guest.ptr = *ptr;
292 body->guest.ptr.offset += cur_offset->bo_offset;
293 body->guest.pitch = svga3dsurface_calculate_pitch(desc,
295 body->host.sid = srf->res.id;
296 body->host.face = cur_offset->face;
297 body->host.mipmap = cur_offset->mip;
298 body->transfer = ((to_surface) ? SVGA3D_WRITE_HOST_VRAM :
299 SVGA3D_READ_HOST_VRAM);
306 cb->w = cur_size->width;
307 cb->h = cur_size->height;
308 cb->d = cur_size->depth;
310 suffix->suffixSize = sizeof(*suffix);
311 suffix->maximumOffset =
312 svga3dsurface_get_image_buffer_size(desc, cur_size,
314 suffix->flags.discard = 0;
315 suffix->flags.unsynchronized = 0;
316 suffix->flags.reserved = 0;
323 * vmw_hw_surface_destroy - destroy a Device surface
325 * @res: Pointer to a struct vmw_resource embedded in a struct
328 * Destroys a the device surface associated with a struct vmw_surface if
329 * any, and adjusts accounting and resource count accordingly.
331 static void vmw_hw_surface_destroy(struct vmw_resource *res)
334 struct vmw_private *dev_priv = res->dev_priv;
335 struct vmw_surface *srf;
338 if (res->func->destroy == vmw_gb_surface_destroy) {
339 (void) vmw_gb_surface_destroy(res);
345 cmd = vmw_fifo_reserve(dev_priv, vmw_surface_destroy_size());
346 if (unlikely(!cmd)) {
347 DRM_ERROR("Failed reserving FIFO space for surface "
352 vmw_surface_destroy_encode(res->id, cmd);
353 vmw_fifo_commit(dev_priv, vmw_surface_destroy_size());
356 * used_memory_size_atomic, or separate lock
357 * to avoid taking dev_priv::cmdbuf_mutex in
361 mutex_lock(&dev_priv->cmdbuf_mutex);
362 srf = vmw_res_to_srf(res);
363 dev_priv->used_memory_size -= res->backup_size;
364 mutex_unlock(&dev_priv->cmdbuf_mutex);
369 * vmw_legacy_srf_create - Create a device surface as part of the
370 * resource validation process.
372 * @res: Pointer to a struct vmw_surface.
374 * If the surface doesn't have a hw id.
376 * Returns -EBUSY if there wasn't sufficient device resources to
377 * complete the validation. Retry after freeing up resources.
379 * May return other errors if the kernel is out of guest resources.
381 static int vmw_legacy_srf_create(struct vmw_resource *res)
383 struct vmw_private *dev_priv = res->dev_priv;
384 struct vmw_surface *srf;
385 uint32_t submit_size;
389 if (likely(res->id != -1))
392 srf = vmw_res_to_srf(res);
393 if (unlikely(dev_priv->used_memory_size + res->backup_size >=
394 dev_priv->memory_size))
398 * Alloc id for the resource.
401 ret = vmw_resource_alloc_id(res);
402 if (unlikely(ret != 0)) {
403 DRM_ERROR("Failed to allocate a surface id.\n");
407 if (unlikely(res->id >= SVGA3D_MAX_SURFACE_IDS)) {
413 * Encode surface define- commands.
416 submit_size = vmw_surface_define_size(srf);
417 cmd = vmw_fifo_reserve(dev_priv, submit_size);
418 if (unlikely(!cmd)) {
419 DRM_ERROR("Failed reserving FIFO space for surface "
425 vmw_surface_define_encode(srf, cmd);
426 vmw_fifo_commit(dev_priv, submit_size);
427 vmw_fifo_resource_inc(dev_priv);
430 * Surface memory usage accounting.
433 dev_priv->used_memory_size += res->backup_size;
437 vmw_resource_release_id(res);
443 * vmw_legacy_srf_dma - Copy backup data to or from a legacy surface.
445 * @res: Pointer to a struct vmw_res embedded in a struct
447 * @val_buf: Pointer to a struct ttm_validate_buffer containing
448 * information about the backup buffer.
449 * @bind: Boolean wether to DMA to the surface.
451 * Transfer backup data to or from a legacy surface as part of the
452 * validation process.
453 * May return other errors if the kernel is out of guest resources.
454 * The backup buffer will be fenced or idle upon successful completion,
455 * and if the surface needs persistent backup storage, the backup buffer
456 * will also be returned reserved iff @bind is true.
458 static int vmw_legacy_srf_dma(struct vmw_resource *res,
459 struct ttm_validate_buffer *val_buf,
463 struct vmw_fence_obj *fence;
464 uint32_t submit_size;
465 struct vmw_surface *srf = vmw_res_to_srf(res);
467 struct vmw_private *dev_priv = res->dev_priv;
469 BUG_ON(!val_buf->bo);
470 submit_size = vmw_surface_dma_size(srf);
471 cmd = vmw_fifo_reserve(dev_priv, submit_size);
472 if (unlikely(!cmd)) {
473 DRM_ERROR("Failed reserving FIFO space for surface "
477 vmw_bo_get_guest_ptr(val_buf->bo, &ptr);
478 vmw_surface_dma_encode(srf, cmd, &ptr, bind);
480 vmw_fifo_commit(dev_priv, submit_size);
483 * Create a fence object and fence the backup buffer.
486 (void) vmw_execbuf_fence_commands(NULL, dev_priv,
489 vmw_bo_fence_single(val_buf->bo, fence);
491 if (likely(fence != NULL))
492 vmw_fence_obj_unreference(&fence);
498 * vmw_legacy_srf_bind - Perform a legacy surface bind as part of the
499 * surface validation process.
501 * @res: Pointer to a struct vmw_res embedded in a struct
503 * @val_buf: Pointer to a struct ttm_validate_buffer containing
504 * information about the backup buffer.
506 * This function will copy backup data to the surface if the
507 * backup buffer is dirty.
509 static int vmw_legacy_srf_bind(struct vmw_resource *res,
510 struct ttm_validate_buffer *val_buf)
512 if (!res->backup_dirty)
515 return vmw_legacy_srf_dma(res, val_buf, true);
520 * vmw_legacy_srf_unbind - Perform a legacy surface unbind as part of the
521 * surface eviction process.
523 * @res: Pointer to a struct vmw_res embedded in a struct
525 * @val_buf: Pointer to a struct ttm_validate_buffer containing
526 * information about the backup buffer.
528 * This function will copy backup data from the surface.
530 static int vmw_legacy_srf_unbind(struct vmw_resource *res,
532 struct ttm_validate_buffer *val_buf)
534 if (unlikely(readback))
535 return vmw_legacy_srf_dma(res, val_buf, false);
540 * vmw_legacy_srf_destroy - Destroy a device surface as part of a
541 * resource eviction process.
543 * @res: Pointer to a struct vmw_res embedded in a struct
546 static int vmw_legacy_srf_destroy(struct vmw_resource *res)
548 struct vmw_private *dev_priv = res->dev_priv;
549 uint32_t submit_size;
552 BUG_ON(res->id == -1);
555 * Encode the dma- and surface destroy commands.
558 submit_size = vmw_surface_destroy_size();
559 cmd = vmw_fifo_reserve(dev_priv, submit_size);
560 if (unlikely(!cmd)) {
561 DRM_ERROR("Failed reserving FIFO space for surface "
566 vmw_surface_destroy_encode(res->id, cmd);
567 vmw_fifo_commit(dev_priv, submit_size);
570 * Surface memory usage accounting.
573 dev_priv->used_memory_size -= res->backup_size;
576 * Release the surface ID.
579 vmw_resource_release_id(res);
580 vmw_fifo_resource_dec(dev_priv);
587 * vmw_surface_init - initialize a struct vmw_surface
589 * @dev_priv: Pointer to a device private struct.
590 * @srf: Pointer to the struct vmw_surface to initialize.
591 * @res_free: Pointer to a resource destructor used to free
594 static int vmw_surface_init(struct vmw_private *dev_priv,
595 struct vmw_surface *srf,
596 void (*res_free) (struct vmw_resource *res))
599 struct vmw_resource *res = &srf->res;
602 ret = vmw_resource_init(dev_priv, res, true, res_free,
603 (dev_priv->has_mob) ? &vmw_gb_surface_func :
604 &vmw_legacy_surface_func);
606 if (unlikely(ret != 0)) {
612 * The surface won't be visible to hardware until a
616 INIT_LIST_HEAD(&srf->view_list);
617 vmw_resource_activate(res, vmw_hw_surface_destroy);
622 * vmw_user_surface_base_to_res - TTM base object to resource converter for
623 * user visible surfaces
625 * @base: Pointer to a TTM base object
627 * Returns the struct vmw_resource embedded in a struct vmw_surface
628 * for the user-visible object identified by the TTM base object @base.
630 static struct vmw_resource *
631 vmw_user_surface_base_to_res(struct ttm_base_object *base)
633 return &(container_of(base, struct vmw_user_surface,
634 prime.base)->srf.res);
638 * vmw_user_surface_free - User visible surface resource destructor
640 * @res: A struct vmw_resource embedded in a struct vmw_surface.
642 static void vmw_user_surface_free(struct vmw_resource *res)
644 struct vmw_surface *srf = vmw_res_to_srf(res);
645 struct vmw_user_surface *user_srf =
646 container_of(srf, struct vmw_user_surface, srf);
647 struct vmw_private *dev_priv = srf->res.dev_priv;
648 uint32_t size = user_srf->size;
650 if (user_srf->master)
651 drm_master_put(&user_srf->master);
654 kfree(srf->snooper.image);
655 ttm_prime_object_kfree(user_srf, prime);
656 ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
660 * vmw_user_surface_free - User visible surface TTM base object destructor
662 * @p_base: Pointer to a pointer to a TTM base object
663 * embedded in a struct vmw_user_surface.
665 * Drops the base object's reference on its resource, and the
666 * pointer pointed to by *p_base is set to NULL.
668 static void vmw_user_surface_base_release(struct ttm_base_object **p_base)
670 struct ttm_base_object *base = *p_base;
671 struct vmw_user_surface *user_srf =
672 container_of(base, struct vmw_user_surface, prime.base);
673 struct vmw_resource *res = &user_srf->srf.res;
676 if (user_srf->backup_base)
677 ttm_base_object_unref(&user_srf->backup_base);
678 vmw_resource_unreference(&res);
682 * vmw_user_surface_destroy_ioctl - Ioctl function implementing
683 * the user surface destroy functionality.
685 * @dev: Pointer to a struct drm_device.
686 * @data: Pointer to data copied from / to user-space.
687 * @file_priv: Pointer to a drm file private structure.
689 int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
690 struct drm_file *file_priv)
692 struct drm_vmw_surface_arg *arg = (struct drm_vmw_surface_arg *)data;
693 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
695 return ttm_ref_object_base_unref(tfile, arg->sid, TTM_REF_USAGE);
699 * vmw_user_surface_define_ioctl - Ioctl function implementing
700 * the user surface define functionality.
702 * @dev: Pointer to a struct drm_device.
703 * @data: Pointer to data copied from / to user-space.
704 * @file_priv: Pointer to a drm file private structure.
706 int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
707 struct drm_file *file_priv)
709 struct vmw_private *dev_priv = vmw_priv(dev);
710 struct vmw_user_surface *user_srf;
711 struct vmw_surface *srf;
712 struct vmw_resource *res;
713 struct vmw_resource *tmp;
714 union drm_vmw_surface_create_arg *arg =
715 (union drm_vmw_surface_create_arg *)data;
716 struct drm_vmw_surface_create_req *req = &arg->req;
717 struct drm_vmw_surface_arg *rep = &arg->rep;
718 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
719 struct ttm_operation_ctx ctx = {
720 .interruptible = true,
725 uint32_t cur_bo_offset;
726 struct drm_vmw_size *cur_size;
727 struct vmw_surface_offset *cur_offset;
730 const struct svga3d_surface_desc *desc;
732 if (unlikely(vmw_user_surface_size == 0))
733 vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
737 for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
738 if (req->mip_levels[i] > DRM_VMW_MAX_MIP_LEVELS)
740 num_sizes += req->mip_levels[i];
743 if (num_sizes > DRM_VMW_MAX_SURFACE_FACES * DRM_VMW_MAX_MIP_LEVELS ||
747 size = vmw_user_surface_size + 128 +
748 ttm_round_pot(num_sizes * sizeof(struct drm_vmw_size)) +
749 ttm_round_pot(num_sizes * sizeof(struct vmw_surface_offset));
752 desc = svga3dsurface_get_desc(req->format);
753 if (unlikely(desc->block_desc == SVGA3DBLOCKDESC_NONE)) {
754 DRM_ERROR("Invalid surface format for surface creation.\n");
755 DRM_ERROR("Format requested is: %d\n", req->format);
759 ret = ttm_read_lock(&dev_priv->reservation_sem, true);
760 if (unlikely(ret != 0))
763 ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
765 if (unlikely(ret != 0)) {
766 if (ret != -ERESTARTSYS)
767 DRM_ERROR("Out of graphics memory for surface"
772 user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL);
773 if (unlikely(!user_srf)) {
775 goto out_no_user_srf;
778 srf = &user_srf->srf;
781 /* Driver internally stores as 64-bit flags */
782 srf->flags = (SVGA3dSurfaceAllFlags)req->flags;
783 srf->format = req->format;
784 srf->scanout = req->scanout;
786 memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels));
787 srf->num_sizes = num_sizes;
788 user_srf->size = size;
789 srf->sizes = memdup_user((struct drm_vmw_size __user *)(unsigned long)
791 sizeof(*srf->sizes) * srf->num_sizes);
792 if (IS_ERR(srf->sizes)) {
793 ret = PTR_ERR(srf->sizes);
796 srf->offsets = kmalloc_array(srf->num_sizes,
797 sizeof(*srf->offsets),
799 if (unlikely(!srf->offsets)) {
804 srf->base_size = *srf->sizes;
805 srf->autogen_filter = SVGA3D_TEX_FILTER_NONE;
806 srf->multisample_count = 0;
807 srf->multisample_pattern = SVGA3D_MS_PATTERN_NONE;
808 srf->quality_level = SVGA3D_MS_QUALITY_NONE;
811 cur_offset = srf->offsets;
812 cur_size = srf->sizes;
814 for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
815 for (j = 0; j < srf->mip_levels[i]; ++j) {
816 uint32_t stride = svga3dsurface_calculate_pitch
819 cur_offset->face = i;
821 cur_offset->bo_offset = cur_bo_offset;
822 cur_bo_offset += svga3dsurface_get_image_buffer_size
823 (desc, cur_size, stride);
828 res->backup_size = cur_bo_offset;
830 srf->num_sizes == 1 &&
831 srf->sizes[0].width == 64 &&
832 srf->sizes[0].height == 64 &&
833 srf->format == SVGA3D_A8R8G8B8) {
835 srf->snooper.image = kzalloc(64 * 64 * 4, GFP_KERNEL);
836 if (!srf->snooper.image) {
837 DRM_ERROR("Failed to allocate cursor_image\n");
842 srf->snooper.image = NULL;
845 user_srf->prime.base.shareable = false;
846 user_srf->prime.base.tfile = NULL;
847 if (drm_is_primary_client(file_priv))
848 user_srf->master = drm_master_get(file_priv->master);
851 * From this point, the generic resource management functions
852 * destroy the object on failure.
855 ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free);
856 if (unlikely(ret != 0))
860 * A gb-aware client referencing a shared surface will
861 * expect a backup buffer to be present.
863 if (dev_priv->has_mob && req->shareable) {
864 uint32_t backup_handle;
866 ret = vmw_user_bo_alloc(dev_priv, tfile,
871 &user_srf->backup_base);
872 if (unlikely(ret != 0)) {
873 vmw_resource_unreference(&res);
878 tmp = vmw_resource_reference(&srf->res);
879 ret = ttm_prime_object_init(tfile, res->backup_size, &user_srf->prime,
880 req->shareable, VMW_RES_SURFACE,
881 &vmw_user_surface_base_release, NULL);
883 if (unlikely(ret != 0)) {
884 vmw_resource_unreference(&tmp);
885 vmw_resource_unreference(&res);
889 rep->sid = user_srf->prime.base.hash.key;
890 vmw_resource_unreference(&res);
892 ttm_read_unlock(&dev_priv->reservation_sem);
899 ttm_prime_object_kfree(user_srf, prime);
901 ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
903 ttm_read_unlock(&dev_priv->reservation_sem);
909 vmw_surface_handle_reference(struct vmw_private *dev_priv,
910 struct drm_file *file_priv,
912 enum drm_vmw_handle_type handle_type,
913 struct ttm_base_object **base_p)
915 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
916 struct vmw_user_surface *user_srf;
918 struct ttm_base_object *base;
920 bool require_exist = false;
922 if (handle_type == DRM_VMW_HANDLE_PRIME) {
923 ret = ttm_prime_fd_to_handle(tfile, u_handle, &handle);
924 if (unlikely(ret != 0))
927 if (unlikely(drm_is_render_client(file_priv)))
928 require_exist = true;
930 if (READ_ONCE(vmw_fpriv(file_priv)->locked_master)) {
931 DRM_ERROR("Locked master refused legacy "
932 "surface reference.\n");
940 base = ttm_base_object_lookup_for_ref(dev_priv->tdev, handle);
941 if (unlikely(!base)) {
942 DRM_ERROR("Could not find surface to reference.\n");
946 if (unlikely(ttm_base_object_type(base) != VMW_RES_SURFACE)) {
947 DRM_ERROR("Referenced object is not a surface.\n");
948 goto out_bad_resource;
951 if (handle_type != DRM_VMW_HANDLE_PRIME) {
952 user_srf = container_of(base, struct vmw_user_surface,
956 * Make sure the surface creator has the same
957 * authenticating master, or is already registered with us.
959 if (drm_is_primary_client(file_priv) &&
960 user_srf->master != file_priv->master)
961 require_exist = true;
963 ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL,
965 if (unlikely(ret != 0)) {
966 DRM_ERROR("Could not add a reference to a surface.\n");
967 goto out_bad_resource;
975 ttm_base_object_unref(&base);
977 if (handle_type == DRM_VMW_HANDLE_PRIME)
978 (void) ttm_ref_object_base_unref(tfile, handle, TTM_REF_USAGE);
984 * vmw_user_surface_define_ioctl - Ioctl function implementing
985 * the user surface reference functionality.
987 * @dev: Pointer to a struct drm_device.
988 * @data: Pointer to data copied from / to user-space.
989 * @file_priv: Pointer to a drm file private structure.
991 int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
992 struct drm_file *file_priv)
994 struct vmw_private *dev_priv = vmw_priv(dev);
995 union drm_vmw_surface_reference_arg *arg =
996 (union drm_vmw_surface_reference_arg *)data;
997 struct drm_vmw_surface_arg *req = &arg->req;
998 struct drm_vmw_surface_create_req *rep = &arg->rep;
999 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
1000 struct vmw_surface *srf;
1001 struct vmw_user_surface *user_srf;
1002 struct drm_vmw_size __user *user_sizes;
1003 struct ttm_base_object *base;
1006 ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid,
1007 req->handle_type, &base);
1008 if (unlikely(ret != 0))
1011 user_srf = container_of(base, struct vmw_user_surface, prime.base);
1012 srf = &user_srf->srf;
1014 /* Downcast of flags when sending back to user space */
1015 rep->flags = (uint32_t)srf->flags;
1016 rep->format = srf->format;
1017 memcpy(rep->mip_levels, srf->mip_levels, sizeof(srf->mip_levels));
1018 user_sizes = (struct drm_vmw_size __user *)(unsigned long)
1022 ret = copy_to_user(user_sizes, &srf->base_size,
1023 sizeof(srf->base_size));
1024 if (unlikely(ret != 0)) {
1025 DRM_ERROR("copy_to_user failed %p %u\n",
1026 user_sizes, srf->num_sizes);
1027 ttm_ref_object_base_unref(tfile, base->hash.key, TTM_REF_USAGE);
1031 ttm_base_object_unref(&base);
1037 * vmw_surface_define_encode - Encode a surface_define command.
1039 * @srf: Pointer to a struct vmw_surface object.
1040 * @cmd_space: Pointer to memory area in which the commands should be encoded.
1042 static int vmw_gb_surface_create(struct vmw_resource *res)
1044 struct vmw_private *dev_priv = res->dev_priv;
1045 struct vmw_surface *srf = vmw_res_to_srf(res);
1046 uint32_t cmd_len, cmd_id, submit_len;
1049 SVGA3dCmdHeader header;
1050 SVGA3dCmdDefineGBSurface body;
1053 SVGA3dCmdHeader header;
1054 SVGA3dCmdDefineGBSurface_v2 body;
1057 SVGA3dCmdHeader header;
1058 SVGA3dCmdDefineGBSurface_v3 body;
1061 if (likely(res->id != -1))
1064 vmw_fifo_resource_inc(dev_priv);
1065 ret = vmw_resource_alloc_id(res);
1066 if (unlikely(ret != 0)) {
1067 DRM_ERROR("Failed to allocate a surface id.\n");
1071 if (unlikely(res->id >= VMWGFX_NUM_GB_SURFACE)) {
1076 if (dev_priv->has_sm4_1 && srf->array_size > 0) {
1077 cmd_id = SVGA_3D_CMD_DEFINE_GB_SURFACE_V3;
1078 cmd_len = sizeof(cmd3->body);
1079 submit_len = sizeof(*cmd3);
1080 } else if (srf->array_size > 0) {
1081 /* has_dx checked on creation time. */
1082 cmd_id = SVGA_3D_CMD_DEFINE_GB_SURFACE_V2;
1083 cmd_len = sizeof(cmd2->body);
1084 submit_len = sizeof(*cmd2);
1086 cmd_id = SVGA_3D_CMD_DEFINE_GB_SURFACE;
1087 cmd_len = sizeof(cmd->body);
1088 submit_len = sizeof(*cmd);
1091 cmd = vmw_fifo_reserve(dev_priv, submit_len);
1092 cmd2 = (typeof(cmd2))cmd;
1093 cmd3 = (typeof(cmd3))cmd;
1094 if (unlikely(!cmd)) {
1095 DRM_ERROR("Failed reserving FIFO space for surface "
1101 if (dev_priv->has_sm4_1 && srf->array_size > 0) {
1102 cmd3->header.id = cmd_id;
1103 cmd3->header.size = cmd_len;
1104 cmd3->body.sid = srf->res.id;
1105 cmd3->body.surfaceFlags = srf->flags;
1106 cmd3->body.format = srf->format;
1107 cmd3->body.numMipLevels = srf->mip_levels[0];
1108 cmd3->body.multisampleCount = srf->multisample_count;
1109 cmd3->body.multisamplePattern = srf->multisample_pattern;
1110 cmd3->body.qualityLevel = srf->quality_level;
1111 cmd3->body.autogenFilter = srf->autogen_filter;
1112 cmd3->body.size.width = srf->base_size.width;
1113 cmd3->body.size.height = srf->base_size.height;
1114 cmd3->body.size.depth = srf->base_size.depth;
1115 cmd3->body.arraySize = srf->array_size;
1116 } else if (srf->array_size > 0) {
1117 cmd2->header.id = cmd_id;
1118 cmd2->header.size = cmd_len;
1119 cmd2->body.sid = srf->res.id;
1120 cmd2->body.surfaceFlags = srf->flags;
1121 cmd2->body.format = srf->format;
1122 cmd2->body.numMipLevels = srf->mip_levels[0];
1123 cmd2->body.multisampleCount = srf->multisample_count;
1124 cmd2->body.autogenFilter = srf->autogen_filter;
1125 cmd2->body.size.width = srf->base_size.width;
1126 cmd2->body.size.height = srf->base_size.height;
1127 cmd2->body.size.depth = srf->base_size.depth;
1128 cmd2->body.arraySize = srf->array_size;
1130 cmd->header.id = cmd_id;
1131 cmd->header.size = cmd_len;
1132 cmd->body.sid = srf->res.id;
1133 cmd->body.surfaceFlags = srf->flags;
1134 cmd->body.format = srf->format;
1135 cmd->body.numMipLevels = srf->mip_levels[0];
1136 cmd->body.multisampleCount = srf->multisample_count;
1137 cmd->body.autogenFilter = srf->autogen_filter;
1138 cmd->body.size.width = srf->base_size.width;
1139 cmd->body.size.height = srf->base_size.height;
1140 cmd->body.size.depth = srf->base_size.depth;
1143 vmw_fifo_commit(dev_priv, submit_len);
1148 vmw_resource_release_id(res);
1150 vmw_fifo_resource_dec(dev_priv);
1155 static int vmw_gb_surface_bind(struct vmw_resource *res,
1156 struct ttm_validate_buffer *val_buf)
1158 struct vmw_private *dev_priv = res->dev_priv;
1160 SVGA3dCmdHeader header;
1161 SVGA3dCmdBindGBSurface body;
1164 SVGA3dCmdHeader header;
1165 SVGA3dCmdUpdateGBSurface body;
1167 uint32_t submit_size;
1168 struct ttm_buffer_object *bo = val_buf->bo;
1170 BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
1172 submit_size = sizeof(*cmd1) + (res->backup_dirty ? sizeof(*cmd2) : 0);
1174 cmd1 = vmw_fifo_reserve(dev_priv, submit_size);
1175 if (unlikely(!cmd1)) {
1176 DRM_ERROR("Failed reserving FIFO space for surface "
1181 cmd1->header.id = SVGA_3D_CMD_BIND_GB_SURFACE;
1182 cmd1->header.size = sizeof(cmd1->body);
1183 cmd1->body.sid = res->id;
1184 cmd1->body.mobid = bo->mem.start;
1185 if (res->backup_dirty) {
1186 cmd2 = (void *) &cmd1[1];
1187 cmd2->header.id = SVGA_3D_CMD_UPDATE_GB_SURFACE;
1188 cmd2->header.size = sizeof(cmd2->body);
1189 cmd2->body.sid = res->id;
1190 res->backup_dirty = false;
1192 vmw_fifo_commit(dev_priv, submit_size);
1197 static int vmw_gb_surface_unbind(struct vmw_resource *res,
1199 struct ttm_validate_buffer *val_buf)
1201 struct vmw_private *dev_priv = res->dev_priv;
1202 struct ttm_buffer_object *bo = val_buf->bo;
1203 struct vmw_fence_obj *fence;
1206 SVGA3dCmdHeader header;
1207 SVGA3dCmdReadbackGBSurface body;
1210 SVGA3dCmdHeader header;
1211 SVGA3dCmdInvalidateGBSurface body;
1214 SVGA3dCmdHeader header;
1215 SVGA3dCmdBindGBSurface body;
1217 uint32_t submit_size;
1221 BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
1223 submit_size = sizeof(*cmd3) + (readback ? sizeof(*cmd1) : sizeof(*cmd2));
1224 cmd = vmw_fifo_reserve(dev_priv, submit_size);
1225 if (unlikely(!cmd)) {
1226 DRM_ERROR("Failed reserving FIFO space for surface "
1232 cmd1 = (void *) cmd;
1233 cmd1->header.id = SVGA_3D_CMD_READBACK_GB_SURFACE;
1234 cmd1->header.size = sizeof(cmd1->body);
1235 cmd1->body.sid = res->id;
1236 cmd3 = (void *) &cmd1[1];
1238 cmd2 = (void *) cmd;
1239 cmd2->header.id = SVGA_3D_CMD_INVALIDATE_GB_SURFACE;
1240 cmd2->header.size = sizeof(cmd2->body);
1241 cmd2->body.sid = res->id;
1242 cmd3 = (void *) &cmd2[1];
1245 cmd3->header.id = SVGA_3D_CMD_BIND_GB_SURFACE;
1246 cmd3->header.size = sizeof(cmd3->body);
1247 cmd3->body.sid = res->id;
1248 cmd3->body.mobid = SVGA3D_INVALID_ID;
1250 vmw_fifo_commit(dev_priv, submit_size);
1253 * Create a fence object and fence the backup buffer.
1256 (void) vmw_execbuf_fence_commands(NULL, dev_priv,
1259 vmw_bo_fence_single(val_buf->bo, fence);
1261 if (likely(fence != NULL))
1262 vmw_fence_obj_unreference(&fence);
1267 static int vmw_gb_surface_destroy(struct vmw_resource *res)
1269 struct vmw_private *dev_priv = res->dev_priv;
1270 struct vmw_surface *srf = vmw_res_to_srf(res);
1272 SVGA3dCmdHeader header;
1273 SVGA3dCmdDestroyGBSurface body;
1276 if (likely(res->id == -1))
1279 mutex_lock(&dev_priv->binding_mutex);
1280 vmw_view_surface_list_destroy(dev_priv, &srf->view_list);
1281 vmw_binding_res_list_scrub(&res->binding_head);
1283 cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
1284 if (unlikely(!cmd)) {
1285 DRM_ERROR("Failed reserving FIFO space for surface "
1287 mutex_unlock(&dev_priv->binding_mutex);
1291 cmd->header.id = SVGA_3D_CMD_DESTROY_GB_SURFACE;
1292 cmd->header.size = sizeof(cmd->body);
1293 cmd->body.sid = res->id;
1294 vmw_fifo_commit(dev_priv, sizeof(*cmd));
1295 mutex_unlock(&dev_priv->binding_mutex);
1296 vmw_resource_release_id(res);
1297 vmw_fifo_resource_dec(dev_priv);
1304 * vmw_gb_surface_define_ioctl - Ioctl function implementing
1305 * the user surface define functionality.
1307 * @dev: Pointer to a struct drm_device.
1308 * @data: Pointer to data copied from / to user-space.
1309 * @file_priv: Pointer to a drm file private structure.
1311 int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
1312 struct drm_file *file_priv)
1314 union drm_vmw_gb_surface_create_arg *arg =
1315 (union drm_vmw_gb_surface_create_arg *)data;
1316 struct drm_vmw_gb_surface_create_rep *rep = &arg->rep;
1317 struct drm_vmw_gb_surface_create_ext_req req_ext;
1319 req_ext.base = arg->req;
1320 req_ext.version = drm_vmw_gb_surface_v1;
1321 req_ext.svga3d_flags_upper_32_bits = 0;
1322 req_ext.multisample_pattern = SVGA3D_MS_PATTERN_NONE;
1323 req_ext.quality_level = SVGA3D_MS_QUALITY_NONE;
1324 req_ext.must_be_zero = 0;
1326 return vmw_gb_surface_define_internal(dev, &req_ext, rep, file_priv);
1330 * vmw_gb_surface_reference_ioctl - Ioctl function implementing
1331 * the user surface reference functionality.
1333 * @dev: Pointer to a struct drm_device.
1334 * @data: Pointer to data copied from / to user-space.
1335 * @file_priv: Pointer to a drm file private structure.
1337 int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data,
1338 struct drm_file *file_priv)
1340 union drm_vmw_gb_surface_reference_arg *arg =
1341 (union drm_vmw_gb_surface_reference_arg *)data;
1342 struct drm_vmw_surface_arg *req = &arg->req;
1343 struct drm_vmw_gb_surface_ref_rep *rep = &arg->rep;
1344 struct drm_vmw_gb_surface_ref_ext_rep rep_ext;
1347 ret = vmw_gb_surface_reference_internal(dev, req, &rep_ext, file_priv);
1349 if (unlikely(ret != 0))
1352 rep->creq = rep_ext.creq.base;
1353 rep->crep = rep_ext.crep;
1359 * vmw_surface_gb_priv_define - Define a private GB surface
1361 * @dev: Pointer to a struct drm_device
1362 * @user_accounting_size: Used to track user-space memory usage, set
1363 * to 0 for kernel mode only memory
1364 * @svga3d_flags: SVGA3d surface flags for the device
1365 * @format: requested surface format
1366 * @for_scanout: true if inteded to be used for scanout buffer
1367 * @num_mip_levels: number of MIP levels
1368 * @multisample_count:
1369 * @array_size: Surface array size.
1370 * @size: width, heigh, depth of the surface requested
1371 * @multisample_pattern: Multisampling pattern when msaa is supported
1372 * @quality_level: Precision settings
1373 * @user_srf_out: allocated user_srf. Set to NULL on failure.
1375 * GB surfaces allocated by this function will not have a user mode handle, and
1376 * thus will only be visible to vmwgfx. For optimization reasons the
1377 * surface may later be given a user mode handle by another function to make
1378 * it available to user mode drivers.
1380 int vmw_surface_gb_priv_define(struct drm_device *dev,
1381 uint32_t user_accounting_size,
1382 SVGA3dSurfaceAllFlags svga3d_flags,
1383 SVGA3dSurfaceFormat format,
1385 uint32_t num_mip_levels,
1386 uint32_t multisample_count,
1387 uint32_t array_size,
1388 struct drm_vmw_size size,
1389 SVGA3dMSPattern multisample_pattern,
1390 SVGA3dMSQualityLevel quality_level,
1391 struct vmw_surface **srf_out)
1393 struct vmw_private *dev_priv = vmw_priv(dev);
1394 struct vmw_user_surface *user_srf;
1395 struct ttm_operation_ctx ctx = {
1396 .interruptible = true,
1397 .no_wait_gpu = false
1399 struct vmw_surface *srf;
1402 u32 sample_count = 1;
1407 if (!svga3dsurface_is_screen_target_format(format)) {
1408 DRM_ERROR("Invalid Screen Target surface format.");
1412 if (size.width > dev_priv->texture_max_width ||
1413 size.height > dev_priv->texture_max_height) {
1414 DRM_ERROR("%ux%u\n, exceeds max surface size %ux%u",
1415 size.width, size.height,
1416 dev_priv->texture_max_width,
1417 dev_priv->texture_max_height);
1421 const struct svga3d_surface_desc *desc;
1423 desc = svga3dsurface_get_desc(format);
1424 if (unlikely(desc->block_desc == SVGA3DBLOCKDESC_NONE)) {
1425 DRM_ERROR("Invalid surface format.\n");
1430 /* array_size must be null for non-GL3 host. */
1431 if (array_size > 0 && !dev_priv->has_dx) {
1432 DRM_ERROR("Tried to create DX surface on non-DX host.\n");
1436 ret = ttm_read_lock(&dev_priv->reservation_sem, true);
1437 if (unlikely(ret != 0))
1440 ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
1441 user_accounting_size, &ctx);
1442 if (unlikely(ret != 0)) {
1443 if (ret != -ERESTARTSYS)
1444 DRM_ERROR("Out of graphics memory for surface"
1449 user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL);
1450 if (unlikely(!user_srf)) {
1452 goto out_no_user_srf;
1455 *srf_out = &user_srf->srf;
1456 user_srf->size = user_accounting_size;
1457 user_srf->prime.base.shareable = false;
1458 user_srf->prime.base.tfile = NULL;
1460 srf = &user_srf->srf;
1461 srf->flags = svga3d_flags;
1462 srf->format = format;
1463 srf->scanout = for_scanout;
1464 srf->mip_levels[0] = num_mip_levels;
1467 srf->offsets = NULL;
1468 srf->base_size = size;
1469 srf->autogen_filter = SVGA3D_TEX_FILTER_NONE;
1470 srf->array_size = array_size;
1471 srf->multisample_count = multisample_count;
1472 srf->multisample_pattern = multisample_pattern;
1473 srf->quality_level = quality_level;
1476 num_layers = array_size;
1477 else if (svga3d_flags & SVGA3D_SURFACE_CUBEMAP)
1478 num_layers = SVGA3D_MAX_SURFACE_FACES;
1480 if (srf->flags & SVGA3D_SURFACE_MULTISAMPLE)
1481 sample_count = srf->multisample_count;
1483 srf->res.backup_size =
1484 svga3dsurface_get_serialized_size_extended(srf->format,
1490 if (srf->flags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT)
1491 srf->res.backup_size += sizeof(SVGA3dDXSOState);
1494 * Don't set SVGA3D_SURFACE_SCREENTARGET flag for a scanout surface with
1495 * size greater than STDU max width/height. This is really a workaround
1496 * to support creation of big framebuffer requested by some user-space
1497 * for whole topology. That big framebuffer won't really be used for
1498 * binding with screen target as during prepare_fb a separate surface is
1499 * created so it's safe to ignore SVGA3D_SURFACE_SCREENTARGET flag.
1501 if (dev_priv->active_display_unit == vmw_du_screen_target &&
1502 for_scanout && size.width <= dev_priv->stdu_max_width &&
1503 size.height <= dev_priv->stdu_max_height)
1504 srf->flags |= SVGA3D_SURFACE_SCREENTARGET;
1507 * From this point, the generic resource management functions
1508 * destroy the object on failure.
1510 ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free);
1512 ttm_read_unlock(&dev_priv->reservation_sem);
1516 ttm_mem_global_free(vmw_mem_glob(dev_priv), user_accounting_size);
1519 ttm_read_unlock(&dev_priv->reservation_sem);
1524 * vmw_gb_surface_define_ext_ioctl - Ioctl function implementing
1525 * the user surface define functionality.
1527 * @dev: Pointer to a struct drm_device.
1528 * @data: Pointer to data copied from / to user-space.
1529 * @file_priv: Pointer to a drm file private structure.
1531 int vmw_gb_surface_define_ext_ioctl(struct drm_device *dev, void *data,
1532 struct drm_file *file_priv)
1534 union drm_vmw_gb_surface_create_ext_arg *arg =
1535 (union drm_vmw_gb_surface_create_ext_arg *)data;
1536 struct drm_vmw_gb_surface_create_ext_req *req = &arg->req;
1537 struct drm_vmw_gb_surface_create_rep *rep = &arg->rep;
1539 return vmw_gb_surface_define_internal(dev, req, rep, file_priv);
1543 * vmw_gb_surface_reference_ext_ioctl - Ioctl function implementing
1544 * the user surface reference functionality.
1546 * @dev: Pointer to a struct drm_device.
1547 * @data: Pointer to data copied from / to user-space.
1548 * @file_priv: Pointer to a drm file private structure.
1550 int vmw_gb_surface_reference_ext_ioctl(struct drm_device *dev, void *data,
1551 struct drm_file *file_priv)
1553 union drm_vmw_gb_surface_reference_ext_arg *arg =
1554 (union drm_vmw_gb_surface_reference_ext_arg *)data;
1555 struct drm_vmw_surface_arg *req = &arg->req;
1556 struct drm_vmw_gb_surface_ref_ext_rep *rep = &arg->rep;
1558 return vmw_gb_surface_reference_internal(dev, req, rep, file_priv);
1562 * vmw_gb_surface_define_internal - Ioctl function implementing
1563 * the user surface define functionality.
1565 * @dev: Pointer to a struct drm_device.
1566 * @req: Request argument from user-space.
1567 * @rep: Response argument to user-space.
1568 * @file_priv: Pointer to a drm file private structure.
1571 vmw_gb_surface_define_internal(struct drm_device *dev,
1572 struct drm_vmw_gb_surface_create_ext_req *req,
1573 struct drm_vmw_gb_surface_create_rep *rep,
1574 struct drm_file *file_priv)
1576 struct vmw_private *dev_priv = vmw_priv(dev);
1577 struct vmw_user_surface *user_srf;
1578 struct vmw_surface *srf;
1579 struct vmw_resource *res;
1580 struct vmw_resource *tmp;
1581 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
1584 uint32_t backup_handle = 0;
1585 SVGA3dSurfaceAllFlags svga3d_flags_64 =
1586 SVGA3D_FLAGS_64(req->svga3d_flags_upper_32_bits,
1587 req->base.svga3d_flags);
1589 if (!dev_priv->has_sm4_1) {
1591 * If SM4_1 is not support then cannot send 64-bit flag to
1594 if (req->svga3d_flags_upper_32_bits != 0)
1597 if (req->base.multisample_count != 0)
1600 if (req->multisample_pattern != SVGA3D_MS_PATTERN_NONE)
1603 if (req->quality_level != SVGA3D_MS_QUALITY_NONE)
1607 if ((svga3d_flags_64 & SVGA3D_SURFACE_MULTISAMPLE) &&
1608 req->base.multisample_count == 0)
1611 if (req->base.mip_levels > DRM_VMW_MAX_MIP_LEVELS)
1614 if (unlikely(vmw_user_surface_size == 0))
1615 vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
1618 size = vmw_user_surface_size + 128;
1620 /* Define a surface based on the parameters. */
1621 ret = vmw_surface_gb_priv_define(dev,
1625 req->base.drm_surface_flags &
1626 drm_vmw_surface_flag_scanout,
1627 req->base.mip_levels,
1628 req->base.multisample_count,
1629 req->base.array_size,
1630 req->base.base_size,
1631 req->multisample_pattern,
1634 if (unlikely(ret != 0))
1637 user_srf = container_of(srf, struct vmw_user_surface, srf);
1638 if (drm_is_primary_client(file_priv))
1639 user_srf->master = drm_master_get(file_priv->master);
1641 ret = ttm_read_lock(&dev_priv->reservation_sem, true);
1642 if (unlikely(ret != 0))
1645 res = &user_srf->srf.res;
1647 if (req->base.buffer_handle != SVGA3D_INVALID_ID) {
1648 ret = vmw_user_bo_lookup(tfile, req->base.buffer_handle,
1650 &user_srf->backup_base);
1652 if (res->backup->base.num_pages * PAGE_SIZE <
1654 DRM_ERROR("Surface backup buffer too small.\n");
1655 vmw_bo_unreference(&res->backup);
1659 backup_handle = req->base.buffer_handle;
1662 } else if (req->base.drm_surface_flags &
1663 drm_vmw_surface_flag_create_buffer)
1664 ret = vmw_user_bo_alloc(dev_priv, tfile,
1666 req->base.drm_surface_flags &
1667 drm_vmw_surface_flag_shareable,
1670 &user_srf->backup_base);
1672 if (unlikely(ret != 0)) {
1673 vmw_resource_unreference(&res);
1677 tmp = vmw_resource_reference(res);
1678 ret = ttm_prime_object_init(tfile, res->backup_size, &user_srf->prime,
1679 req->base.drm_surface_flags &
1680 drm_vmw_surface_flag_shareable,
1682 &vmw_user_surface_base_release, NULL);
1684 if (unlikely(ret != 0)) {
1685 vmw_resource_unreference(&tmp);
1686 vmw_resource_unreference(&res);
1690 rep->handle = user_srf->prime.base.hash.key;
1691 rep->backup_size = res->backup_size;
1693 rep->buffer_map_handle =
1694 drm_vma_node_offset_addr(&res->backup->base.vma_node);
1695 rep->buffer_size = res->backup->base.num_pages * PAGE_SIZE;
1696 rep->buffer_handle = backup_handle;
1698 rep->buffer_map_handle = 0;
1699 rep->buffer_size = 0;
1700 rep->buffer_handle = SVGA3D_INVALID_ID;
1703 vmw_resource_unreference(&res);
1706 ttm_read_unlock(&dev_priv->reservation_sem);
1711 * vmw_gb_surface_reference_internal - Ioctl function implementing
1712 * the user surface reference functionality.
1714 * @dev: Pointer to a struct drm_device.
1715 * @req: Pointer to user-space request surface arg.
1716 * @rep: Pointer to response to user-space.
1717 * @file_priv: Pointer to a drm file private structure.
1720 vmw_gb_surface_reference_internal(struct drm_device *dev,
1721 struct drm_vmw_surface_arg *req,
1722 struct drm_vmw_gb_surface_ref_ext_rep *rep,
1723 struct drm_file *file_priv)
1725 struct vmw_private *dev_priv = vmw_priv(dev);
1726 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
1727 struct vmw_surface *srf;
1728 struct vmw_user_surface *user_srf;
1729 struct ttm_base_object *base;
1730 uint32_t backup_handle;
1733 ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid,
1734 req->handle_type, &base);
1735 if (unlikely(ret != 0))
1738 user_srf = container_of(base, struct vmw_user_surface, prime.base);
1739 srf = &user_srf->srf;
1740 if (!srf->res.backup) {
1741 DRM_ERROR("Shared GB surface is missing a backup buffer.\n");
1742 goto out_bad_resource;
1745 mutex_lock(&dev_priv->cmdbuf_mutex); /* Protect res->backup */
1746 ret = vmw_user_bo_reference(tfile, srf->res.backup, &backup_handle);
1747 mutex_unlock(&dev_priv->cmdbuf_mutex);
1749 if (unlikely(ret != 0)) {
1750 DRM_ERROR("Could not add a reference to a GB surface "
1751 "backup buffer.\n");
1752 (void) ttm_ref_object_base_unref(tfile, base->hash.key,
1754 goto out_bad_resource;
1757 rep->creq.base.svga3d_flags = SVGA3D_FLAGS_LOWER_32(srf->flags);
1758 rep->creq.base.format = srf->format;
1759 rep->creq.base.mip_levels = srf->mip_levels[0];
1760 rep->creq.base.drm_surface_flags = 0;
1761 rep->creq.base.multisample_count = srf->multisample_count;
1762 rep->creq.base.autogen_filter = srf->autogen_filter;
1763 rep->creq.base.array_size = srf->array_size;
1764 rep->creq.base.buffer_handle = backup_handle;
1765 rep->creq.base.base_size = srf->base_size;
1766 rep->crep.handle = user_srf->prime.base.hash.key;
1767 rep->crep.backup_size = srf->res.backup_size;
1768 rep->crep.buffer_handle = backup_handle;
1769 rep->crep.buffer_map_handle =
1770 drm_vma_node_offset_addr(&srf->res.backup->base.vma_node);
1771 rep->crep.buffer_size = srf->res.backup->base.num_pages * PAGE_SIZE;
1773 rep->creq.version = drm_vmw_gb_surface_v1;
1774 rep->creq.svga3d_flags_upper_32_bits =
1775 SVGA3D_FLAGS_UPPER_32(srf->flags);
1776 rep->creq.multisample_pattern = srf->multisample_pattern;
1777 rep->creq.quality_level = srf->quality_level;
1778 rep->creq.must_be_zero = 0;
1781 ttm_base_object_unref(&base);