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[]; 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 if (res->guest_memory_bo) 690 drm_gem_object_put(&res->guest_memory_bo->tbo.base); 691 692 *p_base = NULL; 693 vmw_resource_unreference(&res); 694 } 695 696 /** 697 * vmw_surface_destroy_ioctl - Ioctl function implementing 698 * the user surface destroy functionality. 699 * 700 * @dev: Pointer to a struct drm_device. 701 * @data: Pointer to data copied from / to user-space. 702 * @file_priv: Pointer to a drm file private structure. 703 */ 704 int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data, 705 struct drm_file *file_priv) 706 { 707 struct drm_vmw_surface_arg *arg = (struct drm_vmw_surface_arg *)data; 708 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 709 710 return ttm_ref_object_base_unref(tfile, arg->sid); 711 } 712 713 /** 714 * vmw_surface_define_ioctl - Ioctl function implementing 715 * the user surface define functionality. 716 * 717 * @dev: Pointer to a struct drm_device. 718 * @data: Pointer to data copied from / to user-space. 719 * @file_priv: Pointer to a drm file private structure. 720 */ 721 int vmw_surface_define_ioctl(struct drm_device *dev, void *data, 722 struct drm_file *file_priv) 723 { 724 struct vmw_private *dev_priv = vmw_priv(dev); 725 struct vmw_user_surface *user_srf; 726 struct vmw_surface *srf; 727 struct vmw_surface_metadata *metadata; 728 struct vmw_resource *res; 729 struct vmw_resource *tmp; 730 union drm_vmw_surface_create_arg *arg = 731 (union drm_vmw_surface_create_arg *)data; 732 struct drm_vmw_surface_create_req *req = &arg->req; 733 struct drm_vmw_surface_arg *rep = &arg->rep; 734 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 735 int ret; 736 int i, j; 737 uint32_t cur_bo_offset; 738 struct drm_vmw_size *cur_size; 739 struct vmw_surface_offset *cur_offset; 740 uint32_t num_sizes; 741 const SVGA3dSurfaceDesc *desc; 742 743 num_sizes = 0; 744 for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) { 745 if (req->mip_levels[i] > DRM_VMW_MAX_MIP_LEVELS) 746 return -EINVAL; 747 num_sizes += req->mip_levels[i]; 748 } 749 750 if (num_sizes > DRM_VMW_MAX_SURFACE_FACES * DRM_VMW_MAX_MIP_LEVELS || 751 num_sizes == 0) 752 return -EINVAL; 753 754 desc = vmw_surface_get_desc(req->format); 755 if (unlikely(desc->blockDesc == SVGA3DBLOCKDESC_NONE)) { 756 VMW_DEBUG_USER("Invalid format %d for surface creation.\n", 757 req->format); 758 return -EINVAL; 759 } 760 761 user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL); 762 if (unlikely(!user_srf)) { 763 ret = -ENOMEM; 764 goto out_unlock; 765 } 766 767 srf = &user_srf->srf; 768 metadata = &srf->metadata; 769 res = &srf->res; 770 771 /* Driver internally stores as 64-bit flags */ 772 metadata->flags = (SVGA3dSurfaceAllFlags)req->flags; 773 metadata->format = req->format; 774 metadata->scanout = req->scanout; 775 776 memcpy(metadata->mip_levels, req->mip_levels, 777 sizeof(metadata->mip_levels)); 778 metadata->num_sizes = num_sizes; 779 metadata->sizes = 780 memdup_user((struct drm_vmw_size __user *)(unsigned long) 781 req->size_addr, 782 sizeof(*metadata->sizes) * metadata->num_sizes); 783 if (IS_ERR(metadata->sizes)) { 784 ret = PTR_ERR(metadata->sizes); 785 goto out_no_sizes; 786 } 787 srf->offsets = kmalloc_array(metadata->num_sizes, sizeof(*srf->offsets), 788 GFP_KERNEL); 789 if (unlikely(!srf->offsets)) { 790 ret = -ENOMEM; 791 goto out_no_offsets; 792 } 793 794 metadata->base_size = *srf->metadata.sizes; 795 metadata->autogen_filter = SVGA3D_TEX_FILTER_NONE; 796 metadata->multisample_count = 0; 797 metadata->multisample_pattern = SVGA3D_MS_PATTERN_NONE; 798 metadata->quality_level = SVGA3D_MS_QUALITY_NONE; 799 800 cur_bo_offset = 0; 801 cur_offset = srf->offsets; 802 cur_size = metadata->sizes; 803 804 for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) { 805 for (j = 0; j < metadata->mip_levels[i]; ++j) { 806 uint32_t stride = vmw_surface_calculate_pitch( 807 desc, cur_size); 808 809 cur_offset->face = i; 810 cur_offset->mip = j; 811 cur_offset->bo_offset = cur_bo_offset; 812 cur_bo_offset += vmw_surface_get_image_buffer_size 813 (desc, cur_size, stride); 814 ++cur_offset; 815 ++cur_size; 816 } 817 } 818 res->guest_memory_size = cur_bo_offset; 819 if (metadata->scanout && 820 metadata->num_sizes == 1 && 821 metadata->sizes[0].width == VMW_CURSOR_SNOOP_WIDTH && 822 metadata->sizes[0].height == VMW_CURSOR_SNOOP_HEIGHT && 823 metadata->format == VMW_CURSOR_SNOOP_FORMAT) { 824 const struct SVGA3dSurfaceDesc *desc = 825 vmw_surface_get_desc(VMW_CURSOR_SNOOP_FORMAT); 826 const u32 cursor_size_bytes = VMW_CURSOR_SNOOP_WIDTH * 827 VMW_CURSOR_SNOOP_HEIGHT * 828 desc->pitchBytesPerBlock; 829 srf->snooper.image = kzalloc(cursor_size_bytes, GFP_KERNEL); 830 if (!srf->snooper.image) { 831 DRM_ERROR("Failed to allocate cursor_image\n"); 832 ret = -ENOMEM; 833 goto out_no_copy; 834 } 835 } else { 836 srf->snooper.image = NULL; 837 } 838 839 user_srf->prime.base.shareable = false; 840 user_srf->prime.base.tfile = NULL; 841 if (drm_is_primary_client(file_priv)) 842 user_srf->master = drm_file_get_master(file_priv); 843 844 /** 845 * From this point, the generic resource management functions 846 * destroy the object on failure. 847 */ 848 849 ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free); 850 if (unlikely(ret != 0)) 851 goto out_unlock; 852 853 /* 854 * A gb-aware client referencing a shared surface will 855 * expect a backup buffer to be present. 856 */ 857 if (dev_priv->has_mob && req->shareable) { 858 uint32_t backup_handle; 859 860 ret = vmw_gem_object_create_with_handle(dev_priv, 861 file_priv, 862 res->guest_memory_size, 863 &backup_handle, 864 &res->guest_memory_bo); 865 if (unlikely(ret != 0)) { 866 vmw_resource_unreference(&res); 867 goto out_unlock; 868 } 869 vmw_bo_reference(res->guest_memory_bo); 870 /* 871 * We don't expose the handle to the userspace and surface 872 * already holds a gem reference 873 */ 874 drm_gem_handle_delete(file_priv, backup_handle); 875 } 876 877 tmp = vmw_resource_reference(&srf->res); 878 ret = ttm_prime_object_init(tfile, res->guest_memory_size, &user_srf->prime, 879 req->shareable, VMW_RES_SURFACE, 880 &vmw_user_surface_base_release); 881 882 if (unlikely(ret != 0)) { 883 vmw_resource_unreference(&tmp); 884 vmw_resource_unreference(&res); 885 goto out_unlock; 886 } 887 888 rep->sid = user_srf->prime.base.handle; 889 vmw_resource_unreference(&res); 890 891 return 0; 892 out_no_copy: 893 kfree(srf->offsets); 894 out_no_offsets: 895 kfree(metadata->sizes); 896 out_no_sizes: 897 ttm_prime_object_kfree(user_srf, prime); 898 out_unlock: 899 return ret; 900 } 901 902 903 static int 904 vmw_surface_handle_reference(struct vmw_private *dev_priv, 905 struct drm_file *file_priv, 906 uint32_t u_handle, 907 enum drm_vmw_handle_type handle_type, 908 struct ttm_base_object **base_p) 909 { 910 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 911 struct vmw_user_surface *user_srf; 912 uint32_t handle; 913 struct ttm_base_object *base; 914 int ret; 915 916 if (handle_type == DRM_VMW_HANDLE_PRIME) { 917 ret = ttm_prime_fd_to_handle(tfile, u_handle, &handle); 918 if (unlikely(ret != 0)) 919 return ret; 920 } else { 921 handle = u_handle; 922 } 923 924 ret = -EINVAL; 925 base = ttm_base_object_lookup_for_ref(dev_priv->tdev, handle); 926 if (unlikely(!base)) { 927 VMW_DEBUG_USER("Could not find surface to reference.\n"); 928 goto out_no_lookup; 929 } 930 931 if (unlikely(ttm_base_object_type(base) != VMW_RES_SURFACE)) { 932 VMW_DEBUG_USER("Referenced object is not a surface.\n"); 933 goto out_bad_resource; 934 } 935 if (handle_type != DRM_VMW_HANDLE_PRIME) { 936 bool require_exist = false; 937 938 user_srf = container_of(base, struct vmw_user_surface, 939 prime.base); 940 941 /* Error out if we are unauthenticated primary */ 942 if (drm_is_primary_client(file_priv) && 943 !file_priv->authenticated) { 944 ret = -EACCES; 945 goto out_bad_resource; 946 } 947 948 /* 949 * Make sure the surface creator has the same 950 * authenticating master, or is already registered with us. 951 */ 952 if (drm_is_primary_client(file_priv) && 953 user_srf->master != file_priv->master) 954 require_exist = true; 955 956 if (unlikely(drm_is_render_client(file_priv))) 957 require_exist = true; 958 959 ret = ttm_ref_object_add(tfile, base, NULL, require_exist); 960 if (unlikely(ret != 0)) { 961 DRM_ERROR("Could not add a reference to a surface.\n"); 962 goto out_bad_resource; 963 } 964 } 965 966 *base_p = base; 967 return 0; 968 969 out_bad_resource: 970 ttm_base_object_unref(&base); 971 out_no_lookup: 972 if (handle_type == DRM_VMW_HANDLE_PRIME) 973 (void) ttm_ref_object_base_unref(tfile, handle); 974 975 return ret; 976 } 977 978 /** 979 * vmw_surface_reference_ioctl - Ioctl function implementing 980 * the user surface reference functionality. 981 * 982 * @dev: Pointer to a struct drm_device. 983 * @data: Pointer to data copied from / to user-space. 984 * @file_priv: Pointer to a drm file private structure. 985 */ 986 int vmw_surface_reference_ioctl(struct drm_device *dev, void *data, 987 struct drm_file *file_priv) 988 { 989 struct vmw_private *dev_priv = vmw_priv(dev); 990 union drm_vmw_surface_reference_arg *arg = 991 (union drm_vmw_surface_reference_arg *)data; 992 struct drm_vmw_surface_arg *req = &arg->req; 993 struct drm_vmw_surface_create_req *rep = &arg->rep; 994 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 995 struct vmw_surface *srf; 996 struct vmw_user_surface *user_srf; 997 struct drm_vmw_size __user *user_sizes; 998 struct ttm_base_object *base; 999 int ret; 1000 1001 ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid, 1002 req->handle_type, &base); 1003 if (unlikely(ret != 0)) 1004 return ret; 1005 1006 user_srf = container_of(base, struct vmw_user_surface, prime.base); 1007 srf = &user_srf->srf; 1008 1009 /* Downcast of flags when sending back to user space */ 1010 rep->flags = (uint32_t)srf->metadata.flags; 1011 rep->format = srf->metadata.format; 1012 memcpy(rep->mip_levels, srf->metadata.mip_levels, 1013 sizeof(srf->metadata.mip_levels)); 1014 user_sizes = (struct drm_vmw_size __user *)(unsigned long) 1015 rep->size_addr; 1016 1017 if (user_sizes) 1018 ret = copy_to_user(user_sizes, &srf->metadata.base_size, 1019 sizeof(srf->metadata.base_size)); 1020 if (unlikely(ret != 0)) { 1021 VMW_DEBUG_USER("copy_to_user failed %p %u\n", user_sizes, 1022 srf->metadata.num_sizes); 1023 ttm_ref_object_base_unref(tfile, base->handle); 1024 ret = -EFAULT; 1025 } 1026 1027 ttm_base_object_unref(&base); 1028 1029 return ret; 1030 } 1031 1032 /** 1033 * vmw_gb_surface_create - Encode a surface_define command. 1034 * 1035 * @res: Pointer to a struct vmw_resource embedded in a struct 1036 * vmw_surface. 1037 */ 1038 static int vmw_gb_surface_create(struct vmw_resource *res) 1039 { 1040 struct vmw_private *dev_priv = res->dev_priv; 1041 struct vmw_surface *srf = vmw_res_to_srf(res); 1042 struct vmw_surface_metadata *metadata = &srf->metadata; 1043 uint32_t cmd_len, cmd_id, submit_len; 1044 int ret; 1045 struct { 1046 SVGA3dCmdHeader header; 1047 SVGA3dCmdDefineGBSurface body; 1048 } *cmd; 1049 struct { 1050 SVGA3dCmdHeader header; 1051 SVGA3dCmdDefineGBSurface_v2 body; 1052 } *cmd2; 1053 struct { 1054 SVGA3dCmdHeader header; 1055 SVGA3dCmdDefineGBSurface_v3 body; 1056 } *cmd3; 1057 struct { 1058 SVGA3dCmdHeader header; 1059 SVGA3dCmdDefineGBSurface_v4 body; 1060 } *cmd4; 1061 1062 if (likely(res->id != -1)) 1063 return 0; 1064 1065 vmw_fifo_resource_inc(dev_priv); 1066 ret = vmw_resource_alloc_id(res); 1067 if (unlikely(ret != 0)) { 1068 DRM_ERROR("Failed to allocate a surface id.\n"); 1069 goto out_no_id; 1070 } 1071 1072 if (unlikely(res->id >= VMWGFX_NUM_GB_SURFACE)) { 1073 ret = -EBUSY; 1074 goto out_no_fifo; 1075 } 1076 1077 if (has_sm5_context(dev_priv) && metadata->array_size > 0) { 1078 cmd_id = SVGA_3D_CMD_DEFINE_GB_SURFACE_V4; 1079 cmd_len = sizeof(cmd4->body); 1080 submit_len = sizeof(*cmd4); 1081 } else if (has_sm4_1_context(dev_priv) && metadata->array_size > 0) { 1082 cmd_id = SVGA_3D_CMD_DEFINE_GB_SURFACE_V3; 1083 cmd_len = sizeof(cmd3->body); 1084 submit_len = sizeof(*cmd3); 1085 } else if (metadata->array_size > 0) { 1086 /* VMW_SM_4 support verified at creation time. */ 1087 cmd_id = SVGA_3D_CMD_DEFINE_GB_SURFACE_V2; 1088 cmd_len = sizeof(cmd2->body); 1089 submit_len = sizeof(*cmd2); 1090 } else { 1091 cmd_id = SVGA_3D_CMD_DEFINE_GB_SURFACE; 1092 cmd_len = sizeof(cmd->body); 1093 submit_len = sizeof(*cmd); 1094 } 1095 1096 cmd = VMW_CMD_RESERVE(dev_priv, submit_len); 1097 cmd2 = (typeof(cmd2))cmd; 1098 cmd3 = (typeof(cmd3))cmd; 1099 cmd4 = (typeof(cmd4))cmd; 1100 if (unlikely(!cmd)) { 1101 ret = -ENOMEM; 1102 goto out_no_fifo; 1103 } 1104 1105 if (has_sm5_context(dev_priv) && metadata->array_size > 0) { 1106 cmd4->header.id = cmd_id; 1107 cmd4->header.size = cmd_len; 1108 cmd4->body.sid = srf->res.id; 1109 cmd4->body.surfaceFlags = metadata->flags; 1110 cmd4->body.format = metadata->format; 1111 cmd4->body.numMipLevels = metadata->mip_levels[0]; 1112 cmd4->body.multisampleCount = metadata->multisample_count; 1113 cmd4->body.multisamplePattern = metadata->multisample_pattern; 1114 cmd4->body.qualityLevel = metadata->quality_level; 1115 cmd4->body.autogenFilter = metadata->autogen_filter; 1116 cmd4->body.size.width = metadata->base_size.width; 1117 cmd4->body.size.height = metadata->base_size.height; 1118 cmd4->body.size.depth = metadata->base_size.depth; 1119 cmd4->body.arraySize = metadata->array_size; 1120 cmd4->body.bufferByteStride = metadata->buffer_byte_stride; 1121 } else if (has_sm4_1_context(dev_priv) && metadata->array_size > 0) { 1122 cmd3->header.id = cmd_id; 1123 cmd3->header.size = cmd_len; 1124 cmd3->body.sid = srf->res.id; 1125 cmd3->body.surfaceFlags = metadata->flags; 1126 cmd3->body.format = metadata->format; 1127 cmd3->body.numMipLevels = metadata->mip_levels[0]; 1128 cmd3->body.multisampleCount = metadata->multisample_count; 1129 cmd3->body.multisamplePattern = metadata->multisample_pattern; 1130 cmd3->body.qualityLevel = metadata->quality_level; 1131 cmd3->body.autogenFilter = metadata->autogen_filter; 1132 cmd3->body.size.width = metadata->base_size.width; 1133 cmd3->body.size.height = metadata->base_size.height; 1134 cmd3->body.size.depth = metadata->base_size.depth; 1135 cmd3->body.arraySize = metadata->array_size; 1136 } else if (metadata->array_size > 0) { 1137 cmd2->header.id = cmd_id; 1138 cmd2->header.size = cmd_len; 1139 cmd2->body.sid = srf->res.id; 1140 cmd2->body.surfaceFlags = metadata->flags; 1141 cmd2->body.format = metadata->format; 1142 cmd2->body.numMipLevels = metadata->mip_levels[0]; 1143 cmd2->body.multisampleCount = metadata->multisample_count; 1144 cmd2->body.autogenFilter = metadata->autogen_filter; 1145 cmd2->body.size.width = metadata->base_size.width; 1146 cmd2->body.size.height = metadata->base_size.height; 1147 cmd2->body.size.depth = metadata->base_size.depth; 1148 cmd2->body.arraySize = metadata->array_size; 1149 } else { 1150 cmd->header.id = cmd_id; 1151 cmd->header.size = cmd_len; 1152 cmd->body.sid = srf->res.id; 1153 cmd->body.surfaceFlags = metadata->flags; 1154 cmd->body.format = metadata->format; 1155 cmd->body.numMipLevels = metadata->mip_levels[0]; 1156 cmd->body.multisampleCount = metadata->multisample_count; 1157 cmd->body.autogenFilter = metadata->autogen_filter; 1158 cmd->body.size.width = metadata->base_size.width; 1159 cmd->body.size.height = metadata->base_size.height; 1160 cmd->body.size.depth = metadata->base_size.depth; 1161 } 1162 1163 vmw_cmd_commit(dev_priv, submit_len); 1164 1165 return 0; 1166 1167 out_no_fifo: 1168 vmw_resource_release_id(res); 1169 out_no_id: 1170 vmw_fifo_resource_dec(dev_priv); 1171 return ret; 1172 } 1173 1174 1175 static int vmw_gb_surface_bind(struct vmw_resource *res, 1176 struct ttm_validate_buffer *val_buf) 1177 { 1178 struct vmw_private *dev_priv = res->dev_priv; 1179 struct { 1180 SVGA3dCmdHeader header; 1181 SVGA3dCmdBindGBSurface body; 1182 } *cmd1; 1183 struct { 1184 SVGA3dCmdHeader header; 1185 SVGA3dCmdUpdateGBSurface body; 1186 } *cmd2; 1187 uint32_t submit_size; 1188 struct ttm_buffer_object *bo = val_buf->bo; 1189 1190 BUG_ON(bo->resource->mem_type != VMW_PL_MOB); 1191 1192 submit_size = sizeof(*cmd1) + (res->guest_memory_dirty ? sizeof(*cmd2) : 0); 1193 1194 cmd1 = VMW_CMD_RESERVE(dev_priv, submit_size); 1195 if (unlikely(!cmd1)) 1196 return -ENOMEM; 1197 1198 cmd1->header.id = SVGA_3D_CMD_BIND_GB_SURFACE; 1199 cmd1->header.size = sizeof(cmd1->body); 1200 cmd1->body.sid = res->id; 1201 cmd1->body.mobid = bo->resource->start; 1202 if (res->guest_memory_dirty) { 1203 cmd2 = (void *) &cmd1[1]; 1204 cmd2->header.id = SVGA_3D_CMD_UPDATE_GB_SURFACE; 1205 cmd2->header.size = sizeof(cmd2->body); 1206 cmd2->body.sid = res->id; 1207 } 1208 vmw_cmd_commit(dev_priv, submit_size); 1209 1210 if (res->guest_memory_bo->dirty && res->guest_memory_dirty) { 1211 /* We've just made a full upload. Cear dirty regions. */ 1212 vmw_bo_dirty_clear_res(res); 1213 } 1214 1215 res->guest_memory_dirty = false; 1216 1217 return 0; 1218 } 1219 1220 static int vmw_gb_surface_unbind(struct vmw_resource *res, 1221 bool readback, 1222 struct ttm_validate_buffer *val_buf) 1223 { 1224 struct vmw_private *dev_priv = res->dev_priv; 1225 struct ttm_buffer_object *bo = val_buf->bo; 1226 struct vmw_fence_obj *fence; 1227 1228 struct { 1229 SVGA3dCmdHeader header; 1230 SVGA3dCmdReadbackGBSurface body; 1231 } *cmd1; 1232 struct { 1233 SVGA3dCmdHeader header; 1234 SVGA3dCmdInvalidateGBSurface body; 1235 } *cmd2; 1236 struct { 1237 SVGA3dCmdHeader header; 1238 SVGA3dCmdBindGBSurface body; 1239 } *cmd3; 1240 uint32_t submit_size; 1241 uint8_t *cmd; 1242 1243 1244 BUG_ON(bo->resource->mem_type != VMW_PL_MOB); 1245 1246 submit_size = sizeof(*cmd3) + (readback ? sizeof(*cmd1) : sizeof(*cmd2)); 1247 cmd = VMW_CMD_RESERVE(dev_priv, submit_size); 1248 if (unlikely(!cmd)) 1249 return -ENOMEM; 1250 1251 if (readback) { 1252 cmd1 = (void *) cmd; 1253 cmd1->header.id = SVGA_3D_CMD_READBACK_GB_SURFACE; 1254 cmd1->header.size = sizeof(cmd1->body); 1255 cmd1->body.sid = res->id; 1256 cmd3 = (void *) &cmd1[1]; 1257 } else { 1258 cmd2 = (void *) cmd; 1259 cmd2->header.id = SVGA_3D_CMD_INVALIDATE_GB_SURFACE; 1260 cmd2->header.size = sizeof(cmd2->body); 1261 cmd2->body.sid = res->id; 1262 cmd3 = (void *) &cmd2[1]; 1263 } 1264 1265 cmd3->header.id = SVGA_3D_CMD_BIND_GB_SURFACE; 1266 cmd3->header.size = sizeof(cmd3->body); 1267 cmd3->body.sid = res->id; 1268 cmd3->body.mobid = SVGA3D_INVALID_ID; 1269 1270 vmw_cmd_commit(dev_priv, submit_size); 1271 1272 /* 1273 * Create a fence object and fence the backup buffer. 1274 */ 1275 1276 (void) vmw_execbuf_fence_commands(NULL, dev_priv, 1277 &fence, NULL); 1278 1279 vmw_bo_fence_single(val_buf->bo, fence); 1280 1281 if (likely(fence != NULL)) 1282 vmw_fence_obj_unreference(&fence); 1283 1284 return 0; 1285 } 1286 1287 static int vmw_gb_surface_destroy(struct vmw_resource *res) 1288 { 1289 struct vmw_private *dev_priv = res->dev_priv; 1290 struct vmw_surface *srf = vmw_res_to_srf(res); 1291 struct { 1292 SVGA3dCmdHeader header; 1293 SVGA3dCmdDestroyGBSurface body; 1294 } *cmd; 1295 1296 if (likely(res->id == -1)) 1297 return 0; 1298 1299 mutex_lock(&dev_priv->binding_mutex); 1300 vmw_view_surface_list_destroy(dev_priv, &srf->view_list); 1301 vmw_binding_res_list_scrub(&res->binding_head); 1302 1303 cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd)); 1304 if (unlikely(!cmd)) { 1305 mutex_unlock(&dev_priv->binding_mutex); 1306 return -ENOMEM; 1307 } 1308 1309 cmd->header.id = SVGA_3D_CMD_DESTROY_GB_SURFACE; 1310 cmd->header.size = sizeof(cmd->body); 1311 cmd->body.sid = res->id; 1312 vmw_cmd_commit(dev_priv, sizeof(*cmd)); 1313 mutex_unlock(&dev_priv->binding_mutex); 1314 vmw_resource_release_id(res); 1315 vmw_fifo_resource_dec(dev_priv); 1316 1317 return 0; 1318 } 1319 1320 /** 1321 * vmw_gb_surface_define_ioctl - Ioctl function implementing 1322 * the user surface define functionality. 1323 * 1324 * @dev: Pointer to a struct drm_device. 1325 * @data: Pointer to data copied from / to user-space. 1326 * @file_priv: Pointer to a drm file private structure. 1327 */ 1328 int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data, 1329 struct drm_file *file_priv) 1330 { 1331 union drm_vmw_gb_surface_create_arg *arg = 1332 (union drm_vmw_gb_surface_create_arg *)data; 1333 struct drm_vmw_gb_surface_create_rep *rep = &arg->rep; 1334 struct drm_vmw_gb_surface_create_ext_req req_ext; 1335 1336 req_ext.base = arg->req; 1337 req_ext.version = drm_vmw_gb_surface_v1; 1338 req_ext.svga3d_flags_upper_32_bits = 0; 1339 req_ext.multisample_pattern = SVGA3D_MS_PATTERN_NONE; 1340 req_ext.quality_level = SVGA3D_MS_QUALITY_NONE; 1341 req_ext.buffer_byte_stride = 0; 1342 req_ext.must_be_zero = 0; 1343 1344 return vmw_gb_surface_define_internal(dev, &req_ext, rep, file_priv); 1345 } 1346 1347 /** 1348 * vmw_gb_surface_reference_ioctl - Ioctl function implementing 1349 * the user surface reference functionality. 1350 * 1351 * @dev: Pointer to a struct drm_device. 1352 * @data: Pointer to data copied from / to user-space. 1353 * @file_priv: Pointer to a drm file private structure. 1354 */ 1355 int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data, 1356 struct drm_file *file_priv) 1357 { 1358 union drm_vmw_gb_surface_reference_arg *arg = 1359 (union drm_vmw_gb_surface_reference_arg *)data; 1360 struct drm_vmw_surface_arg *req = &arg->req; 1361 struct drm_vmw_gb_surface_ref_rep *rep = &arg->rep; 1362 struct drm_vmw_gb_surface_ref_ext_rep rep_ext; 1363 int ret; 1364 1365 ret = vmw_gb_surface_reference_internal(dev, req, &rep_ext, file_priv); 1366 1367 if (unlikely(ret != 0)) 1368 return ret; 1369 1370 rep->creq = rep_ext.creq.base; 1371 rep->crep = rep_ext.crep; 1372 1373 return ret; 1374 } 1375 1376 /** 1377 * vmw_gb_surface_define_ext_ioctl - Ioctl function implementing 1378 * the user surface define functionality. 1379 * 1380 * @dev: Pointer to a struct drm_device. 1381 * @data: Pointer to data copied from / to user-space. 1382 * @file_priv: Pointer to a drm file private structure. 1383 */ 1384 int vmw_gb_surface_define_ext_ioctl(struct drm_device *dev, void *data, 1385 struct drm_file *file_priv) 1386 { 1387 union drm_vmw_gb_surface_create_ext_arg *arg = 1388 (union drm_vmw_gb_surface_create_ext_arg *)data; 1389 struct drm_vmw_gb_surface_create_ext_req *req = &arg->req; 1390 struct drm_vmw_gb_surface_create_rep *rep = &arg->rep; 1391 1392 return vmw_gb_surface_define_internal(dev, req, rep, file_priv); 1393 } 1394 1395 /** 1396 * vmw_gb_surface_reference_ext_ioctl - Ioctl function implementing 1397 * the user surface reference functionality. 1398 * 1399 * @dev: Pointer to a struct drm_device. 1400 * @data: Pointer to data copied from / to user-space. 1401 * @file_priv: Pointer to a drm file private structure. 1402 */ 1403 int vmw_gb_surface_reference_ext_ioctl(struct drm_device *dev, void *data, 1404 struct drm_file *file_priv) 1405 { 1406 union drm_vmw_gb_surface_reference_ext_arg *arg = 1407 (union drm_vmw_gb_surface_reference_ext_arg *)data; 1408 struct drm_vmw_surface_arg *req = &arg->req; 1409 struct drm_vmw_gb_surface_ref_ext_rep *rep = &arg->rep; 1410 1411 return vmw_gb_surface_reference_internal(dev, req, rep, file_priv); 1412 } 1413 1414 /** 1415 * vmw_gb_surface_define_internal - Ioctl function implementing 1416 * the user surface define functionality. 1417 * 1418 * @dev: Pointer to a struct drm_device. 1419 * @req: Request argument from user-space. 1420 * @rep: Response argument to user-space. 1421 * @file_priv: Pointer to a drm file private structure. 1422 */ 1423 static int 1424 vmw_gb_surface_define_internal(struct drm_device *dev, 1425 struct drm_vmw_gb_surface_create_ext_req *req, 1426 struct drm_vmw_gb_surface_create_rep *rep, 1427 struct drm_file *file_priv) 1428 { 1429 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 1430 struct vmw_private *dev_priv = vmw_priv(dev); 1431 struct vmw_user_surface *user_srf; 1432 struct vmw_surface_metadata metadata = {0}; 1433 struct vmw_surface *srf; 1434 struct vmw_resource *res; 1435 struct vmw_resource *tmp; 1436 int ret = 0; 1437 uint32_t backup_handle = 0; 1438 SVGA3dSurfaceAllFlags svga3d_flags_64 = 1439 SVGA3D_FLAGS_64(req->svga3d_flags_upper_32_bits, 1440 req->base.svga3d_flags); 1441 1442 /* array_size must be null for non-GL3 host. */ 1443 if (req->base.array_size > 0 && !has_sm4_context(dev_priv)) { 1444 VMW_DEBUG_USER("SM4 surface not supported.\n"); 1445 return -EINVAL; 1446 } 1447 1448 if (!has_sm4_1_context(dev_priv)) { 1449 if (req->svga3d_flags_upper_32_bits != 0) 1450 ret = -EINVAL; 1451 1452 if (req->base.multisample_count != 0) 1453 ret = -EINVAL; 1454 1455 if (req->multisample_pattern != SVGA3D_MS_PATTERN_NONE) 1456 ret = -EINVAL; 1457 1458 if (req->quality_level != SVGA3D_MS_QUALITY_NONE) 1459 ret = -EINVAL; 1460 1461 if (ret) { 1462 VMW_DEBUG_USER("SM4.1 surface not supported.\n"); 1463 return ret; 1464 } 1465 } 1466 1467 if (req->buffer_byte_stride > 0 && !has_sm5_context(dev_priv)) { 1468 VMW_DEBUG_USER("SM5 surface not supported.\n"); 1469 return -EINVAL; 1470 } 1471 1472 if ((svga3d_flags_64 & SVGA3D_SURFACE_MULTISAMPLE) && 1473 req->base.multisample_count == 0) { 1474 VMW_DEBUG_USER("Invalid sample count.\n"); 1475 return -EINVAL; 1476 } 1477 1478 if (req->base.mip_levels > DRM_VMW_MAX_MIP_LEVELS) { 1479 VMW_DEBUG_USER("Invalid mip level.\n"); 1480 return -EINVAL; 1481 } 1482 1483 metadata.flags = svga3d_flags_64; 1484 metadata.format = req->base.format; 1485 metadata.mip_levels[0] = req->base.mip_levels; 1486 metadata.multisample_count = req->base.multisample_count; 1487 metadata.multisample_pattern = req->multisample_pattern; 1488 metadata.quality_level = req->quality_level; 1489 metadata.array_size = req->base.array_size; 1490 metadata.buffer_byte_stride = req->buffer_byte_stride; 1491 metadata.num_sizes = 1; 1492 metadata.base_size = req->base.base_size; 1493 metadata.scanout = req->base.drm_surface_flags & 1494 drm_vmw_surface_flag_scanout; 1495 1496 /* Define a surface based on the parameters. */ 1497 ret = vmw_gb_surface_define(dev_priv, &metadata, &srf); 1498 if (ret != 0) { 1499 VMW_DEBUG_USER("Failed to define surface.\n"); 1500 return ret; 1501 } 1502 1503 user_srf = container_of(srf, struct vmw_user_surface, srf); 1504 if (drm_is_primary_client(file_priv)) 1505 user_srf->master = drm_file_get_master(file_priv); 1506 1507 res = &user_srf->srf.res; 1508 1509 if (req->base.buffer_handle != SVGA3D_INVALID_ID) { 1510 ret = vmw_user_bo_lookup(file_priv, req->base.buffer_handle, 1511 &res->guest_memory_bo); 1512 if (ret == 0) { 1513 if (res->guest_memory_bo->tbo.base.size < res->guest_memory_size) { 1514 VMW_DEBUG_USER("Surface backup buffer too small.\n"); 1515 vmw_bo_unreference(&res->guest_memory_bo); 1516 ret = -EINVAL; 1517 goto out_unlock; 1518 } else { 1519 backup_handle = req->base.buffer_handle; 1520 } 1521 } 1522 } else if (req->base.drm_surface_flags & 1523 (drm_vmw_surface_flag_create_buffer | 1524 drm_vmw_surface_flag_coherent)) { 1525 ret = vmw_gem_object_create_with_handle(dev_priv, file_priv, 1526 res->guest_memory_size, 1527 &backup_handle, 1528 &res->guest_memory_bo); 1529 if (ret == 0) 1530 vmw_bo_reference(res->guest_memory_bo); 1531 } 1532 1533 if (unlikely(ret != 0)) { 1534 vmw_resource_unreference(&res); 1535 goto out_unlock; 1536 } 1537 1538 if (req->base.drm_surface_flags & drm_vmw_surface_flag_coherent) { 1539 struct vmw_bo *backup = res->guest_memory_bo; 1540 1541 ttm_bo_reserve(&backup->tbo, false, false, NULL); 1542 if (!res->func->dirty_alloc) 1543 ret = -EINVAL; 1544 if (!ret) 1545 ret = vmw_bo_dirty_add(backup); 1546 if (!ret) { 1547 res->coherent = true; 1548 ret = res->func->dirty_alloc(res); 1549 } 1550 ttm_bo_unreserve(&backup->tbo); 1551 if (ret) { 1552 vmw_resource_unreference(&res); 1553 goto out_unlock; 1554 } 1555 1556 } 1557 1558 tmp = vmw_resource_reference(res); 1559 ret = ttm_prime_object_init(tfile, res->guest_memory_size, &user_srf->prime, 1560 req->base.drm_surface_flags & 1561 drm_vmw_surface_flag_shareable, 1562 VMW_RES_SURFACE, 1563 &vmw_user_surface_base_release); 1564 1565 if (unlikely(ret != 0)) { 1566 vmw_resource_unreference(&tmp); 1567 vmw_resource_unreference(&res); 1568 goto out_unlock; 1569 } 1570 1571 rep->handle = user_srf->prime.base.handle; 1572 rep->backup_size = res->guest_memory_size; 1573 if (res->guest_memory_bo) { 1574 rep->buffer_map_handle = 1575 drm_vma_node_offset_addr(&res->guest_memory_bo->tbo.base.vma_node); 1576 rep->buffer_size = res->guest_memory_bo->tbo.base.size; 1577 rep->buffer_handle = backup_handle; 1578 } else { 1579 rep->buffer_map_handle = 0; 1580 rep->buffer_size = 0; 1581 rep->buffer_handle = SVGA3D_INVALID_ID; 1582 } 1583 vmw_resource_unreference(&res); 1584 1585 out_unlock: 1586 return ret; 1587 } 1588 1589 /** 1590 * vmw_gb_surface_reference_internal - Ioctl function implementing 1591 * the user surface reference functionality. 1592 * 1593 * @dev: Pointer to a struct drm_device. 1594 * @req: Pointer to user-space request surface arg. 1595 * @rep: Pointer to response to user-space. 1596 * @file_priv: Pointer to a drm file private structure. 1597 */ 1598 static int 1599 vmw_gb_surface_reference_internal(struct drm_device *dev, 1600 struct drm_vmw_surface_arg *req, 1601 struct drm_vmw_gb_surface_ref_ext_rep *rep, 1602 struct drm_file *file_priv) 1603 { 1604 struct vmw_private *dev_priv = vmw_priv(dev); 1605 struct vmw_surface *srf; 1606 struct vmw_user_surface *user_srf; 1607 struct vmw_surface_metadata *metadata; 1608 struct ttm_base_object *base; 1609 u32 backup_handle; 1610 int ret; 1611 1612 ret = vmw_surface_handle_reference(dev_priv, file_priv, req->sid, 1613 req->handle_type, &base); 1614 if (unlikely(ret != 0)) 1615 return ret; 1616 1617 user_srf = container_of(base, struct vmw_user_surface, prime.base); 1618 srf = &user_srf->srf; 1619 if (!srf->res.guest_memory_bo) { 1620 DRM_ERROR("Shared GB surface is missing a backup buffer.\n"); 1621 goto out_bad_resource; 1622 } 1623 metadata = &srf->metadata; 1624 1625 mutex_lock(&dev_priv->cmdbuf_mutex); /* Protect res->backup */ 1626 ret = drm_gem_handle_create(file_priv, &srf->res.guest_memory_bo->tbo.base, 1627 &backup_handle); 1628 mutex_unlock(&dev_priv->cmdbuf_mutex); 1629 if (ret != 0) { 1630 drm_err(dev, "Wasn't able to create a backing handle for surface sid = %u.\n", 1631 req->sid); 1632 goto out_bad_resource; 1633 } 1634 1635 rep->creq.base.svga3d_flags = SVGA3D_FLAGS_LOWER_32(metadata->flags); 1636 rep->creq.base.format = metadata->format; 1637 rep->creq.base.mip_levels = metadata->mip_levels[0]; 1638 rep->creq.base.drm_surface_flags = 0; 1639 rep->creq.base.multisample_count = metadata->multisample_count; 1640 rep->creq.base.autogen_filter = metadata->autogen_filter; 1641 rep->creq.base.array_size = metadata->array_size; 1642 rep->creq.base.buffer_handle = backup_handle; 1643 rep->creq.base.base_size = metadata->base_size; 1644 rep->crep.handle = user_srf->prime.base.handle; 1645 rep->crep.backup_size = srf->res.guest_memory_size; 1646 rep->crep.buffer_handle = backup_handle; 1647 rep->crep.buffer_map_handle = 1648 drm_vma_node_offset_addr(&srf->res.guest_memory_bo->tbo.base.vma_node); 1649 rep->crep.buffer_size = srf->res.guest_memory_bo->tbo.base.size; 1650 1651 rep->creq.version = drm_vmw_gb_surface_v1; 1652 rep->creq.svga3d_flags_upper_32_bits = 1653 SVGA3D_FLAGS_UPPER_32(metadata->flags); 1654 rep->creq.multisample_pattern = metadata->multisample_pattern; 1655 rep->creq.quality_level = metadata->quality_level; 1656 rep->creq.must_be_zero = 0; 1657 1658 out_bad_resource: 1659 ttm_base_object_unref(&base); 1660 1661 return ret; 1662 } 1663 1664 /** 1665 * vmw_subres_dirty_add - Add a dirty region to a subresource 1666 * @dirty: The surfaces's dirty tracker. 1667 * @loc_start: The location corresponding to the start of the region. 1668 * @loc_end: The location corresponding to the end of the region. 1669 * 1670 * As we are assuming that @loc_start and @loc_end represent a sequential 1671 * range of backing store memory, if the region spans multiple lines then 1672 * regardless of the x coordinate, the full lines are dirtied. 1673 * Correspondingly if the region spans multiple z slices, then full rather 1674 * than partial z slices are dirtied. 1675 */ 1676 static void vmw_subres_dirty_add(struct vmw_surface_dirty *dirty, 1677 const struct vmw_surface_loc *loc_start, 1678 const struct vmw_surface_loc *loc_end) 1679 { 1680 const struct vmw_surface_cache *cache = &dirty->cache; 1681 SVGA3dBox *box = &dirty->boxes[loc_start->sub_resource]; 1682 u32 mip = loc_start->sub_resource % cache->num_mip_levels; 1683 const struct drm_vmw_size *size = &cache->mip[mip].size; 1684 u32 box_c2 = box->z + box->d; 1685 1686 if (WARN_ON(loc_start->sub_resource >= dirty->num_subres)) 1687 return; 1688 1689 if (box->d == 0 || box->z > loc_start->z) 1690 box->z = loc_start->z; 1691 if (box_c2 < loc_end->z) 1692 box->d = loc_end->z - box->z; 1693 1694 if (loc_start->z + 1 == loc_end->z) { 1695 box_c2 = box->y + box->h; 1696 if (box->h == 0 || box->y > loc_start->y) 1697 box->y = loc_start->y; 1698 if (box_c2 < loc_end->y) 1699 box->h = loc_end->y - box->y; 1700 1701 if (loc_start->y + 1 == loc_end->y) { 1702 box_c2 = box->x + box->w; 1703 if (box->w == 0 || box->x > loc_start->x) 1704 box->x = loc_start->x; 1705 if (box_c2 < loc_end->x) 1706 box->w = loc_end->x - box->x; 1707 } else { 1708 box->x = 0; 1709 box->w = size->width; 1710 } 1711 } else { 1712 box->y = 0; 1713 box->h = size->height; 1714 box->x = 0; 1715 box->w = size->width; 1716 } 1717 } 1718 1719 /** 1720 * vmw_subres_dirty_full - Mark a full subresource as dirty 1721 * @dirty: The surface's dirty tracker. 1722 * @subres: The subresource 1723 */ 1724 static void vmw_subres_dirty_full(struct vmw_surface_dirty *dirty, u32 subres) 1725 { 1726 const struct vmw_surface_cache *cache = &dirty->cache; 1727 u32 mip = subres % cache->num_mip_levels; 1728 const struct drm_vmw_size *size = &cache->mip[mip].size; 1729 SVGA3dBox *box = &dirty->boxes[subres]; 1730 1731 box->x = 0; 1732 box->y = 0; 1733 box->z = 0; 1734 box->w = size->width; 1735 box->h = size->height; 1736 box->d = size->depth; 1737 } 1738 1739 /* 1740 * vmw_surface_tex_dirty_add_range - The dirty_add_range callback for texture 1741 * surfaces. 1742 */ 1743 static void vmw_surface_tex_dirty_range_add(struct vmw_resource *res, 1744 size_t start, size_t end) 1745 { 1746 struct vmw_surface_dirty *dirty = 1747 (struct vmw_surface_dirty *) res->dirty; 1748 size_t backup_end = res->guest_memory_offset + res->guest_memory_size; 1749 struct vmw_surface_loc loc1, loc2; 1750 const struct vmw_surface_cache *cache; 1751 1752 start = max_t(size_t, start, res->guest_memory_offset) - res->guest_memory_offset; 1753 end = min(end, backup_end) - res->guest_memory_offset; 1754 cache = &dirty->cache; 1755 vmw_surface_get_loc(cache, &loc1, start); 1756 vmw_surface_get_loc(cache, &loc2, end - 1); 1757 vmw_surface_inc_loc(cache, &loc2); 1758 1759 if (loc1.sheet != loc2.sheet) { 1760 u32 sub_res; 1761 1762 /* 1763 * Multiple multisample sheets. To do this in an optimized 1764 * fashion, compute the dirty region for each sheet and the 1765 * resulting union. Since this is not a common case, just dirty 1766 * the whole surface. 1767 */ 1768 for (sub_res = 0; sub_res < dirty->num_subres; ++sub_res) 1769 vmw_subres_dirty_full(dirty, sub_res); 1770 return; 1771 } 1772 if (loc1.sub_resource + 1 == loc2.sub_resource) { 1773 /* Dirty range covers a single sub-resource */ 1774 vmw_subres_dirty_add(dirty, &loc1, &loc2); 1775 } else { 1776 /* Dirty range covers multiple sub-resources */ 1777 struct vmw_surface_loc loc_min, loc_max; 1778 u32 sub_res; 1779 1780 vmw_surface_max_loc(cache, loc1.sub_resource, &loc_max); 1781 vmw_subres_dirty_add(dirty, &loc1, &loc_max); 1782 vmw_surface_min_loc(cache, loc2.sub_resource - 1, &loc_min); 1783 vmw_subres_dirty_add(dirty, &loc_min, &loc2); 1784 for (sub_res = loc1.sub_resource + 1; 1785 sub_res < loc2.sub_resource - 1; ++sub_res) 1786 vmw_subres_dirty_full(dirty, sub_res); 1787 } 1788 } 1789 1790 /* 1791 * vmw_surface_tex_dirty_add_range - The dirty_add_range callback for buffer 1792 * surfaces. 1793 */ 1794 static void vmw_surface_buf_dirty_range_add(struct vmw_resource *res, 1795 size_t start, size_t end) 1796 { 1797 struct vmw_surface_dirty *dirty = 1798 (struct vmw_surface_dirty *) res->dirty; 1799 const struct vmw_surface_cache *cache = &dirty->cache; 1800 size_t backup_end = res->guest_memory_offset + cache->mip_chain_bytes; 1801 SVGA3dBox *box = &dirty->boxes[0]; 1802 u32 box_c2; 1803 1804 box->h = box->d = 1; 1805 start = max_t(size_t, start, res->guest_memory_offset) - res->guest_memory_offset; 1806 end = min(end, backup_end) - res->guest_memory_offset; 1807 box_c2 = box->x + box->w; 1808 if (box->w == 0 || box->x > start) 1809 box->x = start; 1810 if (box_c2 < end) 1811 box->w = end - box->x; 1812 } 1813 1814 /* 1815 * vmw_surface_tex_dirty_add_range - The dirty_add_range callback for surfaces 1816 */ 1817 static void vmw_surface_dirty_range_add(struct vmw_resource *res, size_t start, 1818 size_t end) 1819 { 1820 struct vmw_surface *srf = vmw_res_to_srf(res); 1821 1822 if (WARN_ON(end <= res->guest_memory_offset || 1823 start >= res->guest_memory_offset + res->guest_memory_size)) 1824 return; 1825 1826 if (srf->metadata.format == SVGA3D_BUFFER) 1827 vmw_surface_buf_dirty_range_add(res, start, end); 1828 else 1829 vmw_surface_tex_dirty_range_add(res, start, end); 1830 } 1831 1832 /* 1833 * vmw_surface_dirty_sync - The surface's dirty_sync callback. 1834 */ 1835 static int vmw_surface_dirty_sync(struct vmw_resource *res) 1836 { 1837 struct vmw_private *dev_priv = res->dev_priv; 1838 u32 i, num_dirty; 1839 struct vmw_surface_dirty *dirty = 1840 (struct vmw_surface_dirty *) res->dirty; 1841 size_t alloc_size; 1842 const struct vmw_surface_cache *cache = &dirty->cache; 1843 struct { 1844 SVGA3dCmdHeader header; 1845 SVGA3dCmdDXUpdateSubResource body; 1846 } *cmd1; 1847 struct { 1848 SVGA3dCmdHeader header; 1849 SVGA3dCmdUpdateGBImage body; 1850 } *cmd2; 1851 void *cmd; 1852 1853 num_dirty = 0; 1854 for (i = 0; i < dirty->num_subres; ++i) { 1855 const SVGA3dBox *box = &dirty->boxes[i]; 1856 1857 if (box->d) 1858 num_dirty++; 1859 } 1860 1861 if (!num_dirty) 1862 goto out; 1863 1864 alloc_size = num_dirty * ((has_sm4_context(dev_priv)) ? sizeof(*cmd1) : sizeof(*cmd2)); 1865 cmd = VMW_CMD_RESERVE(dev_priv, alloc_size); 1866 if (!cmd) 1867 return -ENOMEM; 1868 1869 cmd1 = cmd; 1870 cmd2 = cmd; 1871 1872 for (i = 0; i < dirty->num_subres; ++i) { 1873 const SVGA3dBox *box = &dirty->boxes[i]; 1874 1875 if (!box->d) 1876 continue; 1877 1878 /* 1879 * DX_UPDATE_SUBRESOURCE is aware of array surfaces. 1880 * UPDATE_GB_IMAGE is not. 1881 */ 1882 if (has_sm4_context(dev_priv)) { 1883 cmd1->header.id = SVGA_3D_CMD_DX_UPDATE_SUBRESOURCE; 1884 cmd1->header.size = sizeof(cmd1->body); 1885 cmd1->body.sid = res->id; 1886 cmd1->body.subResource = i; 1887 cmd1->body.box = *box; 1888 cmd1++; 1889 } else { 1890 cmd2->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE; 1891 cmd2->header.size = sizeof(cmd2->body); 1892 cmd2->body.image.sid = res->id; 1893 cmd2->body.image.face = i / cache->num_mip_levels; 1894 cmd2->body.image.mipmap = i - 1895 (cache->num_mip_levels * cmd2->body.image.face); 1896 cmd2->body.box = *box; 1897 cmd2++; 1898 } 1899 1900 } 1901 vmw_cmd_commit(dev_priv, alloc_size); 1902 out: 1903 memset(&dirty->boxes[0], 0, sizeof(dirty->boxes[0]) * 1904 dirty->num_subres); 1905 1906 return 0; 1907 } 1908 1909 /* 1910 * vmw_surface_dirty_alloc - The surface's dirty_alloc callback. 1911 */ 1912 static int vmw_surface_dirty_alloc(struct vmw_resource *res) 1913 { 1914 struct vmw_surface *srf = vmw_res_to_srf(res); 1915 const struct vmw_surface_metadata *metadata = &srf->metadata; 1916 struct vmw_surface_dirty *dirty; 1917 u32 num_layers = 1; 1918 u32 num_mip; 1919 u32 num_subres; 1920 u32 num_samples; 1921 size_t dirty_size; 1922 int ret; 1923 1924 if (metadata->array_size) 1925 num_layers = metadata->array_size; 1926 else if (metadata->flags & SVGA3D_SURFACE_CUBEMAP) 1927 num_layers *= SVGA3D_MAX_SURFACE_FACES; 1928 1929 num_mip = metadata->mip_levels[0]; 1930 if (!num_mip) 1931 num_mip = 1; 1932 1933 num_subres = num_layers * num_mip; 1934 dirty_size = struct_size(dirty, boxes, num_subres); 1935 1936 dirty = kvzalloc(dirty_size, GFP_KERNEL); 1937 if (!dirty) { 1938 ret = -ENOMEM; 1939 goto out_no_dirty; 1940 } 1941 1942 num_samples = max_t(u32, 1, metadata->multisample_count); 1943 ret = vmw_surface_setup_cache(&metadata->base_size, metadata->format, 1944 num_mip, num_layers, num_samples, 1945 &dirty->cache); 1946 if (ret) 1947 goto out_no_cache; 1948 1949 dirty->num_subres = num_subres; 1950 res->dirty = (struct vmw_resource_dirty *) dirty; 1951 1952 return 0; 1953 1954 out_no_cache: 1955 kvfree(dirty); 1956 out_no_dirty: 1957 return ret; 1958 } 1959 1960 /* 1961 * vmw_surface_dirty_free - The surface's dirty_free callback 1962 */ 1963 static void vmw_surface_dirty_free(struct vmw_resource *res) 1964 { 1965 struct vmw_surface_dirty *dirty = 1966 (struct vmw_surface_dirty *) res->dirty; 1967 1968 kvfree(dirty); 1969 res->dirty = NULL; 1970 } 1971 1972 /* 1973 * vmw_surface_clean - The surface's clean callback 1974 */ 1975 static int vmw_surface_clean(struct vmw_resource *res) 1976 { 1977 struct vmw_private *dev_priv = res->dev_priv; 1978 size_t alloc_size; 1979 struct { 1980 SVGA3dCmdHeader header; 1981 SVGA3dCmdReadbackGBSurface body; 1982 } *cmd; 1983 1984 alloc_size = sizeof(*cmd); 1985 cmd = VMW_CMD_RESERVE(dev_priv, alloc_size); 1986 if (!cmd) 1987 return -ENOMEM; 1988 1989 cmd->header.id = SVGA_3D_CMD_READBACK_GB_SURFACE; 1990 cmd->header.size = sizeof(cmd->body); 1991 cmd->body.sid = res->id; 1992 vmw_cmd_commit(dev_priv, alloc_size); 1993 1994 return 0; 1995 } 1996 1997 /* 1998 * vmw_gb_surface_define - Define a private GB surface 1999 * 2000 * @dev_priv: Pointer to a device private. 2001 * @metadata: Metadata representing the surface to create. 2002 * @user_srf_out: allocated user_srf. Set to NULL on failure. 2003 * 2004 * GB surfaces allocated by this function will not have a user mode handle, and 2005 * thus will only be visible to vmwgfx. For optimization reasons the 2006 * surface may later be given a user mode handle by another function to make 2007 * it available to user mode drivers. 2008 */ 2009 int vmw_gb_surface_define(struct vmw_private *dev_priv, 2010 const struct vmw_surface_metadata *req, 2011 struct vmw_surface **srf_out) 2012 { 2013 struct vmw_surface_metadata *metadata; 2014 struct vmw_user_surface *user_srf; 2015 struct vmw_surface *srf; 2016 u32 sample_count = 1; 2017 u32 num_layers = 1; 2018 int ret; 2019 2020 *srf_out = NULL; 2021 2022 if (req->scanout) { 2023 if (!vmw_surface_is_screen_target_format(req->format)) { 2024 VMW_DEBUG_USER("Invalid Screen Target surface format."); 2025 return -EINVAL; 2026 } 2027 2028 if (req->base_size.width > dev_priv->texture_max_width || 2029 req->base_size.height > dev_priv->texture_max_height) { 2030 VMW_DEBUG_USER("%ux%u\n, exceed max surface size %ux%u", 2031 req->base_size.width, 2032 req->base_size.height, 2033 dev_priv->texture_max_width, 2034 dev_priv->texture_max_height); 2035 return -EINVAL; 2036 } 2037 } else { 2038 const SVGA3dSurfaceDesc *desc = 2039 vmw_surface_get_desc(req->format); 2040 2041 if (desc->blockDesc == SVGA3DBLOCKDESC_NONE) { 2042 VMW_DEBUG_USER("Invalid surface format.\n"); 2043 return -EINVAL; 2044 } 2045 } 2046 2047 if (req->autogen_filter != SVGA3D_TEX_FILTER_NONE) 2048 return -EINVAL; 2049 2050 if (req->num_sizes != 1) 2051 return -EINVAL; 2052 2053 if (req->sizes != NULL) 2054 return -EINVAL; 2055 2056 user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL); 2057 if (unlikely(!user_srf)) { 2058 ret = -ENOMEM; 2059 goto out_unlock; 2060 } 2061 2062 *srf_out = &user_srf->srf; 2063 user_srf->prime.base.shareable = false; 2064 user_srf->prime.base.tfile = NULL; 2065 2066 srf = &user_srf->srf; 2067 srf->metadata = *req; 2068 srf->offsets = NULL; 2069 2070 metadata = &srf->metadata; 2071 2072 if (metadata->array_size) 2073 num_layers = req->array_size; 2074 else if (metadata->flags & SVGA3D_SURFACE_CUBEMAP) 2075 num_layers = SVGA3D_MAX_SURFACE_FACES; 2076 2077 if (metadata->flags & SVGA3D_SURFACE_MULTISAMPLE) 2078 sample_count = metadata->multisample_count; 2079 2080 srf->res.guest_memory_size = 2081 vmw_surface_get_serialized_size_extended( 2082 metadata->format, 2083 metadata->base_size, 2084 metadata->mip_levels[0], 2085 num_layers, 2086 sample_count); 2087 2088 if (metadata->flags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT) 2089 srf->res.guest_memory_size += sizeof(SVGA3dDXSOState); 2090 2091 /* 2092 * Don't set SVGA3D_SURFACE_SCREENTARGET flag for a scanout surface with 2093 * size greater than STDU max width/height. This is really a workaround 2094 * to support creation of big framebuffer requested by some user-space 2095 * for whole topology. That big framebuffer won't really be used for 2096 * binding with screen target as during prepare_fb a separate surface is 2097 * created so it's safe to ignore SVGA3D_SURFACE_SCREENTARGET flag. 2098 */ 2099 if (dev_priv->active_display_unit == vmw_du_screen_target && 2100 metadata->scanout && 2101 metadata->base_size.width <= dev_priv->stdu_max_width && 2102 metadata->base_size.height <= dev_priv->stdu_max_height) 2103 metadata->flags |= SVGA3D_SURFACE_SCREENTARGET; 2104 2105 /* 2106 * From this point, the generic resource management functions 2107 * destroy the object on failure. 2108 */ 2109 ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free); 2110 2111 return ret; 2112 2113 out_unlock: 2114 return ret; 2115 } 2116