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