123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661 |
- /**************************************************************************
- *
- * Copyright © 2014-2015 VMware, Inc., Palo Alto, CA., USA
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
- /*
- * Treat context OTables as resources to make use of the resource
- * backing MOB eviction mechanism, that is used to read back the COTable
- * whenever the backing MOB is evicted.
- */
- #include "vmwgfx_drv.h"
- #include "vmwgfx_resource_priv.h"
- #include <ttm/ttm_placement.h>
- #include "vmwgfx_so.h"
- /**
- * struct vmw_cotable - Context Object Table resource
- *
- * @res: struct vmw_resource we are deriving from.
- * @ctx: non-refcounted pointer to the owning context.
- * @size_read_back: Size of data read back during eviction.
- * @seen_entries: Seen entries in command stream for this cotable.
- * @type: The cotable type.
- * @scrubbed: Whether the cotable has been scrubbed.
- * @resource_list: List of resources in the cotable.
- */
- struct vmw_cotable {
- struct vmw_resource res;
- struct vmw_resource *ctx;
- size_t size_read_back;
- int seen_entries;
- u32 type;
- bool scrubbed;
- struct list_head resource_list;
- };
- /**
- * struct vmw_cotable_info - Static info about cotable types
- *
- * @min_initial_entries: Min number of initial intries at cotable allocation
- * for this cotable type.
- * @size: Size of each entry.
- */
- struct vmw_cotable_info {
- u32 min_initial_entries;
- u32 size;
- void (*unbind_func)(struct vmw_private *, struct list_head *,
- bool);
- };
- static const struct vmw_cotable_info co_info[] = {
- {1, sizeof(SVGACOTableDXRTViewEntry), &vmw_view_cotable_list_destroy},
- {1, sizeof(SVGACOTableDXDSViewEntry), &vmw_view_cotable_list_destroy},
- {1, sizeof(SVGACOTableDXSRViewEntry), &vmw_view_cotable_list_destroy},
- {1, sizeof(SVGACOTableDXElementLayoutEntry), NULL},
- {1, sizeof(SVGACOTableDXBlendStateEntry), NULL},
- {1, sizeof(SVGACOTableDXDepthStencilEntry), NULL},
- {1, sizeof(SVGACOTableDXRasterizerStateEntry), NULL},
- {1, sizeof(SVGACOTableDXSamplerEntry), NULL},
- {1, sizeof(SVGACOTableDXStreamOutputEntry), NULL},
- {1, sizeof(SVGACOTableDXQueryEntry), NULL},
- {1, sizeof(SVGACOTableDXShaderEntry), &vmw_dx_shader_cotable_list_scrub}
- };
- /*
- * Cotables with bindings that we remove must be scrubbed first,
- * otherwise, the device will swap in an invalid context when we remove
- * bindings before scrubbing a cotable...
- */
- const SVGACOTableType vmw_cotable_scrub_order[] = {
- SVGA_COTABLE_RTVIEW,
- SVGA_COTABLE_DSVIEW,
- SVGA_COTABLE_SRVIEW,
- SVGA_COTABLE_DXSHADER,
- SVGA_COTABLE_ELEMENTLAYOUT,
- SVGA_COTABLE_BLENDSTATE,
- SVGA_COTABLE_DEPTHSTENCIL,
- SVGA_COTABLE_RASTERIZERSTATE,
- SVGA_COTABLE_SAMPLER,
- SVGA_COTABLE_STREAMOUTPUT,
- SVGA_COTABLE_DXQUERY,
- };
- static int vmw_cotable_bind(struct vmw_resource *res,
- struct ttm_validate_buffer *val_buf);
- static int vmw_cotable_unbind(struct vmw_resource *res,
- bool readback,
- struct ttm_validate_buffer *val_buf);
- static int vmw_cotable_create(struct vmw_resource *res);
- static int vmw_cotable_destroy(struct vmw_resource *res);
- static const struct vmw_res_func vmw_cotable_func = {
- .res_type = vmw_res_cotable,
- .needs_backup = true,
- .may_evict = true,
- .type_name = "context guest backed object tables",
- .backup_placement = &vmw_mob_placement,
- .create = vmw_cotable_create,
- .destroy = vmw_cotable_destroy,
- .bind = vmw_cotable_bind,
- .unbind = vmw_cotable_unbind,
- };
- /**
- * vmw_cotable - Convert a struct vmw_resource pointer to a struct
- * vmw_cotable pointer
- *
- * @res: Pointer to the resource.
- */
- static struct vmw_cotable *vmw_cotable(struct vmw_resource *res)
- {
- return container_of(res, struct vmw_cotable, res);
- }
- /**
- * vmw_cotable_destroy - Cotable resource destroy callback
- *
- * @res: Pointer to the cotable resource.
- *
- * There is no device cotable destroy command, so this function only
- * makes sure that the resource id is set to invalid.
- */
- static int vmw_cotable_destroy(struct vmw_resource *res)
- {
- res->id = -1;
- return 0;
- }
- /**
- * vmw_cotable_unscrub - Undo a cotable unscrub operation
- *
- * @res: Pointer to the cotable resource
- *
- * This function issues commands to (re)bind the cotable to
- * its backing mob, which needs to be validated and reserved at this point.
- * This is identical to bind() except the function interface looks different.
- */
- static int vmw_cotable_unscrub(struct vmw_resource *res)
- {
- struct vmw_cotable *vcotbl = vmw_cotable(res);
- struct vmw_private *dev_priv = res->dev_priv;
- struct ttm_buffer_object *bo = &res->backup->base;
- struct {
- SVGA3dCmdHeader header;
- SVGA3dCmdDXSetCOTable body;
- } *cmd;
- WARN_ON_ONCE(bo->mem.mem_type != VMW_PL_MOB);
- lockdep_assert_held(&bo->resv->lock.base);
- cmd = vmw_fifo_reserve_dx(dev_priv, sizeof(*cmd), SVGA3D_INVALID_ID);
- if (!cmd) {
- DRM_ERROR("Failed reserving FIFO space for cotable "
- "binding.\n");
- return -ENOMEM;
- }
- WARN_ON(vcotbl->ctx->id == SVGA3D_INVALID_ID);
- WARN_ON(bo->mem.mem_type != VMW_PL_MOB);
- cmd->header.id = SVGA_3D_CMD_DX_SET_COTABLE;
- cmd->header.size = sizeof(cmd->body);
- cmd->body.cid = vcotbl->ctx->id;
- cmd->body.type = vcotbl->type;
- cmd->body.mobid = bo->mem.start;
- cmd->body.validSizeInBytes = vcotbl->size_read_back;
- vmw_fifo_commit_flush(dev_priv, sizeof(*cmd));
- vcotbl->scrubbed = false;
- return 0;
- }
- /**
- * vmw_cotable_bind - Undo a cotable unscrub operation
- *
- * @res: Pointer to the cotable resource
- * @val_buf: Pointer to a struct ttm_validate_buffer prepared by the caller
- * for convenience / fencing.
- *
- * This function issues commands to (re)bind the cotable to
- * its backing mob, which needs to be validated and reserved at this point.
- */
- static int vmw_cotable_bind(struct vmw_resource *res,
- struct ttm_validate_buffer *val_buf)
- {
- /*
- * The create() callback may have changed @res->backup without
- * the caller noticing, and with val_buf->bo still pointing to
- * the old backup buffer. Although hackish, and not used currently,
- * take the opportunity to correct the value here so that it's not
- * misused in the future.
- */
- val_buf->bo = &res->backup->base;
- return vmw_cotable_unscrub(res);
- }
- /**
- * vmw_cotable_scrub - Scrub the cotable from the device.
- *
- * @res: Pointer to the cotable resource.
- * @readback: Whether initiate a readback of the cotable data to the backup
- * buffer.
- *
- * In some situations (context swapouts) it might be desirable to make the
- * device forget about the cotable without performing a full unbind. A full
- * unbind requires reserved backup buffers and it might not be possible to
- * reserve them due to locking order violation issues. The vmw_cotable_scrub
- * function implements a partial unbind() without that requirement but with the
- * following restrictions.
- * 1) Before the cotable is again used by the GPU, vmw_cotable_unscrub() must
- * be called.
- * 2) Before the cotable backing buffer is used by the CPU, or during the
- * resource destruction, vmw_cotable_unbind() must be called.
- */
- int vmw_cotable_scrub(struct vmw_resource *res, bool readback)
- {
- struct vmw_cotable *vcotbl = vmw_cotable(res);
- struct vmw_private *dev_priv = res->dev_priv;
- size_t submit_size;
- struct {
- SVGA3dCmdHeader header;
- SVGA3dCmdDXReadbackCOTable body;
- } *cmd0;
- struct {
- SVGA3dCmdHeader header;
- SVGA3dCmdDXSetCOTable body;
- } *cmd1;
- if (vcotbl->scrubbed)
- return 0;
- if (co_info[vcotbl->type].unbind_func)
- co_info[vcotbl->type].unbind_func(dev_priv,
- &vcotbl->resource_list,
- readback);
- submit_size = sizeof(*cmd1);
- if (readback)
- submit_size += sizeof(*cmd0);
- cmd1 = vmw_fifo_reserve_dx(dev_priv, submit_size, SVGA3D_INVALID_ID);
- if (!cmd1) {
- DRM_ERROR("Failed reserving FIFO space for cotable "
- "unbinding.\n");
- return -ENOMEM;
- }
- vcotbl->size_read_back = 0;
- if (readback) {
- cmd0 = (void *) cmd1;
- cmd0->header.id = SVGA_3D_CMD_DX_READBACK_COTABLE;
- cmd0->header.size = sizeof(cmd0->body);
- cmd0->body.cid = vcotbl->ctx->id;
- cmd0->body.type = vcotbl->type;
- cmd1 = (void *) &cmd0[1];
- vcotbl->size_read_back = res->backup_size;
- }
- cmd1->header.id = SVGA_3D_CMD_DX_SET_COTABLE;
- cmd1->header.size = sizeof(cmd1->body);
- cmd1->body.cid = vcotbl->ctx->id;
- cmd1->body.type = vcotbl->type;
- cmd1->body.mobid = SVGA3D_INVALID_ID;
- cmd1->body.validSizeInBytes = 0;
- vmw_fifo_commit_flush(dev_priv, submit_size);
- vcotbl->scrubbed = true;
- /* Trigger a create() on next validate. */
- res->id = -1;
- return 0;
- }
- /**
- * vmw_cotable_unbind - Cotable resource unbind callback
- *
- * @res: Pointer to the cotable resource.
- * @readback: Whether to read back cotable data to the backup buffer.
- * val_buf: Pointer to a struct ttm_validate_buffer prepared by the caller
- * for convenience / fencing.
- *
- * Unbinds the cotable from the device and fences the backup buffer.
- */
- static int vmw_cotable_unbind(struct vmw_resource *res,
- bool readback,
- struct ttm_validate_buffer *val_buf)
- {
- struct vmw_cotable *vcotbl = vmw_cotable(res);
- struct vmw_private *dev_priv = res->dev_priv;
- struct ttm_buffer_object *bo = val_buf->bo;
- struct vmw_fence_obj *fence;
- if (list_empty(&res->mob_head))
- return 0;
- WARN_ON_ONCE(bo->mem.mem_type != VMW_PL_MOB);
- lockdep_assert_held(&bo->resv->lock.base);
- mutex_lock(&dev_priv->binding_mutex);
- if (!vcotbl->scrubbed)
- vmw_dx_context_scrub_cotables(vcotbl->ctx, readback);
- mutex_unlock(&dev_priv->binding_mutex);
- (void) vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL);
- vmw_fence_single_bo(bo, fence);
- if (likely(fence != NULL))
- vmw_fence_obj_unreference(&fence);
- return 0;
- }
- /**
- * vmw_cotable_readback - Read back a cotable without unbinding.
- *
- * @res: The cotable resource.
- *
- * Reads back a cotable to its backing mob without scrubbing the MOB from
- * the cotable. The MOB is fenced for subsequent CPU access.
- */
- static int vmw_cotable_readback(struct vmw_resource *res)
- {
- struct vmw_cotable *vcotbl = vmw_cotable(res);
- struct vmw_private *dev_priv = res->dev_priv;
- struct {
- SVGA3dCmdHeader header;
- SVGA3dCmdDXReadbackCOTable body;
- } *cmd;
- struct vmw_fence_obj *fence;
- if (!vcotbl->scrubbed) {
- cmd = vmw_fifo_reserve_dx(dev_priv, sizeof(*cmd),
- SVGA3D_INVALID_ID);
- if (!cmd) {
- DRM_ERROR("Failed reserving FIFO space for cotable "
- "readback.\n");
- return -ENOMEM;
- }
- cmd->header.id = SVGA_3D_CMD_DX_READBACK_COTABLE;
- cmd->header.size = sizeof(cmd->body);
- cmd->body.cid = vcotbl->ctx->id;
- cmd->body.type = vcotbl->type;
- vcotbl->size_read_back = res->backup_size;
- vmw_fifo_commit(dev_priv, sizeof(*cmd));
- }
- (void) vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL);
- vmw_fence_single_bo(&res->backup->base, fence);
- vmw_fence_obj_unreference(&fence);
- return 0;
- }
- /**
- * vmw_cotable_resize - Resize a cotable.
- *
- * @res: The cotable resource.
- * @new_size: The new size.
- *
- * Resizes a cotable and binds the new backup buffer.
- * On failure the cotable is left intact.
- * Important! This function may not fail once the MOB switch has been
- * committed to hardware. That would put the device context in an
- * invalid state which we can't currently recover from.
- */
- static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size)
- {
- struct vmw_private *dev_priv = res->dev_priv;
- struct vmw_cotable *vcotbl = vmw_cotable(res);
- struct vmw_dma_buffer *buf, *old_buf = res->backup;
- struct ttm_buffer_object *bo, *old_bo = &res->backup->base;
- size_t old_size = res->backup_size;
- size_t old_size_read_back = vcotbl->size_read_back;
- size_t cur_size_read_back;
- struct ttm_bo_kmap_obj old_map, new_map;
- int ret;
- size_t i;
- ret = vmw_cotable_readback(res);
- if (ret)
- return ret;
- cur_size_read_back = vcotbl->size_read_back;
- vcotbl->size_read_back = old_size_read_back;
- /*
- * While device is processing, Allocate and reserve a buffer object
- * for the new COTable. Initially pin the buffer object to make sure
- * we can use tryreserve without failure.
- */
- buf = kzalloc(sizeof(*buf), GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
- ret = vmw_dmabuf_init(dev_priv, buf, new_size, &vmw_mob_ne_placement,
- true, vmw_dmabuf_bo_free);
- if (ret) {
- DRM_ERROR("Failed initializing new cotable MOB.\n");
- return ret;
- }
- bo = &buf->base;
- WARN_ON_ONCE(ttm_bo_reserve(bo, false, true, false, NULL));
- ret = ttm_bo_wait(old_bo, false, false, false);
- if (unlikely(ret != 0)) {
- DRM_ERROR("Failed waiting for cotable unbind.\n");
- goto out_wait;
- }
- /*
- * Do a page by page copy of COTables. This eliminates slow vmap()s.
- * This should really be a TTM utility.
- */
- for (i = 0; i < old_bo->num_pages; ++i) {
- bool dummy;
- ret = ttm_bo_kmap(old_bo, i, 1, &old_map);
- if (unlikely(ret != 0)) {
- DRM_ERROR("Failed mapping old COTable on resize.\n");
- goto out_wait;
- }
- ret = ttm_bo_kmap(bo, i, 1, &new_map);
- if (unlikely(ret != 0)) {
- DRM_ERROR("Failed mapping new COTable on resize.\n");
- goto out_map_new;
- }
- memcpy(ttm_kmap_obj_virtual(&new_map, &dummy),
- ttm_kmap_obj_virtual(&old_map, &dummy),
- PAGE_SIZE);
- ttm_bo_kunmap(&new_map);
- ttm_bo_kunmap(&old_map);
- }
- /* Unpin new buffer, and switch backup buffers. */
- ret = ttm_bo_validate(bo, &vmw_mob_placement, false, false);
- if (unlikely(ret != 0)) {
- DRM_ERROR("Failed validating new COTable backup buffer.\n");
- goto out_wait;
- }
- res->backup = buf;
- res->backup_size = new_size;
- vcotbl->size_read_back = cur_size_read_back;
- /*
- * Now tell the device to switch. If this fails, then we need to
- * revert the full resize.
- */
- ret = vmw_cotable_unscrub(res);
- if (ret) {
- DRM_ERROR("Failed switching COTable backup buffer.\n");
- res->backup = old_buf;
- res->backup_size = old_size;
- vcotbl->size_read_back = old_size_read_back;
- goto out_wait;
- }
- /* Let go of the old mob. */
- list_del(&res->mob_head);
- list_add_tail(&res->mob_head, &buf->res_list);
- vmw_dmabuf_unreference(&old_buf);
- res->id = vcotbl->type;
- return 0;
- out_map_new:
- ttm_bo_kunmap(&old_map);
- out_wait:
- ttm_bo_unreserve(bo);
- vmw_dmabuf_unreference(&buf);
- return ret;
- }
- /**
- * vmw_cotable_create - Cotable resource create callback
- *
- * @res: Pointer to a cotable resource.
- *
- * There is no separate create command for cotables, so this callback, which
- * is called before bind() in the validation sequence is instead used for two
- * things.
- * 1) Unscrub the cotable if it is scrubbed and still attached to a backup
- * buffer, that is, if @res->mob_head is non-empty.
- * 2) Resize the cotable if needed.
- */
- static int vmw_cotable_create(struct vmw_resource *res)
- {
- struct vmw_cotable *vcotbl = vmw_cotable(res);
- size_t new_size = res->backup_size;
- size_t needed_size;
- int ret;
- /* Check whether we need to resize the cotable */
- needed_size = (vcotbl->seen_entries + 1) * co_info[vcotbl->type].size;
- while (needed_size > new_size)
- new_size *= 2;
- if (likely(new_size <= res->backup_size)) {
- if (vcotbl->scrubbed && !list_empty(&res->mob_head)) {
- ret = vmw_cotable_unscrub(res);
- if (ret)
- return ret;
- }
- res->id = vcotbl->type;
- return 0;
- }
- return vmw_cotable_resize(res, new_size);
- }
- /**
- * vmw_hw_cotable_destroy - Cotable hw_destroy callback
- *
- * @res: Pointer to a cotable resource.
- *
- * The final (part of resource destruction) destroy callback.
- */
- static void vmw_hw_cotable_destroy(struct vmw_resource *res)
- {
- (void) vmw_cotable_destroy(res);
- }
- static size_t cotable_acc_size;
- /**
- * vmw_cotable_free - Cotable resource destructor
- *
- * @res: Pointer to a cotable resource.
- */
- static void vmw_cotable_free(struct vmw_resource *res)
- {
- struct vmw_private *dev_priv = res->dev_priv;
- kfree(res);
- ttm_mem_global_free(vmw_mem_glob(dev_priv), cotable_acc_size);
- }
- /**
- * vmw_cotable_alloc - Create a cotable resource
- *
- * @dev_priv: Pointer to a device private struct.
- * @ctx: Pointer to the context resource.
- * The cotable resource will not add a refcount.
- * @type: The cotable type.
- */
- struct vmw_resource *vmw_cotable_alloc(struct vmw_private *dev_priv,
- struct vmw_resource *ctx,
- u32 type)
- {
- struct vmw_cotable *vcotbl;
- int ret;
- u32 num_entries;
- if (unlikely(cotable_acc_size == 0))
- cotable_acc_size = ttm_round_pot(sizeof(struct vmw_cotable));
- ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
- cotable_acc_size, false, true);
- if (unlikely(ret))
- return ERR_PTR(ret);
- vcotbl = kzalloc(sizeof(*vcotbl), GFP_KERNEL);
- if (unlikely(vcotbl == NULL)) {
- ret = -ENOMEM;
- goto out_no_alloc;
- }
- ret = vmw_resource_init(dev_priv, &vcotbl->res, true,
- vmw_cotable_free, &vmw_cotable_func);
- if (unlikely(ret != 0))
- goto out_no_init;
- INIT_LIST_HEAD(&vcotbl->resource_list);
- vcotbl->res.id = type;
- vcotbl->res.backup_size = PAGE_SIZE;
- num_entries = PAGE_SIZE / co_info[type].size;
- if (num_entries < co_info[type].min_initial_entries) {
- vcotbl->res.backup_size = co_info[type].min_initial_entries *
- co_info[type].size;
- vcotbl->res.backup_size =
- (vcotbl->res.backup_size + PAGE_SIZE - 1) & PAGE_MASK;
- }
- vcotbl->scrubbed = true;
- vcotbl->seen_entries = -1;
- vcotbl->type = type;
- vcotbl->ctx = ctx;
- vmw_resource_activate(&vcotbl->res, vmw_hw_cotable_destroy);
- return &vcotbl->res;
- out_no_init:
- kfree(vcotbl);
- out_no_alloc:
- ttm_mem_global_free(vmw_mem_glob(dev_priv), cotable_acc_size);
- return ERR_PTR(ret);
- }
- /**
- * vmw_cotable_notify - Notify the cotable about an item creation
- *
- * @res: Pointer to a cotable resource.
- * @id: Item id.
- */
- int vmw_cotable_notify(struct vmw_resource *res, int id)
- {
- struct vmw_cotable *vcotbl = vmw_cotable(res);
- if (id < 0 || id >= SVGA_COTABLE_MAX_IDS) {
- DRM_ERROR("Illegal COTable id. Type is %u. Id is %d\n",
- (unsigned) vcotbl->type, id);
- return -EINVAL;
- }
- if (vcotbl->seen_entries < id) {
- /* Trigger a call to create() on next validate */
- res->id = -1;
- vcotbl->seen_entries = id;
- }
- return 0;
- }
- /**
- * vmw_cotable_add_view - add a view to the cotable's list of active views.
- *
- * @res: pointer struct vmw_resource representing the cotable.
- * @head: pointer to the struct list_head member of the resource, dedicated
- * to the cotable active resource list.
- */
- void vmw_cotable_add_resource(struct vmw_resource *res, struct list_head *head)
- {
- struct vmw_cotable *vcotbl =
- container_of(res, struct vmw_cotable, res);
- list_add_tail(head, &vcotbl->resource_list);
- }
|