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 **************************************************************************/
27
28 #include <drm/ttm/ttm_placement.h>
29
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"
35
36 #define SVGA3D_FLAGS_64(upper32, lower32) (((uint64_t)upper32 << 32) | lower32)
37 #define SVGA3D_FLAGS_UPPER_32(svga3d_flags) (svga3d_flags >> 32)
38 #define SVGA3D_FLAGS_LOWER_32(svga3d_flags) \
39 (svga3d_flags & ((uint64_t)U32_MAX))
40
41 /**
42 * struct vmw_user_surface - User-space visible surface resource
43 *
44 * @base: The TTM base object handling user-space visibility.
45 * @srf: The surface metadata.
46 * @size: TTM accounting size for the surface.
47 * @master: master of the creating client. Used for security check.
48 */
49 struct vmw_user_surface {
50 struct ttm_prime_object prime;
51 struct vmw_surface srf;
52 uint32_t size;
53 struct drm_master *master;
54 struct ttm_base_object *backup_base;
55 };
56
57 /**
58 * struct vmw_surface_offset - Backing store mip level offset info
59 *
60 * @face: Surface face.
61 * @mip: Mip level.
62 * @bo_offset: Offset into backing store of this mip level.
63 *
64 */
65 struct vmw_surface_offset {
66 uint32_t face;
67 uint32_t mip;
68 uint32_t bo_offset;
69 };
70
71 static void vmw_user_surface_free(struct vmw_resource *res);
72 static struct vmw_resource *
73 vmw_user_surface_base_to_res(struct ttm_base_object *base);
74 static int vmw_legacy_srf_bind(struct vmw_resource *res,
75 struct ttm_validate_buffer *val_buf);
76 static int vmw_legacy_srf_unbind(struct vmw_resource *res,
77 bool readback,
78 struct ttm_validate_buffer *val_buf);
79 static int vmw_legacy_srf_create(struct vmw_resource *res);
80 static int vmw_legacy_srf_destroy(struct vmw_resource *res);
81 static int vmw_gb_surface_create(struct vmw_resource *res);
82 static int vmw_gb_surface_bind(struct vmw_resource *res,
83 struct ttm_validate_buffer *val_buf);
84 static int vmw_gb_surface_unbind(struct vmw_resource *res,
85 bool readback,
86 struct ttm_validate_buffer *val_buf);
87 static int vmw_gb_surface_destroy(struct vmw_resource *res);
88 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);
98
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 };
104
105 const struct vmw_user_resource_conv *user_surface_converter =
106 &user_surface_conv;
107
108
109 static uint64_t vmw_user_surface_size;
110
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 };
122
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 };
134
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 };
144
145 /**
146 * struct vmw_surface_define - SVGA3D Surface Define command
147 */
148 struct vmw_surface_define {
149 SVGA3dCmdHeader header;
150 SVGA3dCmdDefineSurface body;
151 };
152
153 /**
154 * struct vmw_surface_destroy - SVGA3D Surface Destroy command
155 */
156 struct vmw_surface_destroy {
157 SVGA3dCmdHeader header;
158 SVGA3dCmdDestroySurface body;
159 };
160
161
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 */
vmw_surface_dma_size(const struct vmw_surface * srf)170 static inline uint32_t vmw_surface_dma_size(const struct vmw_surface *srf)
171 {
172 return srf->num_sizes * sizeof(struct vmw_surface_dma);
173 }
174
175
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 */
vmw_surface_define_size(const struct vmw_surface * srf)184 static inline uint32_t vmw_surface_define_size(const struct vmw_surface *srf)
185 {
186 return sizeof(struct vmw_surface_define) + srf->num_sizes *
187 sizeof(SVGA3dSize);
188 }
189
190
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 */
vmw_surface_destroy_size(void)197 static inline uint32_t vmw_surface_destroy_size(void)
198 {
199 return sizeof(struct vmw_surface_destroy);
200 }
201
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 */
vmw_surface_destroy_encode(uint32_t id,void * cmd_space)208 static void vmw_surface_destroy_encode(uint32_t id,
209 void *cmd_space)
210 {
211 struct vmw_surface_destroy *cmd = (struct vmw_surface_destroy *)
212 cmd_space;
213
214 cmd->header.id = SVGA_3D_CMD_SURFACE_DESTROY;
215 cmd->header.size = sizeof(cmd->body);
216 cmd->body.sid = id;
217 }
218
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 */
vmw_surface_define_encode(const struct vmw_surface * srf,void * cmd_space)225 static void vmw_surface_define_encode(const struct vmw_surface *srf,
226 void *cmd_space)
227 {
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;
234
235 cmd_len = sizeof(cmd->body) + srf->num_sizes * sizeof(SVGA3dSize);
236
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];
249
250 cmd += 1;
251 cmd_size = (SVGA3dSize *) cmd;
252 src_size = srf->sizes;
253
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 }
259 }
260
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 */
vmw_surface_dma_encode(struct vmw_surface * srf,void * cmd_space,const SVGAGuestPtr * ptr,bool to_surface)270 static void vmw_surface_dma_encode(struct vmw_surface *srf,
271 void *cmd_space,
272 const SVGAGuestPtr *ptr,
273 bool to_surface)
274 {
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);
279
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];
287
288 header->id = SVGA_3D_CMD_SURFACE_DMA;
289 header->size = sizeof(*body) + sizeof(*cb) + sizeof(*suffix);
290
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;
309
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 };
320
321
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 */
vmw_hw_surface_destroy(struct vmw_resource * res)331 static void vmw_hw_surface_destroy(struct vmw_resource *res)
332 {
333
334 struct vmw_private *dev_priv = res->dev_priv;
335 struct vmw_surface *srf;
336 void *cmd;
337
338 if (res->func->destroy == vmw_gb_surface_destroy) {
339 (void) vmw_gb_surface_destroy(res);
340 return;
341 }
342
343 if (res->id != -1) {
344
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 }
351
352 vmw_surface_destroy_encode(res->id, cmd);
353 vmw_fifo_commit(dev_priv, vmw_surface_destroy_size());
354
355 /*
356 * used_memory_size_atomic, or separate lock
357 * to avoid taking dev_priv::cmdbuf_mutex in
358 * the destroy path.
359 */
360
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 }
366 }
367
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 */
vmw_legacy_srf_create(struct vmw_resource * res)381 static int vmw_legacy_srf_create(struct vmw_resource *res)
382 {
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;
388
389 if (likely(res->id != -1))
390 return 0;
391
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;
396
397 /*
398 * Alloc id for the resource.
399 */
400
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 }
406
407 if (unlikely(res->id >= SVGA3D_MAX_SURFACE_IDS)) {
408 ret = -EBUSY;
409 goto out_no_fifo;
410 }
411
412 /*
413 * Encode surface define- commands.
414 */
415
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 }
424
425 vmw_surface_define_encode(srf, cmd);
426 vmw_fifo_commit(dev_priv, submit_size);
427 vmw_fifo_resource_inc(dev_priv);
428
429 /*
430 * Surface memory usage accounting.
431 */
432
433 dev_priv->used_memory_size += res->backup_size;
434 return 0;
435
436 out_no_fifo:
437 vmw_resource_release_id(res);
438 out_no_id:
439 return ret;
440 }
441
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 */
vmw_legacy_srf_dma(struct vmw_resource * res,struct ttm_validate_buffer * val_buf,bool bind)458 static int vmw_legacy_srf_dma(struct vmw_resource *res,
459 struct ttm_validate_buffer *val_buf,
460 bool bind)
461 {
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;
468
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);
479
480 vmw_fifo_commit(dev_priv, submit_size);
481
482 /*
483 * Create a fence object and fence the backup buffer.
484 */
485
486 (void) vmw_execbuf_fence_commands(NULL, dev_priv,
487 &fence, NULL);
488
489 vmw_bo_fence_single(val_buf->bo, fence);
490
491 if (likely(fence != NULL))
492 vmw_fence_obj_unreference(&fence);
493
494 return 0;
495 }
496
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 */
vmw_legacy_srf_bind(struct vmw_resource * res,struct ttm_validate_buffer * val_buf)509 static int vmw_legacy_srf_bind(struct vmw_resource *res,
510 struct ttm_validate_buffer *val_buf)
511 {
512 if (!res->backup_dirty)
513 return 0;
514
515 return vmw_legacy_srf_dma(res, val_buf, true);
516 }
517
518
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 */
vmw_legacy_srf_unbind(struct vmw_resource * res,bool readback,struct ttm_validate_buffer * val_buf)530 static int vmw_legacy_srf_unbind(struct vmw_resource *res,
531 bool readback,
532 struct ttm_validate_buffer *val_buf)
533 {
534 if (unlikely(readback))
535 return vmw_legacy_srf_dma(res, val_buf, false);
536 return 0;
537 }
538
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 */
vmw_legacy_srf_destroy(struct vmw_resource * res)546 static int vmw_legacy_srf_destroy(struct vmw_resource *res)
547 {
548 struct vmw_private *dev_priv = res->dev_priv;
549 uint32_t submit_size;
550 uint8_t *cmd;
551
552 BUG_ON(res->id == -1);
553
554 /*
555 * Encode the dma- and surface destroy commands.
556 */
557
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 }
565
566 vmw_surface_destroy_encode(res->id, cmd);
567 vmw_fifo_commit(dev_priv, submit_size);
568
569 /*
570 * Surface memory usage accounting.
571 */
572
573 dev_priv->used_memory_size -= res->backup_size;
574
575 /*
576 * Release the surface ID.
577 */
578
579 vmw_resource_release_id(res);
580 vmw_fifo_resource_dec(dev_priv);
581
582 return 0;
583 }
584
585
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 */
vmw_surface_init(struct vmw_private * dev_priv,struct vmw_surface * srf,void (* res_free)(struct vmw_resource * res))594 static int vmw_surface_init(struct vmw_private *dev_priv,
595 struct vmw_surface *srf,
596 void (*res_free) (struct vmw_resource *res))
597 {
598 int ret;
599 struct vmw_resource *res = &srf->res;
600
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);
605
606 if (unlikely(ret != 0)) {
607 res_free(res);
608 return ret;
609 }
610
611 /*
612 * The surface won't be visible to hardware until a
613 * surface validate.
614 */
615
616 INIT_LIST_HEAD(&srf->view_list);
617 vmw_resource_activate(res, vmw_hw_surface_destroy);
618 return ret;
619 }
620
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 *
vmw_user_surface_base_to_res(struct ttm_base_object * base)631 vmw_user_surface_base_to_res(struct ttm_base_object *base)
632 {
633 return &(container_of(base, struct vmw_user_surface,
634 prime.base)->srf.res);
635 }
636
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 */
vmw_user_surface_free(struct vmw_resource * res)642 static void vmw_user_surface_free(struct vmw_resource *res)
643 {
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;
649
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);
657 }
658
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 */
vmw_user_surface_base_release(struct ttm_base_object ** p_base)668 static void vmw_user_surface_base_release(struct ttm_base_object **p_base)
669 {
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;
674
675 *p_base = NULL;
676 if (user_srf->backup_base)
677 ttm_base_object_unref(&user_srf->backup_base);
678 vmw_resource_unreference(&res);
679 }
680
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 */
vmw_surface_destroy_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)689 int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
690 struct drm_file *file_priv)
691 {
692 struct drm_vmw_surface_arg *arg = (struct drm_vmw_surface_arg *)data;
693 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
694
695 return ttm_ref_object_base_unref(tfile, arg->sid, TTM_REF_USAGE);
696 }
697
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 */
vmw_surface_define_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)706 int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
707 struct drm_file *file_priv)
708 {
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;
731
732 if (unlikely(vmw_user_surface_size == 0))
733 vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
734 128;
735
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 }
742
743 if (num_sizes > DRM_VMW_MAX_SURFACE_FACES * DRM_VMW_MAX_MIP_LEVELS ||
744 num_sizes == 0)
745 return -EINVAL;
746
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));
750
751
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 }
758
759 ret = ttm_read_lock(&dev_priv->reservation_sem, true);
760 if (unlikely(ret != 0))
761 return ret;
762
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 }
771
772 user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL);
773 if (unlikely(!user_srf)) {
774 ret = -ENOMEM;
775 goto out_no_user_srf;
776 }
777
778 srf = &user_srf->srf;
779 res = &srf->res;
780
781 /* Driver internally stores as 64-bit flags */
782 srf->flags = (SVGA3dSurfaceAllFlags)req->flags;
783 srf->format = req->format;
784 srf->scanout = req->scanout;
785
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 }
803
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;
809
810 cur_bo_offset = 0;
811 cur_offset = srf->offsets;
812 cur_size = srf->sizes;
813
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);
818
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) {
834
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 }
844
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);
849
850 /**
851 * From this point, the generic resource management functions
852 * destroy the object on failure.
853 */
854
855 ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free);
856 if (unlikely(ret != 0))
857 goto out_unlock;
858
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;
865
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 }
877
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);
882
883 if (unlikely(ret != 0)) {
884 vmw_resource_unreference(&tmp);
885 vmw_resource_unreference(&res);
886 goto out_unlock;
887 }
888
889 rep->sid = user_srf->prime.base.hash.key;
890 vmw_resource_unreference(&res);
891
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;
905 }
906
907
908 static int
vmw_surface_handle_reference(struct vmw_private * dev_priv,struct drm_file * file_priv,uint32_t u_handle,enum drm_vmw_handle_type handle_type,struct ttm_base_object ** base_p)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)
914 {
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;
921
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;
929
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 }
935
936 handle = u_handle;
937 }
938
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 }
945
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 }
950
951 if (handle_type != DRM_VMW_HANDLE_PRIME) {
952 user_srf = container_of(base, struct vmw_user_surface,
953 prime.base);
954
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;
962
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 }
970
971 *base_p = base;
972 return 0;
973
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);
979
980 return ret;
981 }
982
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 */
vmw_surface_reference_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)991 int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
992 struct drm_file *file_priv)
993 {
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;
1005
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;
1010
1011 user_srf = container_of(base, struct vmw_user_surface, prime.base);
1012 srf = &user_srf->srf;
1013
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;
1020
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 }
1030
1031 ttm_base_object_unref(&base);
1032
1033 return ret;
1034 }
1035
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 */
vmw_gb_surface_create(struct vmw_resource * res)1042 static int vmw_gb_surface_create(struct vmw_resource *res)
1043 {
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;
1060
1061 if (likely(res->id != -1))
1062 return 0;
1063
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 }
1070
1071 if (unlikely(res->id >= VMWGFX_NUM_GB_SURFACE)) {
1072 ret = -EBUSY;
1073 goto out_no_fifo;
1074 }
1075
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 }
1090
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 }
1100
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 }
1142
1143 vmw_fifo_commit(dev_priv, submit_len);
1144
1145 return 0;
1146
1147 out_no_fifo:
1148 vmw_resource_release_id(res);
1149 out_no_id:
1150 vmw_fifo_resource_dec(dev_priv);
1151 return ret;
1152 }
1153
1154
vmw_gb_surface_bind(struct vmw_resource * res,struct ttm_validate_buffer * val_buf)1155 static int vmw_gb_surface_bind(struct vmw_resource *res,
1156 struct ttm_validate_buffer *val_buf)
1157 {
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;
1169
1170 BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
1171
1172 submit_size = sizeof(*cmd1) + (res->backup_dirty ? sizeof(*cmd2) : 0);
1173
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 }
1180
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);
1193
1194 return 0;
1195 }
1196
vmw_gb_surface_unbind(struct vmw_resource * res,bool readback,struct ttm_validate_buffer * val_buf)1197 static int vmw_gb_surface_unbind(struct vmw_resource *res,
1198 bool readback,
1199 struct ttm_validate_buffer *val_buf)
1200 {
1201 struct vmw_private *dev_priv = res->dev_priv;
1202 struct ttm_buffer_object *bo = val_buf->bo;
1203 struct vmw_fence_obj *fence;
1204
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;
1219
1220
1221 BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
1222
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 }
1230
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 }
1244
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;
1249
1250 vmw_fifo_commit(dev_priv, submit_size);
1251
1252 /*
1253 * Create a fence object and fence the backup buffer.
1254 */
1255
1256 (void) vmw_execbuf_fence_commands(NULL, dev_priv,
1257 &fence, NULL);
1258
1259 vmw_bo_fence_single(val_buf->bo, fence);
1260
1261 if (likely(fence != NULL))
1262 vmw_fence_obj_unreference(&fence);
1263
1264 return 0;
1265 }
1266
vmw_gb_surface_destroy(struct vmw_resource * res)1267 static int vmw_gb_surface_destroy(struct vmw_resource *res)
1268 {
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;
1275
1276 if (likely(res->id == -1))
1277 return 0;
1278
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);
1282
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 }
1290
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);
1298
1299 return 0;
1300 }
1301
1302
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 */
vmw_gb_surface_define_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)1311 int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
1312 struct drm_file *file_priv)
1313 {
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;
1318
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;
1325
1326 return vmw_gb_surface_define_internal(dev, &req_ext, rep, file_priv);
1327 }
1328
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 */
vmw_gb_surface_reference_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)1337 int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data,
1338 struct drm_file *file_priv)
1339 {
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;
1346
1347 ret = vmw_gb_surface_reference_internal(dev, req, &rep_ext, file_priv);
1348
1349 if (unlikely(ret != 0))
1350 return ret;
1351
1352 rep->creq = rep_ext.creq.base;
1353 rep->crep = rep_ext.crep;
1354
1355 return ret;
1356 }
1357
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 */
vmw_surface_gb_priv_define(struct drm_device * dev,uint32_t user_accounting_size,SVGA3dSurfaceAllFlags svga3d_flags,SVGA3dSurfaceFormat format,bool for_scanout,uint32_t num_mip_levels,uint32_t multisample_count,uint32_t array_size,struct drm_vmw_size size,SVGA3dMSPattern multisample_pattern,SVGA3dMSQualityLevel quality_level,struct vmw_surface ** srf_out)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)
1392 {
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;
1403
1404 *srf_out = NULL;
1405
1406 if (for_scanout) {
1407 if (!svga3dsurface_is_screen_target_format(format)) {
1408 DRM_ERROR("Invalid Screen Target surface format.");
1409 return -EINVAL;
1410 }
1411
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;
1422
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 }
1429
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 }
1435
1436 ret = ttm_read_lock(&dev_priv->reservation_sem, true);
1437 if (unlikely(ret != 0))
1438 return ret;
1439
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 }
1448
1449 user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL);
1450 if (unlikely(!user_srf)) {
1451 ret = -ENOMEM;
1452 goto out_no_user_srf;
1453 }
1454
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;
1459
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;
1474
1475 if (array_size)
1476 num_layers = array_size;
1477 else if (svga3d_flags & SVGA3D_SURFACE_CUBEMAP)
1478 num_layers = SVGA3D_MAX_SURFACE_FACES;
1479
1480 if (srf->flags & SVGA3D_SURFACE_MULTISAMPLE)
1481 sample_count = srf->multisample_count;
1482
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);
1489
1490 if (srf->flags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT)
1491 srf->res.backup_size += sizeof(SVGA3dDXSOState);
1492
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;
1505
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);
1511
1512 ttm_read_unlock(&dev_priv->reservation_sem);
1513 return ret;
1514
1515 out_no_user_srf:
1516 ttm_mem_global_free(vmw_mem_glob(dev_priv), user_accounting_size);
1517
1518 out_unlock:
1519 ttm_read_unlock(&dev_priv->reservation_sem);
1520 return ret;
1521 }
1522
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 */
vmw_gb_surface_define_ext_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)1531 int vmw_gb_surface_define_ext_ioctl(struct drm_device *dev, void *data,
1532 struct drm_file *file_priv)
1533 {
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;
1538
1539 return vmw_gb_surface_define_internal(dev, req, rep, file_priv);
1540 }
1541
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 */
vmw_gb_surface_reference_ext_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)1550 int vmw_gb_surface_reference_ext_ioctl(struct drm_device *dev, void *data,
1551 struct drm_file *file_priv)
1552 {
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;
1557
1558 return vmw_gb_surface_reference_internal(dev, req, rep, file_priv);
1559 }
1560
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
vmw_gb_surface_define_internal(struct drm_device * dev,struct drm_vmw_gb_surface_create_ext_req * req,struct drm_vmw_gb_surface_create_rep * rep,struct drm_file * file_priv)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)
1575 {
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);
1588
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;
1596
1597 if (req->base.multisample_count != 0)
1598 return -EINVAL;
1599
1600 if (req->multisample_pattern != SVGA3D_MS_PATTERN_NONE)
1601 return -EINVAL;
1602
1603 if (req->quality_level != SVGA3D_MS_QUALITY_NONE)
1604 return -EINVAL;
1605 }
1606
1607 if ((svga3d_flags_64 & SVGA3D_SURFACE_MULTISAMPLE) &&
1608 req->base.multisample_count == 0)
1609 return -EINVAL;
1610
1611 if (req->base.mip_levels > DRM_VMW_MAX_MIP_LEVELS)
1612 return -EINVAL;
1613
1614 if (unlikely(vmw_user_surface_size == 0))
1615 vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
1616 128;
1617
1618 size = vmw_user_surface_size + 128;
1619
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;
1636
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);
1640
1641 ret = ttm_read_lock(&dev_priv->reservation_sem, true);
1642 if (unlikely(ret != 0))
1643 return ret;
1644
1645 res = &user_srf->srf.res;
1646
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);
1671
1672 if (unlikely(ret != 0)) {
1673 vmw_resource_unreference(&res);
1674 goto out_unlock;
1675 }
1676
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);
1683
1684 if (unlikely(ret != 0)) {
1685 vmw_resource_unreference(&tmp);
1686 vmw_resource_unreference(&res);
1687 goto out_unlock;
1688 }
1689
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 }
1702
1703 vmw_resource_unreference(&res);
1704
1705 out_unlock:
1706 ttm_read_unlock(&dev_priv->reservation_sem);
1707 return ret;
1708 }
1709
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
vmw_gb_surface_reference_internal(struct drm_device * dev,struct drm_vmw_surface_arg * req,struct drm_vmw_gb_surface_ref_ext_rep * rep,struct drm_file * file_priv)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)
1724 {
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;
1732
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;
1737
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 }
1744
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);
1748
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 }
1756
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;
1772
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;
1779
1780 out_bad_resource:
1781 ttm_base_object_unref(&base);
1782
1783 return ret;
1784 }
1785