18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 OR MIT 28c2ecf20Sopenharmony_ci/************************************************************************** 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright © 2018-2019 VMware, Inc., Palo Alto, CA., USA 58c2ecf20Sopenharmony_ci * All Rights Reserved. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 88c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the 98c2ecf20Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 108c2ecf20Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 118c2ecf20Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 128c2ecf20Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 138c2ecf20Sopenharmony_ci * the following conditions: 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice (including the 168c2ecf20Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 178c2ecf20Sopenharmony_ci * of the Software. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 208c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 218c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 228c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 238c2ecf20Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 248c2ecf20Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 258c2ecf20Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 268c2ecf20Sopenharmony_ci * 278c2ecf20Sopenharmony_ci **************************************************************************/ 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#include <drm/ttm/ttm_placement.h> 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#include "vmwgfx_drv.h" 328c2ecf20Sopenharmony_ci#include "vmwgfx_resource_priv.h" 338c2ecf20Sopenharmony_ci#include "vmwgfx_binding.h" 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci/** 368c2ecf20Sopenharmony_ci * struct vmw_dx_streamoutput - Streamoutput resource metadata. 378c2ecf20Sopenharmony_ci * @res: Base resource struct. 388c2ecf20Sopenharmony_ci * @ctx: Non-refcounted context to which @res belong. 398c2ecf20Sopenharmony_ci * @cotable: Refcounted cotable holding this Streamoutput. 408c2ecf20Sopenharmony_ci * @cotable_head: List head for cotable-so_res list. 418c2ecf20Sopenharmony_ci * @id: User-space provided identifier. 428c2ecf20Sopenharmony_ci * @size: User-space provided mob size. 438c2ecf20Sopenharmony_ci * @committed: Whether streamoutput is actually created or pending creation. 448c2ecf20Sopenharmony_ci */ 458c2ecf20Sopenharmony_cistruct vmw_dx_streamoutput { 468c2ecf20Sopenharmony_ci struct vmw_resource res; 478c2ecf20Sopenharmony_ci struct vmw_resource *ctx; 488c2ecf20Sopenharmony_ci struct vmw_resource *cotable; 498c2ecf20Sopenharmony_ci struct list_head cotable_head; 508c2ecf20Sopenharmony_ci u32 id; 518c2ecf20Sopenharmony_ci u32 size; 528c2ecf20Sopenharmony_ci bool committed; 538c2ecf20Sopenharmony_ci}; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistatic int vmw_dx_streamoutput_create(struct vmw_resource *res); 568c2ecf20Sopenharmony_cistatic int vmw_dx_streamoutput_bind(struct vmw_resource *res, 578c2ecf20Sopenharmony_ci struct ttm_validate_buffer *val_buf); 588c2ecf20Sopenharmony_cistatic int vmw_dx_streamoutput_unbind(struct vmw_resource *res, bool readback, 598c2ecf20Sopenharmony_ci struct ttm_validate_buffer *val_buf); 608c2ecf20Sopenharmony_cistatic void vmw_dx_streamoutput_commit_notify(struct vmw_resource *res, 618c2ecf20Sopenharmony_ci enum vmw_cmdbuf_res_state state); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cistatic size_t vmw_streamoutput_size; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_cistatic const struct vmw_res_func vmw_dx_streamoutput_func = { 668c2ecf20Sopenharmony_ci .res_type = vmw_res_streamoutput, 678c2ecf20Sopenharmony_ci .needs_backup = true, 688c2ecf20Sopenharmony_ci .may_evict = false, 698c2ecf20Sopenharmony_ci .type_name = "DX streamoutput", 708c2ecf20Sopenharmony_ci .backup_placement = &vmw_mob_placement, 718c2ecf20Sopenharmony_ci .create = vmw_dx_streamoutput_create, 728c2ecf20Sopenharmony_ci .destroy = NULL, /* Command buffer managed resource. */ 738c2ecf20Sopenharmony_ci .bind = vmw_dx_streamoutput_bind, 748c2ecf20Sopenharmony_ci .unbind = vmw_dx_streamoutput_unbind, 758c2ecf20Sopenharmony_ci .commit_notify = vmw_dx_streamoutput_commit_notify, 768c2ecf20Sopenharmony_ci}; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistatic inline struct vmw_dx_streamoutput * 798c2ecf20Sopenharmony_civmw_res_to_dx_streamoutput(struct vmw_resource *res) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci return container_of(res, struct vmw_dx_streamoutput, res); 828c2ecf20Sopenharmony_ci} 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci/** 858c2ecf20Sopenharmony_ci * vmw_dx_streamoutput_unscrub - Reattach the MOB to streamoutput. 868c2ecf20Sopenharmony_ci * @res: The streamoutput resource. 878c2ecf20Sopenharmony_ci * 888c2ecf20Sopenharmony_ci * Return: 0 on success, negative error code on failure. 898c2ecf20Sopenharmony_ci */ 908c2ecf20Sopenharmony_cistatic int vmw_dx_streamoutput_unscrub(struct vmw_resource *res) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci struct vmw_dx_streamoutput *so = vmw_res_to_dx_streamoutput(res); 938c2ecf20Sopenharmony_ci struct vmw_private *dev_priv = res->dev_priv; 948c2ecf20Sopenharmony_ci struct { 958c2ecf20Sopenharmony_ci SVGA3dCmdHeader header; 968c2ecf20Sopenharmony_ci SVGA3dCmdDXBindStreamOutput body; 978c2ecf20Sopenharmony_ci } *cmd; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci if (!list_empty(&so->cotable_head) || !so->committed ) 1008c2ecf20Sopenharmony_ci return 0; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci cmd = VMW_FIFO_RESERVE_DX(dev_priv, sizeof(*cmd), so->ctx->id); 1038c2ecf20Sopenharmony_ci if (!cmd) 1048c2ecf20Sopenharmony_ci return -ENOMEM; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci cmd->header.id = SVGA_3D_CMD_DX_BIND_STREAMOUTPUT; 1078c2ecf20Sopenharmony_ci cmd->header.size = sizeof(cmd->body); 1088c2ecf20Sopenharmony_ci cmd->body.soid = so->id; 1098c2ecf20Sopenharmony_ci cmd->body.mobid = res->backup->base.mem.start; 1108c2ecf20Sopenharmony_ci cmd->body.offsetInBytes = res->backup_offset; 1118c2ecf20Sopenharmony_ci cmd->body.sizeInBytes = so->size; 1128c2ecf20Sopenharmony_ci vmw_fifo_commit(dev_priv, sizeof(*cmd)); 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci vmw_cotable_add_resource(so->cotable, &so->cotable_head); 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci return 0; 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cistatic int vmw_dx_streamoutput_create(struct vmw_resource *res) 1208c2ecf20Sopenharmony_ci{ 1218c2ecf20Sopenharmony_ci struct vmw_private *dev_priv = res->dev_priv; 1228c2ecf20Sopenharmony_ci struct vmw_dx_streamoutput *so = vmw_res_to_dx_streamoutput(res); 1238c2ecf20Sopenharmony_ci int ret = 0; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci WARN_ON_ONCE(!so->committed); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci if (vmw_resource_mob_attached(res)) { 1288c2ecf20Sopenharmony_ci mutex_lock(&dev_priv->binding_mutex); 1298c2ecf20Sopenharmony_ci ret = vmw_dx_streamoutput_unscrub(res); 1308c2ecf20Sopenharmony_ci mutex_unlock(&dev_priv->binding_mutex); 1318c2ecf20Sopenharmony_ci } 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci res->id = so->id; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci return ret; 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_cistatic int vmw_dx_streamoutput_bind(struct vmw_resource *res, 1398c2ecf20Sopenharmony_ci struct ttm_validate_buffer *val_buf) 1408c2ecf20Sopenharmony_ci{ 1418c2ecf20Sopenharmony_ci struct vmw_private *dev_priv = res->dev_priv; 1428c2ecf20Sopenharmony_ci struct ttm_buffer_object *bo = val_buf->bo; 1438c2ecf20Sopenharmony_ci int ret; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci if (WARN_ON(bo->mem.mem_type != VMW_PL_MOB)) 1468c2ecf20Sopenharmony_ci return -EINVAL; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci mutex_lock(&dev_priv->binding_mutex); 1498c2ecf20Sopenharmony_ci ret = vmw_dx_streamoutput_unscrub(res); 1508c2ecf20Sopenharmony_ci mutex_unlock(&dev_priv->binding_mutex); 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci return ret; 1538c2ecf20Sopenharmony_ci} 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci/** 1568c2ecf20Sopenharmony_ci * vmw_dx_streamoutput_scrub - Unbind the MOB from streamoutput. 1578c2ecf20Sopenharmony_ci * @res: The streamoutput resource. 1588c2ecf20Sopenharmony_ci * 1598c2ecf20Sopenharmony_ci * Return: 0 on success, negative error code on failure. 1608c2ecf20Sopenharmony_ci */ 1618c2ecf20Sopenharmony_cistatic int vmw_dx_streamoutput_scrub(struct vmw_resource *res) 1628c2ecf20Sopenharmony_ci{ 1638c2ecf20Sopenharmony_ci struct vmw_private *dev_priv = res->dev_priv; 1648c2ecf20Sopenharmony_ci struct vmw_dx_streamoutput *so = vmw_res_to_dx_streamoutput(res); 1658c2ecf20Sopenharmony_ci struct { 1668c2ecf20Sopenharmony_ci SVGA3dCmdHeader header; 1678c2ecf20Sopenharmony_ci SVGA3dCmdDXBindStreamOutput body; 1688c2ecf20Sopenharmony_ci } *cmd; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci if (list_empty(&so->cotable_head)) 1718c2ecf20Sopenharmony_ci return 0; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci WARN_ON_ONCE(!so->committed); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci cmd = VMW_FIFO_RESERVE_DX(dev_priv, sizeof(*cmd), so->ctx->id); 1768c2ecf20Sopenharmony_ci if (!cmd) 1778c2ecf20Sopenharmony_ci return -ENOMEM; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci cmd->header.id = SVGA_3D_CMD_DX_BIND_STREAMOUTPUT; 1808c2ecf20Sopenharmony_ci cmd->header.size = sizeof(cmd->body); 1818c2ecf20Sopenharmony_ci cmd->body.soid = res->id; 1828c2ecf20Sopenharmony_ci cmd->body.mobid = SVGA3D_INVALID_ID; 1838c2ecf20Sopenharmony_ci cmd->body.offsetInBytes = 0; 1848c2ecf20Sopenharmony_ci cmd->body.sizeInBytes = so->size; 1858c2ecf20Sopenharmony_ci vmw_fifo_commit(dev_priv, sizeof(*cmd)); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci res->id = -1; 1888c2ecf20Sopenharmony_ci list_del_init(&so->cotable_head); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci return 0; 1918c2ecf20Sopenharmony_ci} 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_cistatic int vmw_dx_streamoutput_unbind(struct vmw_resource *res, bool readback, 1948c2ecf20Sopenharmony_ci struct ttm_validate_buffer *val_buf) 1958c2ecf20Sopenharmony_ci{ 1968c2ecf20Sopenharmony_ci struct vmw_private *dev_priv = res->dev_priv; 1978c2ecf20Sopenharmony_ci struct vmw_fence_obj *fence; 1988c2ecf20Sopenharmony_ci int ret; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci if (WARN_ON(res->backup->base.mem.mem_type != VMW_PL_MOB)) 2018c2ecf20Sopenharmony_ci return -EINVAL; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci mutex_lock(&dev_priv->binding_mutex); 2048c2ecf20Sopenharmony_ci ret = vmw_dx_streamoutput_scrub(res); 2058c2ecf20Sopenharmony_ci mutex_unlock(&dev_priv->binding_mutex); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci if (ret) 2088c2ecf20Sopenharmony_ci return ret; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci (void) vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL); 2118c2ecf20Sopenharmony_ci vmw_bo_fence_single(val_buf->bo, fence); 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci if (fence != NULL) 2148c2ecf20Sopenharmony_ci vmw_fence_obj_unreference(&fence); 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci return 0; 2178c2ecf20Sopenharmony_ci} 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_cistatic void vmw_dx_streamoutput_commit_notify(struct vmw_resource *res, 2208c2ecf20Sopenharmony_ci enum vmw_cmdbuf_res_state state) 2218c2ecf20Sopenharmony_ci{ 2228c2ecf20Sopenharmony_ci struct vmw_private *dev_priv = res->dev_priv; 2238c2ecf20Sopenharmony_ci struct vmw_dx_streamoutput *so = vmw_res_to_dx_streamoutput(res); 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci if (state == VMW_CMDBUF_RES_ADD) { 2268c2ecf20Sopenharmony_ci mutex_lock(&dev_priv->binding_mutex); 2278c2ecf20Sopenharmony_ci vmw_cotable_add_resource(so->cotable, &so->cotable_head); 2288c2ecf20Sopenharmony_ci so->committed = true; 2298c2ecf20Sopenharmony_ci res->id = so->id; 2308c2ecf20Sopenharmony_ci mutex_unlock(&dev_priv->binding_mutex); 2318c2ecf20Sopenharmony_ci } else { 2328c2ecf20Sopenharmony_ci mutex_lock(&dev_priv->binding_mutex); 2338c2ecf20Sopenharmony_ci list_del_init(&so->cotable_head); 2348c2ecf20Sopenharmony_ci so->committed = false; 2358c2ecf20Sopenharmony_ci res->id = -1; 2368c2ecf20Sopenharmony_ci mutex_unlock(&dev_priv->binding_mutex); 2378c2ecf20Sopenharmony_ci } 2388c2ecf20Sopenharmony_ci} 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci/** 2418c2ecf20Sopenharmony_ci * vmw_dx_streamoutput_lookup - Do a streamoutput resource lookup by user key. 2428c2ecf20Sopenharmony_ci * @man: Command buffer managed resource manager for current context. 2438c2ecf20Sopenharmony_ci * @user_key: User-space identifier for lookup. 2448c2ecf20Sopenharmony_ci * 2458c2ecf20Sopenharmony_ci * Return: Valid refcounted vmw_resource on success, error pointer on failure. 2468c2ecf20Sopenharmony_ci */ 2478c2ecf20Sopenharmony_cistruct vmw_resource * 2488c2ecf20Sopenharmony_civmw_dx_streamoutput_lookup(struct vmw_cmdbuf_res_manager *man, 2498c2ecf20Sopenharmony_ci u32 user_key) 2508c2ecf20Sopenharmony_ci{ 2518c2ecf20Sopenharmony_ci return vmw_cmdbuf_res_lookup(man, vmw_cmdbuf_res_streamoutput, 2528c2ecf20Sopenharmony_ci user_key); 2538c2ecf20Sopenharmony_ci} 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_cistatic void vmw_dx_streamoutput_res_free(struct vmw_resource *res) 2568c2ecf20Sopenharmony_ci{ 2578c2ecf20Sopenharmony_ci struct vmw_private *dev_priv = res->dev_priv; 2588c2ecf20Sopenharmony_ci struct vmw_dx_streamoutput *so = vmw_res_to_dx_streamoutput(res); 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci vmw_resource_unreference(&so->cotable); 2618c2ecf20Sopenharmony_ci kfree(so); 2628c2ecf20Sopenharmony_ci ttm_mem_global_free(vmw_mem_glob(dev_priv), vmw_streamoutput_size); 2638c2ecf20Sopenharmony_ci} 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_cistatic void vmw_dx_streamoutput_hw_destroy(struct vmw_resource *res) 2668c2ecf20Sopenharmony_ci{ 2678c2ecf20Sopenharmony_ci /* Destroyed by user-space cmd buf or as part of context takedown. */ 2688c2ecf20Sopenharmony_ci res->id = -1; 2698c2ecf20Sopenharmony_ci} 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci/** 2728c2ecf20Sopenharmony_ci * vmw_dx_streamoutput_add - Add a streamoutput as a cmd buf managed resource. 2738c2ecf20Sopenharmony_ci * @man: Command buffer managed resource manager for current context. 2748c2ecf20Sopenharmony_ci * @ctx: Pointer to context resource. 2758c2ecf20Sopenharmony_ci * @user_key: The identifier for this streamoutput. 2768c2ecf20Sopenharmony_ci * @list: The list of staged command buffer managed resources. 2778c2ecf20Sopenharmony_ci * 2788c2ecf20Sopenharmony_ci * Return: 0 on success, negative error code on failure. 2798c2ecf20Sopenharmony_ci */ 2808c2ecf20Sopenharmony_ciint vmw_dx_streamoutput_add(struct vmw_cmdbuf_res_manager *man, 2818c2ecf20Sopenharmony_ci struct vmw_resource *ctx, u32 user_key, 2828c2ecf20Sopenharmony_ci struct list_head *list) 2838c2ecf20Sopenharmony_ci{ 2848c2ecf20Sopenharmony_ci struct vmw_dx_streamoutput *so; 2858c2ecf20Sopenharmony_ci struct vmw_resource *res; 2868c2ecf20Sopenharmony_ci struct vmw_private *dev_priv = ctx->dev_priv; 2878c2ecf20Sopenharmony_ci struct ttm_operation_ctx ttm_opt_ctx = { 2888c2ecf20Sopenharmony_ci .interruptible = true, 2898c2ecf20Sopenharmony_ci .no_wait_gpu = false 2908c2ecf20Sopenharmony_ci }; 2918c2ecf20Sopenharmony_ci int ret; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci if (!vmw_streamoutput_size) 2948c2ecf20Sopenharmony_ci vmw_streamoutput_size = ttm_round_pot(sizeof(*so)); 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), 2978c2ecf20Sopenharmony_ci vmw_streamoutput_size, &ttm_opt_ctx); 2988c2ecf20Sopenharmony_ci if (ret) { 2998c2ecf20Sopenharmony_ci if (ret != -ERESTARTSYS) 3008c2ecf20Sopenharmony_ci DRM_ERROR("Out of graphics memory for streamout.\n"); 3018c2ecf20Sopenharmony_ci return ret; 3028c2ecf20Sopenharmony_ci } 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci so = kmalloc(sizeof(*so), GFP_KERNEL); 3058c2ecf20Sopenharmony_ci if (!so) { 3068c2ecf20Sopenharmony_ci ttm_mem_global_free(vmw_mem_glob(dev_priv), 3078c2ecf20Sopenharmony_ci vmw_streamoutput_size); 3088c2ecf20Sopenharmony_ci return -ENOMEM; 3098c2ecf20Sopenharmony_ci } 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci res = &so->res; 3128c2ecf20Sopenharmony_ci so->ctx = ctx; 3138c2ecf20Sopenharmony_ci so->cotable = vmw_resource_reference 3148c2ecf20Sopenharmony_ci (vmw_context_cotable(ctx, SVGA_COTABLE_STREAMOUTPUT)); 3158c2ecf20Sopenharmony_ci so->id = user_key; 3168c2ecf20Sopenharmony_ci so->committed = false; 3178c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&so->cotable_head); 3188c2ecf20Sopenharmony_ci ret = vmw_resource_init(dev_priv, res, true, 3198c2ecf20Sopenharmony_ci vmw_dx_streamoutput_res_free, 3208c2ecf20Sopenharmony_ci &vmw_dx_streamoutput_func); 3218c2ecf20Sopenharmony_ci if (ret) 3228c2ecf20Sopenharmony_ci goto out_resource_init; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci ret = vmw_cmdbuf_res_add(man, vmw_cmdbuf_res_streamoutput, user_key, 3258c2ecf20Sopenharmony_ci res, list); 3268c2ecf20Sopenharmony_ci if (ret) 3278c2ecf20Sopenharmony_ci goto out_resource_init; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci res->id = so->id; 3308c2ecf20Sopenharmony_ci res->hw_destroy = vmw_dx_streamoutput_hw_destroy; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ciout_resource_init: 3338c2ecf20Sopenharmony_ci vmw_resource_unreference(&res); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci return ret; 3368c2ecf20Sopenharmony_ci} 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci/** 3398c2ecf20Sopenharmony_ci * vmw_dx_streamoutput_set_size - Sets streamoutput mob size in res struct. 3408c2ecf20Sopenharmony_ci * @res: The streamoutput res for which need to set size. 3418c2ecf20Sopenharmony_ci * @size: The size provided by user-space to set. 3428c2ecf20Sopenharmony_ci */ 3438c2ecf20Sopenharmony_civoid vmw_dx_streamoutput_set_size(struct vmw_resource *res, u32 size) 3448c2ecf20Sopenharmony_ci{ 3458c2ecf20Sopenharmony_ci struct vmw_dx_streamoutput *so = vmw_res_to_dx_streamoutput(res); 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci so->size = size; 3488c2ecf20Sopenharmony_ci} 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci/** 3518c2ecf20Sopenharmony_ci * vmw_dx_streamoutput_remove - Stage streamoutput for removal. 3528c2ecf20Sopenharmony_ci * @man: Command buffer managed resource manager for current context. 3538c2ecf20Sopenharmony_ci * @user_key: The identifier for this streamoutput. 3548c2ecf20Sopenharmony_ci * @list: The list of staged command buffer managed resources. 3558c2ecf20Sopenharmony_ci * 3568c2ecf20Sopenharmony_ci * Return: 0 on success, negative error code on failure. 3578c2ecf20Sopenharmony_ci */ 3588c2ecf20Sopenharmony_ciint vmw_dx_streamoutput_remove(struct vmw_cmdbuf_res_manager *man, 3598c2ecf20Sopenharmony_ci u32 user_key, 3608c2ecf20Sopenharmony_ci struct list_head *list) 3618c2ecf20Sopenharmony_ci{ 3628c2ecf20Sopenharmony_ci struct vmw_resource *r; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci return vmw_cmdbuf_res_remove(man, vmw_cmdbuf_res_streamoutput, 3658c2ecf20Sopenharmony_ci (u32)user_key, list, &r); 3668c2ecf20Sopenharmony_ci} 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci/** 3698c2ecf20Sopenharmony_ci * vmw_dx_streamoutput_cotable_list_scrub - cotable unbind_func callback. 3708c2ecf20Sopenharmony_ci * @dev_priv: Device private. 3718c2ecf20Sopenharmony_ci * @list: The list of cotable resources. 3728c2ecf20Sopenharmony_ci * @readback: Whether the call was part of a readback unbind. 3738c2ecf20Sopenharmony_ci */ 3748c2ecf20Sopenharmony_civoid vmw_dx_streamoutput_cotable_list_scrub(struct vmw_private *dev_priv, 3758c2ecf20Sopenharmony_ci struct list_head *list, 3768c2ecf20Sopenharmony_ci bool readback) 3778c2ecf20Sopenharmony_ci{ 3788c2ecf20Sopenharmony_ci struct vmw_dx_streamoutput *entry, *next; 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci lockdep_assert_held_once(&dev_priv->binding_mutex); 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci list_for_each_entry_safe(entry, next, list, cotable_head) { 3838c2ecf20Sopenharmony_ci WARN_ON(vmw_dx_streamoutput_scrub(&entry->res)); 3848c2ecf20Sopenharmony_ci if (!readback) 3858c2ecf20Sopenharmony_ci entry->committed =false; 3868c2ecf20Sopenharmony_ci } 3878c2ecf20Sopenharmony_ci} 388