1 // SPDX-License-Identifier: GPL-2.0 OR MIT
2 /**************************************************************************
4 * Copyright 2009-2015 VMware, Inc., Palo Alto, CA., USA
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
28 #include <drm/ttm/ttm_placement.h>
30 #include "vmwgfx_drv.h"
31 #include "vmwgfx_resource_priv.h"
32 #include "vmwgfx_binding.h"
34 struct vmw_user_context {
35 struct ttm_base_object base;
36 struct vmw_resource res;
37 struct vmw_ctx_binding_state *cbs;
38 struct vmw_cmdbuf_res_manager *man;
39 struct vmw_resource *cotables[SVGA_COTABLE_DX10_MAX];
40 spinlock_t cotable_lock;
41 struct vmw_buffer_object *dx_query_mob;
44 static void vmw_user_context_free(struct vmw_resource *res);
45 static struct vmw_resource *
46 vmw_user_context_base_to_res(struct ttm_base_object *base);
48 static int vmw_gb_context_create(struct vmw_resource *res);
49 static int vmw_gb_context_bind(struct vmw_resource *res,
50 struct ttm_validate_buffer *val_buf);
51 static int vmw_gb_context_unbind(struct vmw_resource *res,
53 struct ttm_validate_buffer *val_buf);
54 static int vmw_gb_context_destroy(struct vmw_resource *res);
55 static int vmw_dx_context_create(struct vmw_resource *res);
56 static int vmw_dx_context_bind(struct vmw_resource *res,
57 struct ttm_validate_buffer *val_buf);
58 static int vmw_dx_context_unbind(struct vmw_resource *res,
60 struct ttm_validate_buffer *val_buf);
61 static int vmw_dx_context_destroy(struct vmw_resource *res);
63 static uint64_t vmw_user_context_size;
65 static const struct vmw_user_resource_conv user_context_conv = {
66 .object_type = VMW_RES_CONTEXT,
67 .base_obj_to_res = vmw_user_context_base_to_res,
68 .res_free = vmw_user_context_free
71 const struct vmw_user_resource_conv *user_context_converter =
75 static const struct vmw_res_func vmw_legacy_context_func = {
76 .res_type = vmw_res_context,
77 .needs_backup = false,
79 .type_name = "legacy contexts",
80 .backup_placement = NULL,
87 static const struct vmw_res_func vmw_gb_context_func = {
88 .res_type = vmw_res_context,
91 .type_name = "guest backed contexts",
92 .backup_placement = &vmw_mob_placement,
93 .create = vmw_gb_context_create,
94 .destroy = vmw_gb_context_destroy,
95 .bind = vmw_gb_context_bind,
96 .unbind = vmw_gb_context_unbind
99 static const struct vmw_res_func vmw_dx_context_func = {
100 .res_type = vmw_res_dx_context,
101 .needs_backup = true,
103 .type_name = "dx contexts",
104 .backup_placement = &vmw_mob_placement,
105 .create = vmw_dx_context_create,
106 .destroy = vmw_dx_context_destroy,
107 .bind = vmw_dx_context_bind,
108 .unbind = vmw_dx_context_unbind
112 * Context management:
115 static void vmw_context_cotables_unref(struct vmw_user_context *uctx)
117 struct vmw_resource *res;
120 for (i = 0; i < SVGA_COTABLE_DX10_MAX; ++i) {
121 spin_lock(&uctx->cotable_lock);
122 res = uctx->cotables[i];
123 uctx->cotables[i] = NULL;
124 spin_unlock(&uctx->cotable_lock);
127 vmw_resource_unreference(&res);
131 static void vmw_hw_context_destroy(struct vmw_resource *res)
133 struct vmw_user_context *uctx =
134 container_of(res, struct vmw_user_context, res);
135 struct vmw_private *dev_priv = res->dev_priv;
137 SVGA3dCmdHeader header;
138 SVGA3dCmdDestroyContext body;
142 if (res->func->destroy == vmw_gb_context_destroy ||
143 res->func->destroy == vmw_dx_context_destroy) {
144 mutex_lock(&dev_priv->cmdbuf_mutex);
145 vmw_cmdbuf_res_man_destroy(uctx->man);
146 mutex_lock(&dev_priv->binding_mutex);
147 vmw_binding_state_kill(uctx->cbs);
148 (void) res->func->destroy(res);
149 mutex_unlock(&dev_priv->binding_mutex);
150 if (dev_priv->pinned_bo != NULL &&
151 !dev_priv->query_cid_valid)
152 __vmw_execbuf_release_pinned_bo(dev_priv, NULL);
153 mutex_unlock(&dev_priv->cmdbuf_mutex);
154 vmw_context_cotables_unref(uctx);
158 vmw_execbuf_release_pinned_bo(dev_priv);
159 cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
160 if (unlikely(cmd == NULL))
163 cmd->header.id = SVGA_3D_CMD_CONTEXT_DESTROY;
164 cmd->header.size = sizeof(cmd->body);
165 cmd->body.cid = res->id;
167 vmw_fifo_commit(dev_priv, sizeof(*cmd));
168 vmw_fifo_resource_dec(dev_priv);
171 static int vmw_gb_context_init(struct vmw_private *dev_priv,
173 struct vmw_resource *res,
174 void (*res_free)(struct vmw_resource *res))
177 struct vmw_user_context *uctx =
178 container_of(res, struct vmw_user_context, res);
180 res->backup_size = (dx ? sizeof(SVGADXContextMobFormat) :
181 SVGA3D_CONTEXT_DATA_SIZE);
182 ret = vmw_resource_init(dev_priv, res, true,
184 dx ? &vmw_dx_context_func :
185 &vmw_gb_context_func);
186 if (unlikely(ret != 0))
189 if (dev_priv->has_mob) {
190 uctx->man = vmw_cmdbuf_res_man_create(dev_priv);
191 if (IS_ERR(uctx->man)) {
192 ret = PTR_ERR(uctx->man);
198 uctx->cbs = vmw_binding_state_alloc(dev_priv);
199 if (IS_ERR(uctx->cbs)) {
200 ret = PTR_ERR(uctx->cbs);
204 spin_lock_init(&uctx->cotable_lock);
207 for (i = 0; i < SVGA_COTABLE_DX10_MAX; ++i) {
208 uctx->cotables[i] = vmw_cotable_alloc(dev_priv,
210 if (IS_ERR(uctx->cotables[i])) {
211 ret = PTR_ERR(uctx->cotables[i]);
217 res->hw_destroy = vmw_hw_context_destroy;
221 vmw_context_cotables_unref(uctx);
230 static int vmw_context_init(struct vmw_private *dev_priv,
231 struct vmw_resource *res,
232 void (*res_free)(struct vmw_resource *res),
238 SVGA3dCmdHeader header;
239 SVGA3dCmdDefineContext body;
242 if (dev_priv->has_mob)
243 return vmw_gb_context_init(dev_priv, dx, res, res_free);
245 ret = vmw_resource_init(dev_priv, res, false,
246 res_free, &vmw_legacy_context_func);
248 if (unlikely(ret != 0)) {
249 DRM_ERROR("Failed to allocate a resource id.\n");
253 if (unlikely(res->id >= SVGA3D_MAX_CONTEXT_IDS)) {
254 DRM_ERROR("Out of hw context ids.\n");
255 vmw_resource_unreference(&res);
259 cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
260 if (unlikely(cmd == NULL)) {
261 vmw_resource_unreference(&res);
265 cmd->header.id = SVGA_3D_CMD_CONTEXT_DEFINE;
266 cmd->header.size = sizeof(cmd->body);
267 cmd->body.cid = res->id;
269 vmw_fifo_commit(dev_priv, sizeof(*cmd));
270 vmw_fifo_resource_inc(dev_priv);
271 res->hw_destroy = vmw_hw_context_destroy;
275 if (res_free == NULL)
287 static int vmw_gb_context_create(struct vmw_resource *res)
289 struct vmw_private *dev_priv = res->dev_priv;
292 SVGA3dCmdHeader header;
293 SVGA3dCmdDefineGBContext body;
296 if (likely(res->id != -1))
299 ret = vmw_resource_alloc_id(res);
300 if (unlikely(ret != 0)) {
301 DRM_ERROR("Failed to allocate a context id.\n");
305 if (unlikely(res->id >= VMWGFX_NUM_GB_CONTEXT)) {
310 cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
311 if (unlikely(cmd == NULL)) {
316 cmd->header.id = SVGA_3D_CMD_DEFINE_GB_CONTEXT;
317 cmd->header.size = sizeof(cmd->body);
318 cmd->body.cid = res->id;
319 vmw_fifo_commit(dev_priv, sizeof(*cmd));
320 vmw_fifo_resource_inc(dev_priv);
325 vmw_resource_release_id(res);
330 static int vmw_gb_context_bind(struct vmw_resource *res,
331 struct ttm_validate_buffer *val_buf)
333 struct vmw_private *dev_priv = res->dev_priv;
335 SVGA3dCmdHeader header;
336 SVGA3dCmdBindGBContext body;
338 struct ttm_buffer_object *bo = val_buf->bo;
340 BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
342 cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
343 if (unlikely(cmd == NULL))
346 cmd->header.id = SVGA_3D_CMD_BIND_GB_CONTEXT;
347 cmd->header.size = sizeof(cmd->body);
348 cmd->body.cid = res->id;
349 cmd->body.mobid = bo->mem.start;
350 cmd->body.validContents = res->backup_dirty;
351 res->backup_dirty = false;
352 vmw_fifo_commit(dev_priv, sizeof(*cmd));
357 static int vmw_gb_context_unbind(struct vmw_resource *res,
359 struct ttm_validate_buffer *val_buf)
361 struct vmw_private *dev_priv = res->dev_priv;
362 struct ttm_buffer_object *bo = val_buf->bo;
363 struct vmw_fence_obj *fence;
364 struct vmw_user_context *uctx =
365 container_of(res, struct vmw_user_context, res);
368 SVGA3dCmdHeader header;
369 SVGA3dCmdReadbackGBContext body;
372 SVGA3dCmdHeader header;
373 SVGA3dCmdBindGBContext body;
375 uint32_t submit_size;
379 BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
381 mutex_lock(&dev_priv->binding_mutex);
382 vmw_binding_state_scrub(uctx->cbs);
384 submit_size = sizeof(*cmd2) + (readback ? sizeof(*cmd1) : 0);
386 cmd = VMW_FIFO_RESERVE(dev_priv, submit_size);
387 if (unlikely(cmd == NULL)) {
388 mutex_unlock(&dev_priv->binding_mutex);
395 cmd1->header.id = SVGA_3D_CMD_READBACK_GB_CONTEXT;
396 cmd1->header.size = sizeof(cmd1->body);
397 cmd1->body.cid = res->id;
398 cmd2 = (void *) (&cmd1[1]);
400 cmd2->header.id = SVGA_3D_CMD_BIND_GB_CONTEXT;
401 cmd2->header.size = sizeof(cmd2->body);
402 cmd2->body.cid = res->id;
403 cmd2->body.mobid = SVGA3D_INVALID_ID;
405 vmw_fifo_commit(dev_priv, submit_size);
406 mutex_unlock(&dev_priv->binding_mutex);
409 * Create a fence object and fence the backup buffer.
412 (void) vmw_execbuf_fence_commands(NULL, dev_priv,
415 vmw_bo_fence_single(bo, fence);
417 if (likely(fence != NULL))
418 vmw_fence_obj_unreference(&fence);
423 static int vmw_gb_context_destroy(struct vmw_resource *res)
425 struct vmw_private *dev_priv = res->dev_priv;
427 SVGA3dCmdHeader header;
428 SVGA3dCmdDestroyGBContext body;
431 if (likely(res->id == -1))
434 cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
435 if (unlikely(cmd == NULL))
438 cmd->header.id = SVGA_3D_CMD_DESTROY_GB_CONTEXT;
439 cmd->header.size = sizeof(cmd->body);
440 cmd->body.cid = res->id;
441 vmw_fifo_commit(dev_priv, sizeof(*cmd));
442 if (dev_priv->query_cid == res->id)
443 dev_priv->query_cid_valid = false;
444 vmw_resource_release_id(res);
445 vmw_fifo_resource_dec(dev_priv);
454 static int vmw_dx_context_create(struct vmw_resource *res)
456 struct vmw_private *dev_priv = res->dev_priv;
459 SVGA3dCmdHeader header;
460 SVGA3dCmdDXDefineContext body;
463 if (likely(res->id != -1))
466 ret = vmw_resource_alloc_id(res);
467 if (unlikely(ret != 0)) {
468 DRM_ERROR("Failed to allocate a context id.\n");
472 if (unlikely(res->id >= VMWGFX_NUM_DXCONTEXT)) {
477 cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
478 if (unlikely(cmd == NULL)) {
483 cmd->header.id = SVGA_3D_CMD_DX_DEFINE_CONTEXT;
484 cmd->header.size = sizeof(cmd->body);
485 cmd->body.cid = res->id;
486 vmw_fifo_commit(dev_priv, sizeof(*cmd));
487 vmw_fifo_resource_inc(dev_priv);
492 vmw_resource_release_id(res);
497 static int vmw_dx_context_bind(struct vmw_resource *res,
498 struct ttm_validate_buffer *val_buf)
500 struct vmw_private *dev_priv = res->dev_priv;
502 SVGA3dCmdHeader header;
503 SVGA3dCmdDXBindContext body;
505 struct ttm_buffer_object *bo = val_buf->bo;
507 BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
509 cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
510 if (unlikely(cmd == NULL))
513 cmd->header.id = SVGA_3D_CMD_DX_BIND_CONTEXT;
514 cmd->header.size = sizeof(cmd->body);
515 cmd->body.cid = res->id;
516 cmd->body.mobid = bo->mem.start;
517 cmd->body.validContents = res->backup_dirty;
518 res->backup_dirty = false;
519 vmw_fifo_commit(dev_priv, sizeof(*cmd));
526 * vmw_dx_context_scrub_cotables - Scrub all bindings and
527 * cotables from a context
529 * @ctx: Pointer to the context resource
530 * @readback: Whether to save the otable contents on scrubbing.
532 * COtables must be unbound before their context, but unbinding requires
533 * the backup buffer being reserved, whereas scrubbing does not.
534 * This function scrubs all cotables of a context, potentially reading back
535 * the contents into their backup buffers. However, scrubbing cotables
536 * also makes the device context invalid, so scrub all bindings first so
537 * that doesn't have to be done later with an invalid context.
539 void vmw_dx_context_scrub_cotables(struct vmw_resource *ctx,
542 struct vmw_user_context *uctx =
543 container_of(ctx, struct vmw_user_context, res);
546 vmw_binding_state_scrub(uctx->cbs);
547 for (i = 0; i < SVGA_COTABLE_DX10_MAX; ++i) {
548 struct vmw_resource *res;
550 /* Avoid racing with ongoing cotable destruction. */
551 spin_lock(&uctx->cotable_lock);
552 res = uctx->cotables[vmw_cotable_scrub_order[i]];
554 res = vmw_resource_reference_unless_doomed(res);
555 spin_unlock(&uctx->cotable_lock);
559 WARN_ON(vmw_cotable_scrub(res, readback));
560 vmw_resource_unreference(&res);
564 static int vmw_dx_context_unbind(struct vmw_resource *res,
566 struct ttm_validate_buffer *val_buf)
568 struct vmw_private *dev_priv = res->dev_priv;
569 struct ttm_buffer_object *bo = val_buf->bo;
570 struct vmw_fence_obj *fence;
571 struct vmw_user_context *uctx =
572 container_of(res, struct vmw_user_context, res);
575 SVGA3dCmdHeader header;
576 SVGA3dCmdDXReadbackContext body;
579 SVGA3dCmdHeader header;
580 SVGA3dCmdDXBindContext body;
582 uint32_t submit_size;
586 BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
588 mutex_lock(&dev_priv->binding_mutex);
589 vmw_dx_context_scrub_cotables(res, readback);
591 if (uctx->dx_query_mob && uctx->dx_query_mob->dx_query_ctx &&
593 WARN_ON(uctx->dx_query_mob->dx_query_ctx != res);
594 if (vmw_query_readback_all(uctx->dx_query_mob))
595 DRM_ERROR("Failed to read back query states\n");
598 submit_size = sizeof(*cmd2) + (readback ? sizeof(*cmd1) : 0);
600 cmd = VMW_FIFO_RESERVE(dev_priv, submit_size);
601 if (unlikely(cmd == NULL)) {
602 mutex_unlock(&dev_priv->binding_mutex);
609 cmd1->header.id = SVGA_3D_CMD_DX_READBACK_CONTEXT;
610 cmd1->header.size = sizeof(cmd1->body);
611 cmd1->body.cid = res->id;
612 cmd2 = (void *) (&cmd1[1]);
614 cmd2->header.id = SVGA_3D_CMD_DX_BIND_CONTEXT;
615 cmd2->header.size = sizeof(cmd2->body);
616 cmd2->body.cid = res->id;
617 cmd2->body.mobid = SVGA3D_INVALID_ID;
619 vmw_fifo_commit(dev_priv, submit_size);
620 mutex_unlock(&dev_priv->binding_mutex);
623 * Create a fence object and fence the backup buffer.
626 (void) vmw_execbuf_fence_commands(NULL, dev_priv,
629 vmw_bo_fence_single(bo, fence);
631 if (likely(fence != NULL))
632 vmw_fence_obj_unreference(&fence);
637 static int vmw_dx_context_destroy(struct vmw_resource *res)
639 struct vmw_private *dev_priv = res->dev_priv;
641 SVGA3dCmdHeader header;
642 SVGA3dCmdDXDestroyContext body;
645 if (likely(res->id == -1))
648 cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
649 if (unlikely(cmd == NULL))
652 cmd->header.id = SVGA_3D_CMD_DX_DESTROY_CONTEXT;
653 cmd->header.size = sizeof(cmd->body);
654 cmd->body.cid = res->id;
655 vmw_fifo_commit(dev_priv, sizeof(*cmd));
656 if (dev_priv->query_cid == res->id)
657 dev_priv->query_cid_valid = false;
658 vmw_resource_release_id(res);
659 vmw_fifo_resource_dec(dev_priv);
665 * User-space context management:
668 static struct vmw_resource *
669 vmw_user_context_base_to_res(struct ttm_base_object *base)
671 return &(container_of(base, struct vmw_user_context, base)->res);
674 static void vmw_user_context_free(struct vmw_resource *res)
676 struct vmw_user_context *ctx =
677 container_of(res, struct vmw_user_context, res);
678 struct vmw_private *dev_priv = res->dev_priv;
681 vmw_binding_state_free(ctx->cbs);
683 (void) vmw_context_bind_dx_query(res, NULL);
685 ttm_base_object_kfree(ctx, base);
686 ttm_mem_global_free(vmw_mem_glob(dev_priv),
687 vmw_user_context_size);
691 * This function is called when user space has no more references on the
692 * base object. It releases the base-object's reference on the resource object.
695 static void vmw_user_context_base_release(struct ttm_base_object **p_base)
697 struct ttm_base_object *base = *p_base;
698 struct vmw_user_context *ctx =
699 container_of(base, struct vmw_user_context, base);
700 struct vmw_resource *res = &ctx->res;
703 vmw_resource_unreference(&res);
706 int vmw_context_destroy_ioctl(struct drm_device *dev, void *data,
707 struct drm_file *file_priv)
709 struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data;
710 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
712 return ttm_ref_object_base_unref(tfile, arg->cid, TTM_REF_USAGE);
715 static int vmw_context_define(struct drm_device *dev, void *data,
716 struct drm_file *file_priv, bool dx)
718 struct vmw_private *dev_priv = vmw_priv(dev);
719 struct vmw_user_context *ctx;
720 struct vmw_resource *res;
721 struct vmw_resource *tmp;
722 struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data;
723 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
724 struct ttm_operation_ctx ttm_opt_ctx = {
725 .interruptible = true,
730 if (!dev_priv->has_dx && dx) {
731 VMW_DEBUG_USER("DX contexts not supported by device.\n");
735 if (unlikely(vmw_user_context_size == 0))
736 vmw_user_context_size = ttm_round_pot(sizeof(*ctx)) +
737 ((dev_priv->has_mob) ? vmw_cmdbuf_res_man_size() : 0) +
738 + VMW_IDA_ACC_SIZE + TTM_OBJ_EXTRA_SIZE;
740 ret = ttm_read_lock(&dev_priv->reservation_sem, true);
741 if (unlikely(ret != 0))
744 ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
745 vmw_user_context_size,
747 if (unlikely(ret != 0)) {
748 if (ret != -ERESTARTSYS)
749 DRM_ERROR("Out of graphics memory for context"
754 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
755 if (unlikely(!ctx)) {
756 ttm_mem_global_free(vmw_mem_glob(dev_priv),
757 vmw_user_context_size);
763 ctx->base.shareable = false;
764 ctx->base.tfile = NULL;
767 * From here on, the destructor takes over resource freeing.
770 ret = vmw_context_init(dev_priv, res, vmw_user_context_free, dx);
771 if (unlikely(ret != 0))
774 tmp = vmw_resource_reference(&ctx->res);
775 ret = ttm_base_object_init(tfile, &ctx->base, false, VMW_RES_CONTEXT,
776 &vmw_user_context_base_release, NULL);
778 if (unlikely(ret != 0)) {
779 vmw_resource_unreference(&tmp);
783 arg->cid = ctx->base.handle;
785 vmw_resource_unreference(&res);
787 ttm_read_unlock(&dev_priv->reservation_sem);
791 int vmw_context_define_ioctl(struct drm_device *dev, void *data,
792 struct drm_file *file_priv)
794 return vmw_context_define(dev, data, file_priv, false);
797 int vmw_extended_context_define_ioctl(struct drm_device *dev, void *data,
798 struct drm_file *file_priv)
800 union drm_vmw_extended_context_arg *arg = (typeof(arg)) data;
801 struct drm_vmw_context_arg *rep = &arg->rep;
804 case drm_vmw_context_legacy:
805 return vmw_context_define(dev, rep, file_priv, false);
806 case drm_vmw_context_dx:
807 return vmw_context_define(dev, rep, file_priv, true);
815 * vmw_context_binding_list - Return a list of context bindings
817 * @ctx: The context resource
819 * Returns the current list of bindings of the given context. Note that
820 * this list becomes stale as soon as the dev_priv::binding_mutex is unlocked.
822 struct list_head *vmw_context_binding_list(struct vmw_resource *ctx)
824 struct vmw_user_context *uctx =
825 container_of(ctx, struct vmw_user_context, res);
827 return vmw_binding_state_list(uctx->cbs);
830 struct vmw_cmdbuf_res_manager *vmw_context_res_man(struct vmw_resource *ctx)
832 return container_of(ctx, struct vmw_user_context, res)->man;
835 struct vmw_resource *vmw_context_cotable(struct vmw_resource *ctx,
836 SVGACOTableType cotable_type)
838 if (cotable_type >= SVGA_COTABLE_DX10_MAX)
839 return ERR_PTR(-EINVAL);
841 return container_of(ctx, struct vmw_user_context, res)->
842 cotables[cotable_type];
846 * vmw_context_binding_state -
847 * Return a pointer to a context binding state structure
849 * @ctx: The context resource
851 * Returns the current state of bindings of the given context. Note that
852 * this state becomes stale as soon as the dev_priv::binding_mutex is unlocked.
854 struct vmw_ctx_binding_state *
855 vmw_context_binding_state(struct vmw_resource *ctx)
857 return container_of(ctx, struct vmw_user_context, res)->cbs;
861 * vmw_context_bind_dx_query -
862 * Sets query MOB for the context. If @mob is NULL, then this function will
863 * remove the association between the MOB and the context. This function
864 * assumes the binding_mutex is held.
866 * @ctx_res: The context resource
867 * @mob: a reference to the query MOB
869 * Returns -EINVAL if a MOB has already been set and does not match the one
870 * specified in the parameter. 0 otherwise.
872 int vmw_context_bind_dx_query(struct vmw_resource *ctx_res,
873 struct vmw_buffer_object *mob)
875 struct vmw_user_context *uctx =
876 container_of(ctx_res, struct vmw_user_context, res);
879 if (uctx->dx_query_mob) {
880 uctx->dx_query_mob->dx_query_ctx = NULL;
881 vmw_bo_unreference(&uctx->dx_query_mob);
882 uctx->dx_query_mob = NULL;
888 /* Can only have one MOB per context for queries */
889 if (uctx->dx_query_mob && uctx->dx_query_mob != mob)
892 mob->dx_query_ctx = ctx_res;
894 if (!uctx->dx_query_mob)
895 uctx->dx_query_mob = vmw_bo_reference(mob);
901 * vmw_context_get_dx_query_mob - Returns non-counted reference to DX query mob
903 * @ctx_res: The context resource
905 struct vmw_buffer_object *
906 vmw_context_get_dx_query_mob(struct vmw_resource *ctx_res)
908 struct vmw_user_context *uctx =
909 container_of(ctx_res, struct vmw_user_context, res);
911 return uctx->dx_query_mob;