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