]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - rpmsg/rpmsg.git/blob - drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
Merge tag 'kbuild-fixes-v4.19-2' of git://git.kernel.org/pub/scm/linux/kernel/git...
[rpmsg/rpmsg.git] / drivers / gpu / drm / vmwgfx / vmwgfx_surface.c
1 // SPDX-License-Identifier: GPL-2.0 OR MIT
2 /**************************************************************************
3  *
4  * Copyright 2009-2015 VMware, Inc., Palo Alto, CA., USA
5  *
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:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
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.
25  *
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))
41 /**
42  * struct vmw_user_surface - User-space visible surface resource
43  *
44  * @base:           The TTM base object handling user-space visibility.
45  * @srf:            The surface metadata.
46  * @size:           TTM accounting size for the surface.
47  * @master: master of the creating client. Used for security check.
48  */
49 struct vmw_user_surface {
50         struct ttm_prime_object prime;
51         struct vmw_surface srf;
52         uint32_t size;
53         struct drm_master *master;
54         struct ttm_base_object *backup_base;
55 };
57 /**
58  * struct vmw_surface_offset - Backing store mip level offset info
59  *
60  * @face:           Surface face.
61  * @mip:            Mip level.
62  * @bo_offset:      Offset into backing store of this mip level.
63  *
64  */
65 struct vmw_surface_offset {
66         uint32_t face;
67         uint32_t mip;
68         uint32_t bo_offset;
69 };
71 static void vmw_user_surface_free(struct vmw_resource *res);
72 static struct vmw_resource *
73 vmw_user_surface_base_to_res(struct ttm_base_object *base);
74 static int vmw_legacy_srf_bind(struct vmw_resource *res,
75                                struct ttm_validate_buffer *val_buf);
76 static int vmw_legacy_srf_unbind(struct vmw_resource *res,
77                                  bool readback,
78                                  struct ttm_validate_buffer *val_buf);
79 static int vmw_legacy_srf_create(struct vmw_resource *res);
80 static int vmw_legacy_srf_destroy(struct vmw_resource *res);
81 static int vmw_gb_surface_create(struct vmw_resource *res);
82 static int vmw_gb_surface_bind(struct vmw_resource *res,
83                                struct ttm_validate_buffer *val_buf);
84 static int vmw_gb_surface_unbind(struct vmw_resource *res,
85                                  bool readback,
86                                  struct ttm_validate_buffer *val_buf);
87 static int vmw_gb_surface_destroy(struct vmw_resource *res);
88 static int
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);
93 static int
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
103 };
105 const struct vmw_user_resource_conv *user_surface_converter =
106         &user_surface_conv;
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,
114         .may_evict = true,
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
121 };
123 static const struct vmw_res_func vmw_gb_surface_func = {
124         .res_type = vmw_res_surface,
125         .needs_backup = true,
126         .may_evict = 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
133 };
135 /**
136  * struct vmw_surface_dma - SVGA3D DMA command
137  */
138 struct vmw_surface_dma {
139         SVGA3dCmdHeader header;
140         SVGA3dCmdSurfaceDMA body;
141         SVGA3dCopyBox cb;
142         SVGA3dCmdSurfaceDMASuffix suffix;
143 };
145 /**
146  * struct vmw_surface_define - SVGA3D Surface Define command
147  */
148 struct vmw_surface_define {
149         SVGA3dCmdHeader header;
150         SVGA3dCmdDefineSurface body;
151 };
153 /**
154  * struct vmw_surface_destroy - SVGA3D Surface Destroy command
155  */
156 struct vmw_surface_destroy {
157         SVGA3dCmdHeader header;
158         SVGA3dCmdDestroySurface body;
159 };
162 /**
163  * vmw_surface_dma_size - Compute fifo size for a dma command.
164  *
165  * @srf: Pointer to a struct vmw_surface
166  *
167  * Computes the required size for a surface dma command for backup or
168  * restoration of the surface represented by @srf.
169  */
170 static inline uint32_t vmw_surface_dma_size(const struct vmw_surface *srf)
172         return srf->num_sizes * sizeof(struct vmw_surface_dma);
176 /**
177  * vmw_surface_define_size - Compute fifo size for a surface define command.
178  *
179  * @srf: Pointer to a struct vmw_surface
180  *
181  * Computes the required size for a surface define command for the definition
182  * of the surface represented by @srf.
183  */
184 static inline uint32_t vmw_surface_define_size(const struct vmw_surface *srf)
186         return sizeof(struct vmw_surface_define) + srf->num_sizes *
187                 sizeof(SVGA3dSize);
191 /**
192  * vmw_surface_destroy_size - Compute fifo size for a surface destroy command.
193  *
194  * Computes the required size for a surface destroy command for the destruction
195  * of a hw surface.
196  */
197 static inline uint32_t vmw_surface_destroy_size(void)
199         return sizeof(struct vmw_surface_destroy);
202 /**
203  * vmw_surface_destroy_encode - Encode a surface_destroy command.
204  *
205  * @id: The surface id
206  * @cmd_space: Pointer to memory area in which the commands should be encoded.
207  */
208 static void vmw_surface_destroy_encode(uint32_t id,
209                                        void *cmd_space)
211         struct vmw_surface_destroy *cmd = (struct vmw_surface_destroy *)
212                 cmd_space;
214         cmd->header.id = SVGA_3D_CMD_SURFACE_DESTROY;
215         cmd->header.size = sizeof(cmd->body);
216         cmd->body.sid = id;
219 /**
220  * vmw_surface_define_encode - Encode a surface_define command.
221  *
222  * @srf: Pointer to a struct vmw_surface object.
223  * @cmd_space: Pointer to memory area in which the commands should be encoded.
224  */
225 static void vmw_surface_define_encode(const struct vmw_surface *srf,
226                                       void *cmd_space)
228         struct vmw_surface_define *cmd = (struct vmw_surface_define *)
229                 cmd_space;
230         struct drm_vmw_size *src_size;
231         SVGA3dSize *cmd_size;
232         uint32_t cmd_len;
233         int i;
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;
240         /*
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.
244          */
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];
250         cmd += 1;
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;
258         }
261 /**
262  * vmw_surface_dma_encode - Encode a surface_dma command.
263  *
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.
269  */
270 static void vmw_surface_dma_encode(struct vmw_surface *srf,
271                                    void *cmd_space,
272                                    const SVGAGuestPtr *ptr,
273                                    bool to_surface)
275         uint32_t i;
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,
294                                                                   cur_size);
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);
300                 cb->x = 0;
301                 cb->y = 0;
302                 cb->z = 0;
303                 cb->srcx = 0;
304                 cb->srcy = 0;
305                 cb->srcz = 0;
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,
313                                                             body->guest.pitch);
314                 suffix->flags.discard = 0;
315                 suffix->flags.unsynchronized = 0;
316                 suffix->flags.reserved = 0;
317                 ++cmd;
318         }
319 };
322 /**
323  * vmw_hw_surface_destroy - destroy a Device surface
324  *
325  * @res:        Pointer to a struct vmw_resource embedded in a struct
326  *              vmw_surface.
327  *
328  * Destroys a the device surface associated with a struct vmw_surface if
329  * any, and adjusts accounting and resource count accordingly.
330  */
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;
336         void *cmd;
338         if (res->func->destroy == vmw_gb_surface_destroy) {
339                 (void) vmw_gb_surface_destroy(res);
340                 return;
341         }
343         if (res->id != -1) {
345                 cmd = vmw_fifo_reserve(dev_priv, vmw_surface_destroy_size());
346                 if (unlikely(!cmd)) {
347                         DRM_ERROR("Failed reserving FIFO space for surface "
348                                   "destruction.\n");
349                         return;
350                 }
352                 vmw_surface_destroy_encode(res->id, cmd);
353                 vmw_fifo_commit(dev_priv, vmw_surface_destroy_size());
355                 /*
356                  * used_memory_size_atomic, or separate lock
357                  * to avoid taking dev_priv::cmdbuf_mutex in
358                  * the destroy path.
359                  */
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);
365         }
368 /**
369  * vmw_legacy_srf_create - Create a device surface as part of the
370  * resource validation process.
371  *
372  * @res: Pointer to a struct vmw_surface.
373  *
374  * If the surface doesn't have a hw id.
375  *
376  * Returns -EBUSY if there wasn't sufficient device resources to
377  * complete the validation. Retry after freeing up resources.
378  *
379  * May return other errors if the kernel is out of guest resources.
380  */
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;
386         uint8_t *cmd;
387         int ret;
389         if (likely(res->id != -1))
390                 return 0;
392         srf = vmw_res_to_srf(res);
393         if (unlikely(dev_priv->used_memory_size + res->backup_size >=
394                      dev_priv->memory_size))
395                 return -EBUSY;
397         /*
398          * Alloc id for the resource.
399          */
401         ret = vmw_resource_alloc_id(res);
402         if (unlikely(ret != 0)) {
403                 DRM_ERROR("Failed to allocate a surface id.\n");
404                 goto out_no_id;
405         }
407         if (unlikely(res->id >= SVGA3D_MAX_SURFACE_IDS)) {
408                 ret = -EBUSY;
409                 goto out_no_fifo;
410         }
412         /*
413          * Encode surface define- commands.
414          */
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 "
420                           "creation.\n");
421                 ret = -ENOMEM;
422                 goto out_no_fifo;
423         }
425         vmw_surface_define_encode(srf, cmd);
426         vmw_fifo_commit(dev_priv, submit_size);
427         vmw_fifo_resource_inc(dev_priv);
429         /*
430          * Surface memory usage accounting.
431          */
433         dev_priv->used_memory_size += res->backup_size;
434         return 0;
436 out_no_fifo:
437         vmw_resource_release_id(res);
438 out_no_id:
439         return ret;
442 /**
443  * vmw_legacy_srf_dma - Copy backup data to or from a legacy surface.
444  *
445  * @res:            Pointer to a struct vmw_res embedded in a struct
446  *                  vmw_surface.
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.
450  *
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.
457  */
458 static int vmw_legacy_srf_dma(struct vmw_resource *res,
459                               struct ttm_validate_buffer *val_buf,
460                               bool bind)
462         SVGAGuestPtr ptr;
463         struct vmw_fence_obj *fence;
464         uint32_t submit_size;
465         struct vmw_surface *srf = vmw_res_to_srf(res);
466         uint8_t *cmd;
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 "
474                           "DMA.\n");
475                 return -ENOMEM;
476         }
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);
482         /*
483          * Create a fence object and fence the backup buffer.
484          */
486         (void) vmw_execbuf_fence_commands(NULL, dev_priv,
487                                           &fence, NULL);
489         vmw_bo_fence_single(val_buf->bo, fence);
491         if (likely(fence != NULL))
492                 vmw_fence_obj_unreference(&fence);
494         return 0;
497 /**
498  * vmw_legacy_srf_bind - Perform a legacy surface bind as part of the
499  *                       surface validation process.
500  *
501  * @res:            Pointer to a struct vmw_res embedded in a struct
502  *                  vmw_surface.
503  * @val_buf:        Pointer to a struct ttm_validate_buffer containing
504  *                  information about the backup buffer.
505  *
506  * This function will copy backup data to the surface if the
507  * backup buffer is dirty.
508  */
509 static int vmw_legacy_srf_bind(struct vmw_resource *res,
510                                struct ttm_validate_buffer *val_buf)
512         if (!res->backup_dirty)
513                 return 0;
515         return vmw_legacy_srf_dma(res, val_buf, true);
519 /**
520  * vmw_legacy_srf_unbind - Perform a legacy surface unbind as part of the
521  *                         surface eviction process.
522  *
523  * @res:            Pointer to a struct vmw_res embedded in a struct
524  *                  vmw_surface.
525  * @val_buf:        Pointer to a struct ttm_validate_buffer containing
526  *                  information about the backup buffer.
527  *
528  * This function will copy backup data from the surface.
529  */
530 static int vmw_legacy_srf_unbind(struct vmw_resource *res,
531                                  bool readback,
532                                  struct ttm_validate_buffer *val_buf)
534         if (unlikely(readback))
535                 return vmw_legacy_srf_dma(res, val_buf, false);
536         return 0;
539 /**
540  * vmw_legacy_srf_destroy - Destroy a device surface as part of a
541  *                          resource eviction process.
542  *
543  * @res:            Pointer to a struct vmw_res embedded in a struct
544  *                  vmw_surface.
545  */
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;
550         uint8_t *cmd;
552         BUG_ON(res->id == -1);
554         /*
555          * Encode the dma- and surface destroy commands.
556          */
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 "
562                           "eviction.\n");
563                 return -ENOMEM;
564         }
566         vmw_surface_destroy_encode(res->id, cmd);
567         vmw_fifo_commit(dev_priv, submit_size);
569         /*
570          * Surface memory usage accounting.
571          */
573         dev_priv->used_memory_size -= res->backup_size;
575         /*
576          * Release the surface ID.
577          */
579         vmw_resource_release_id(res);
580         vmw_fifo_resource_dec(dev_priv);
582         return 0;
586 /**
587  * vmw_surface_init - initialize a struct vmw_surface
588  *
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
592  *                  the object.
593  */
594 static int vmw_surface_init(struct vmw_private *dev_priv,
595                             struct vmw_surface *srf,
596                             void (*res_free) (struct vmw_resource *res))
598         int ret;
599         struct vmw_resource *res = &srf->res;
601         BUG_ON(!res_free);
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)) {
607                 res_free(res);
608                 return ret;
609         }
611         /*
612          * The surface won't be visible to hardware until a
613          * surface validate.
614          */
616         INIT_LIST_HEAD(&srf->view_list);
617         vmw_resource_activate(res, vmw_hw_surface_destroy);
618         return ret;
621 /**
622  * vmw_user_surface_base_to_res - TTM base object to resource converter for
623  *                                user visible surfaces
624  *
625  * @base:           Pointer to a TTM base object
626  *
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.
629  */
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);
637 /**
638  * vmw_user_surface_free - User visible surface resource destructor
639  *
640  * @res:            A struct vmw_resource embedded in a struct vmw_surface.
641  */
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);
652         kfree(srf->offsets);
653         kfree(srf->sizes);
654         kfree(srf->snooper.image);
655         ttm_prime_object_kfree(user_srf, prime);
656         ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
659 /**
660  * vmw_user_surface_free - User visible surface TTM base object destructor
661  *
662  * @p_base:         Pointer to a pointer to a TTM base object
663  *                  embedded in a struct vmw_user_surface.
664  *
665  * Drops the base object's reference on its resource, and the
666  * pointer pointed to by *p_base is set to NULL.
667  */
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;
675         *p_base = NULL;
676         if (user_srf->backup_base)
677                 ttm_base_object_unref(&user_srf->backup_base);
678         vmw_resource_unreference(&res);
681 /**
682  * vmw_user_surface_destroy_ioctl - Ioctl function implementing
683  *                                  the user surface destroy functionality.
684  *
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.
688  */
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);
698 /**
699  * vmw_user_surface_define_ioctl - Ioctl function implementing
700  *                                  the user surface define functionality.
701  *
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.
705  */
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,
721                 .no_wait_gpu = false
722         };
723         int ret;
724         int i, j;
725         uint32_t cur_bo_offset;
726         struct drm_vmw_size *cur_size;
727         struct vmw_surface_offset *cur_offset;
728         uint32_t num_sizes;
729         uint32_t size;
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)) +
734                         128;
736         num_sizes = 0;
737         for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
738                 if (req->mip_levels[i] > DRM_VMW_MAX_MIP_LEVELS)
739                         return -EINVAL;
740                 num_sizes += req->mip_levels[i];
741         }
743         if (num_sizes > DRM_VMW_MAX_SURFACE_FACES * DRM_VMW_MAX_MIP_LEVELS ||
744             num_sizes == 0)
745                 return -EINVAL;
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);
756                 return -EINVAL;
757         }
759         ret = ttm_read_lock(&dev_priv->reservation_sem, true);
760         if (unlikely(ret != 0))
761                 return ret;
763         ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
764                                    size, &ctx);
765         if (unlikely(ret != 0)) {
766                 if (ret != -ERESTARTSYS)
767                         DRM_ERROR("Out of graphics memory for surface"
768                                   " creation.\n");
769                 goto out_unlock;
770         }
772         user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL);
773         if (unlikely(!user_srf)) {
774                 ret = -ENOMEM;
775                 goto out_no_user_srf;
776         }
778         srf = &user_srf->srf;
779         res = &srf->res;
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)
790                                  req->size_addr,
791                                  sizeof(*srf->sizes) * srf->num_sizes);
792         if (IS_ERR(srf->sizes)) {
793                 ret = PTR_ERR(srf->sizes);
794                 goto out_no_sizes;
795         }
796         srf->offsets = kmalloc_array(srf->num_sizes,
797                                      sizeof(*srf->offsets),
798                                      GFP_KERNEL);
799         if (unlikely(!srf->offsets)) {
800                 ret = -ENOMEM;
801                 goto out_no_offsets;
802         }
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;
810         cur_bo_offset = 0;
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
817                                 (desc, cur_size);
819                         cur_offset->face = i;
820                         cur_offset->mip = j;
821                         cur_offset->bo_offset = cur_bo_offset;
822                         cur_bo_offset += svga3dsurface_get_image_buffer_size
823                                 (desc, cur_size, stride);
824                         ++cur_offset;
825                         ++cur_size;
826                 }
827         }
828         res->backup_size = cur_bo_offset;
829         if (srf->scanout &&
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");
838                         ret = -ENOMEM;
839                         goto out_no_copy;
840                 }
841         } else {
842                 srf->snooper.image = NULL;
843         }
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);
850         /**
851          * From this point, the generic resource management functions
852          * destroy the object on failure.
853          */
855         ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free);
856         if (unlikely(ret != 0))
857                 goto out_unlock;
859         /*
860          * A gb-aware client referencing a shared surface will
861          * expect a backup buffer to be present.
862          */
863         if (dev_priv->has_mob && req->shareable) {
864                 uint32_t backup_handle;
866                 ret = vmw_user_bo_alloc(dev_priv, tfile,
867                                         res->backup_size,
868                                         true,
869                                         &backup_handle,
870                                         &res->backup,
871                                         &user_srf->backup_base);
872                 if (unlikely(ret != 0)) {
873                         vmw_resource_unreference(&res);
874                         goto out_unlock;
875                 }
876         }
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);
886                 goto out_unlock;
887         }
889         rep->sid = user_srf->prime.base.hash.key;
890         vmw_resource_unreference(&res);
892         ttm_read_unlock(&dev_priv->reservation_sem);
893         return 0;
894 out_no_copy:
895         kfree(srf->offsets);
896 out_no_offsets:
897         kfree(srf->sizes);
898 out_no_sizes:
899         ttm_prime_object_kfree(user_srf, prime);
900 out_no_user_srf:
901         ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
902 out_unlock:
903         ttm_read_unlock(&dev_priv->reservation_sem);
904         return ret;
908 static int
909 vmw_surface_handle_reference(struct vmw_private *dev_priv,
910                              struct drm_file *file_priv,
911                              uint32_t u_handle,
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;
917         uint32_t handle;
918         struct ttm_base_object *base;
919         int ret;
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))
925                         return ret;
926         } else {
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");
933                         return -EACCES;
934                 }
936                 handle = u_handle;
937         }
939         ret = -EINVAL;
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");
943                 goto out_no_lookup;
944         }
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;
949         }
951         if (handle_type != DRM_VMW_HANDLE_PRIME) {
952                 user_srf = container_of(base, struct vmw_user_surface,
953                                         prime.base);
955                 /*
956                  * Make sure the surface creator has the same
957                  * authenticating master, or is already registered with us.
958                  */
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,
964                                          require_exist);
965                 if (unlikely(ret != 0)) {
966                         DRM_ERROR("Could not add a reference to a surface.\n");
967                         goto out_bad_resource;
968                 }
969         }
971         *base_p = base;
972         return 0;
974 out_bad_resource:
975         ttm_base_object_unref(&base);
976 out_no_lookup:
977         if (handle_type == DRM_VMW_HANDLE_PRIME)
978                 (void) ttm_ref_object_base_unref(tfile, handle, TTM_REF_USAGE);
980         return ret;
983 /**
984  * vmw_user_surface_define_ioctl - Ioctl function implementing
985  *                                  the user surface reference functionality.
986  *
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.
990  */
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;
1004         int ret;
1006         ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid,
1007                                            req->handle_type, &base);
1008         if (unlikely(ret != 0))
1009                 return ret;
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)
1019             rep->size_addr;
1021         if (user_sizes)
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);
1028                 ret = -EFAULT;
1029         }
1031         ttm_base_object_unref(&base);
1033         return ret;
1036 /**
1037  * vmw_surface_define_encode - Encode a surface_define command.
1038  *
1039  * @srf: Pointer to a struct vmw_surface object.
1040  * @cmd_space: Pointer to memory area in which the commands should be encoded.
1041  */
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;
1047         int ret;
1048         struct {
1049                 SVGA3dCmdHeader header;
1050                 SVGA3dCmdDefineGBSurface body;
1051         } *cmd;
1052         struct {
1053                 SVGA3dCmdHeader header;
1054                 SVGA3dCmdDefineGBSurface_v2 body;
1055         } *cmd2;
1056         struct {
1057                 SVGA3dCmdHeader header;
1058                 SVGA3dCmdDefineGBSurface_v3 body;
1059         } *cmd3;
1061         if (likely(res->id != -1))
1062                 return 0;
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");
1068                 goto out_no_id;
1069         }
1071         if (unlikely(res->id >= VMWGFX_NUM_GB_SURFACE)) {
1072                 ret = -EBUSY;
1073                 goto out_no_fifo;
1074         }
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);
1085         } else {
1086                 cmd_id = SVGA_3D_CMD_DEFINE_GB_SURFACE;
1087                 cmd_len = sizeof(cmd->body);
1088                 submit_len = sizeof(*cmd);
1089         }
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 "
1096                           "creation.\n");
1097                 ret = -ENOMEM;
1098                 goto out_no_fifo;
1099         }
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;
1129         } else {
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;
1141         }
1143         vmw_fifo_commit(dev_priv, submit_len);
1145         return 0;
1147 out_no_fifo:
1148         vmw_resource_release_id(res);
1149 out_no_id:
1150         vmw_fifo_resource_dec(dev_priv);
1151         return ret;
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;
1159         struct {
1160                 SVGA3dCmdHeader header;
1161                 SVGA3dCmdBindGBSurface body;
1162         } *cmd1;
1163         struct {
1164                 SVGA3dCmdHeader header;
1165                 SVGA3dCmdUpdateGBSurface body;
1166         } *cmd2;
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 "
1177                           "binding.\n");
1178                 return -ENOMEM;
1179         }
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;
1191         }
1192         vmw_fifo_commit(dev_priv, submit_size);
1194         return 0;
1197 static int vmw_gb_surface_unbind(struct vmw_resource *res,
1198                                  bool readback,
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;
1205         struct {
1206                 SVGA3dCmdHeader header;
1207                 SVGA3dCmdReadbackGBSurface body;
1208         } *cmd1;
1209         struct {
1210                 SVGA3dCmdHeader header;
1211                 SVGA3dCmdInvalidateGBSurface body;
1212         } *cmd2;
1213         struct {
1214                 SVGA3dCmdHeader header;
1215                 SVGA3dCmdBindGBSurface body;
1216         } *cmd3;
1217         uint32_t submit_size;
1218         uint8_t *cmd;
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 "
1227                           "unbinding.\n");
1228                 return -ENOMEM;
1229         }
1231         if (readback) {
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];
1237         } else {
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];
1243         }
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);
1252         /*
1253          * Create a fence object and fence the backup buffer.
1254          */
1256         (void) vmw_execbuf_fence_commands(NULL, dev_priv,
1257                                           &fence, NULL);
1259         vmw_bo_fence_single(val_buf->bo, fence);
1261         if (likely(fence != NULL))
1262                 vmw_fence_obj_unreference(&fence);
1264         return 0;
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);
1271         struct {
1272                 SVGA3dCmdHeader header;
1273                 SVGA3dCmdDestroyGBSurface body;
1274         } *cmd;
1276         if (likely(res->id == -1))
1277                 return 0;
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 "
1286                           "destruction.\n");
1287                 mutex_unlock(&dev_priv->binding_mutex);
1288                 return -ENOMEM;
1289         }
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);
1299         return 0;
1303 /**
1304  * vmw_gb_surface_define_ioctl - Ioctl function implementing
1305  * the user surface define functionality.
1306  *
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.
1310  */
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);
1329 /**
1330  * vmw_gb_surface_reference_ioctl - Ioctl function implementing
1331  * the user surface reference functionality.
1332  *
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.
1336  */
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;
1345         int ret;
1347         ret = vmw_gb_surface_reference_internal(dev, req, &rep_ext, file_priv);
1349         if (unlikely(ret != 0))
1350                 return ret;
1352         rep->creq = rep_ext.creq.base;
1353         rep->crep = rep_ext.crep;
1355         return ret;
1358 /**
1359  * vmw_surface_gb_priv_define - Define a private GB surface
1360  *
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.
1374  *
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.
1379  */
1380 int vmw_surface_gb_priv_define(struct drm_device *dev,
1381                                uint32_t user_accounting_size,
1382                                SVGA3dSurfaceAllFlags svga3d_flags,
1383                                SVGA3dSurfaceFormat format,
1384                                bool for_scanout,
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
1398         };
1399         struct vmw_surface *srf;
1400         int ret;
1401         u32 num_layers = 1;
1402         u32 sample_count = 1;
1404         *srf_out = NULL;
1406         if (for_scanout) {
1407                 if (!svga3dsurface_is_screen_target_format(format)) {
1408                         DRM_ERROR("Invalid Screen Target surface format.");
1409                         return -EINVAL;
1410                 }
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);
1418                         return -EINVAL;
1419                 }
1420         } else {
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");
1426                         return -EINVAL;
1427                 }
1428         }
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");
1433                 return -EINVAL;
1434         }
1436         ret = ttm_read_lock(&dev_priv->reservation_sem, true);
1437         if (unlikely(ret != 0))
1438                 return ret;
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"
1445                                   " creation.\n");
1446                 goto out_unlock;
1447         }
1449         user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL);
1450         if (unlikely(!user_srf)) {
1451                 ret = -ENOMEM;
1452                 goto out_no_user_srf;
1453         }
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;
1465         srf->num_sizes         = 1;
1466         srf->sizes             = NULL;
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;
1475         if (array_size)
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,
1485                                                            srf->base_size,
1486                                                            srf->mip_levels[0],
1487                                                            num_layers,
1488                                                            sample_count);
1490         if (srf->flags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT)
1491                 srf->res.backup_size += sizeof(SVGA3dDXSOState);
1493         /*
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.
1500          */
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;
1506         /*
1507          * From this point, the generic resource management functions
1508          * destroy the object on failure.
1509          */
1510         ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free);
1512         ttm_read_unlock(&dev_priv->reservation_sem);
1513         return ret;
1515 out_no_user_srf:
1516         ttm_mem_global_free(vmw_mem_glob(dev_priv), user_accounting_size);
1518 out_unlock:
1519         ttm_read_unlock(&dev_priv->reservation_sem);
1520         return ret;
1523 /**
1524  * vmw_gb_surface_define_ext_ioctl - Ioctl function implementing
1525  * the user surface define functionality.
1526  *
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.
1530  */
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);
1542 /**
1543  * vmw_gb_surface_reference_ext_ioctl - Ioctl function implementing
1544  * the user surface reference functionality.
1545  *
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.
1549  */
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);
1561 /**
1562  * vmw_gb_surface_define_internal - Ioctl function implementing
1563  * the user surface define functionality.
1564  *
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.
1569  */
1570 static int
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;
1582         int ret;
1583         uint32_t size;
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) {
1590                 /*
1591                  * If SM4_1 is not support then cannot send 64-bit flag to
1592                  * device.
1593                  */
1594                 if (req->svga3d_flags_upper_32_bits != 0)
1595                         return -EINVAL;
1597                 if (req->base.multisample_count != 0)
1598                         return -EINVAL;
1600                 if (req->multisample_pattern != SVGA3D_MS_PATTERN_NONE)
1601                         return -EINVAL;
1603                 if (req->quality_level != SVGA3D_MS_QUALITY_NONE)
1604                         return -EINVAL;
1605         }
1607         if ((svga3d_flags_64 & SVGA3D_SURFACE_MULTISAMPLE) &&
1608             req->base.multisample_count == 0)
1609                 return -EINVAL;
1611         if (req->base.mip_levels > DRM_VMW_MAX_MIP_LEVELS)
1612                 return -EINVAL;
1614         if (unlikely(vmw_user_surface_size == 0))
1615                 vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
1616                         128;
1618         size = vmw_user_surface_size + 128;
1620         /* Define a surface based on the parameters. */
1621         ret = vmw_surface_gb_priv_define(dev,
1622                                          size,
1623                                          svga3d_flags_64,
1624                                          req->base.format,
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,
1632                                          req->quality_level,
1633                                          &srf);
1634         if (unlikely(ret != 0))
1635                 return ret;
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))
1643                 return ret;
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,
1649                                          &res->backup,
1650                                          &user_srf->backup_base);
1651                 if (ret == 0) {
1652                         if (res->backup->base.num_pages * PAGE_SIZE <
1653                             res->backup_size) {
1654                                 DRM_ERROR("Surface backup buffer too small.\n");
1655                                 vmw_bo_unreference(&res->backup);
1656                                 ret = -EINVAL;
1657                                 goto out_unlock;
1658                         } else {
1659                                 backup_handle = req->base.buffer_handle;
1660                         }
1661                 }
1662         } else if (req->base.drm_surface_flags &
1663                    drm_vmw_surface_flag_create_buffer)
1664                 ret = vmw_user_bo_alloc(dev_priv, tfile,
1665                                         res->backup_size,
1666                                         req->base.drm_surface_flags &
1667                                         drm_vmw_surface_flag_shareable,
1668                                         &backup_handle,
1669                                         &res->backup,
1670                                         &user_srf->backup_base);
1672         if (unlikely(ret != 0)) {
1673                 vmw_resource_unreference(&res);
1674                 goto out_unlock;
1675         }
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,
1681                                     VMW_RES_SURFACE,
1682                                     &vmw_user_surface_base_release, NULL);
1684         if (unlikely(ret != 0)) {
1685                 vmw_resource_unreference(&tmp);
1686                 vmw_resource_unreference(&res);
1687                 goto out_unlock;
1688         }
1690         rep->handle      = user_srf->prime.base.hash.key;
1691         rep->backup_size = res->backup_size;
1692         if (res->backup) {
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;
1697         } else {
1698                 rep->buffer_map_handle = 0;
1699                 rep->buffer_size = 0;
1700                 rep->buffer_handle = SVGA3D_INVALID_ID;
1701         }
1703         vmw_resource_unreference(&res);
1705 out_unlock:
1706         ttm_read_unlock(&dev_priv->reservation_sem);
1707         return ret;
1710 /**
1711  * vmw_gb_surface_reference_internal - Ioctl function implementing
1712  * the user surface reference functionality.
1713  *
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.
1718  */
1719 static int
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;
1731         int ret = -EINVAL;
1733         ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid,
1734                                            req->handle_type, &base);
1735         if (unlikely(ret != 0))
1736                 return ret;
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;
1743         }
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,
1753                                                  TTM_REF_USAGE);
1754                 goto out_bad_resource;
1755         }
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;
1780 out_bad_resource:
1781         ttm_base_object_unref(&base);
1783         return ret;