1c74c162fSThomas Hellstrom /************************************************************************** 2c74c162fSThomas Hellstrom * 354fbde8aSSinclair Yeh * Copyright © 2009-2015 VMware, Inc., Palo Alto, CA., USA 4c74c162fSThomas Hellstrom * All Rights Reserved. 5c74c162fSThomas Hellstrom * 6c74c162fSThomas Hellstrom * Permission is hereby granted, free of charge, to any person obtaining a 7c74c162fSThomas Hellstrom * copy of this software and associated documentation files (the 8c74c162fSThomas Hellstrom * "Software"), to deal in the Software without restriction, including 9c74c162fSThomas Hellstrom * without limitation the rights to use, copy, modify, merge, publish, 10c74c162fSThomas Hellstrom * distribute, sub license, and/or sell copies of the Software, and to 11c74c162fSThomas Hellstrom * permit persons to whom the Software is furnished to do so, subject to 12c74c162fSThomas Hellstrom * the following conditions: 13c74c162fSThomas Hellstrom * 14c74c162fSThomas Hellstrom * The above copyright notice and this permission notice (including the 15c74c162fSThomas Hellstrom * next paragraph) shall be included in all copies or substantial portions 16c74c162fSThomas Hellstrom * of the Software. 17c74c162fSThomas Hellstrom * 18c74c162fSThomas Hellstrom * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19c74c162fSThomas Hellstrom * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20c74c162fSThomas Hellstrom * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 21c74c162fSThomas Hellstrom * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 22c74c162fSThomas Hellstrom * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 23c74c162fSThomas Hellstrom * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 24c74c162fSThomas Hellstrom * USE OR OTHER DEALINGS IN THE SOFTWARE. 25c74c162fSThomas Hellstrom * 26c74c162fSThomas Hellstrom **************************************************************************/ 27c74c162fSThomas Hellstrom 28008be682SMasahiro Yamada #include <drm/ttm/ttm_placement.h> 29008be682SMasahiro Yamada 30c74c162fSThomas Hellstrom #include "vmwgfx_drv.h" 31c74c162fSThomas Hellstrom #include "vmwgfx_resource_priv.h" 32d80efd5cSThomas Hellstrom #include "vmwgfx_binding.h" 33c74c162fSThomas Hellstrom 34c74c162fSThomas Hellstrom struct vmw_shader { 35c74c162fSThomas Hellstrom struct vmw_resource res; 36c74c162fSThomas Hellstrom SVGA3dShaderType type; 37c74c162fSThomas Hellstrom uint32_t size; 38d80efd5cSThomas Hellstrom uint8_t num_input_sig; 39d80efd5cSThomas Hellstrom uint8_t num_output_sig; 40c74c162fSThomas Hellstrom }; 41c74c162fSThomas Hellstrom 42c74c162fSThomas Hellstrom struct vmw_user_shader { 43c74c162fSThomas Hellstrom struct ttm_base_object base; 44c74c162fSThomas Hellstrom struct vmw_shader shader; 45c74c162fSThomas Hellstrom }; 46c74c162fSThomas Hellstrom 47d80efd5cSThomas Hellstrom struct vmw_dx_shader { 48d80efd5cSThomas Hellstrom struct vmw_resource res; 49d80efd5cSThomas Hellstrom struct vmw_resource *ctx; 50d80efd5cSThomas Hellstrom struct vmw_resource *cotable; 51d80efd5cSThomas Hellstrom u32 id; 52d80efd5cSThomas Hellstrom bool committed; 53d80efd5cSThomas Hellstrom struct list_head cotable_head; 54d80efd5cSThomas Hellstrom }; 55d80efd5cSThomas Hellstrom 5618e4a466SThomas Hellstrom static uint64_t vmw_user_shader_size; 5718e4a466SThomas Hellstrom static uint64_t vmw_shader_size; 58d80efd5cSThomas Hellstrom static size_t vmw_shader_dx_size; 59d5bde956SThomas Hellstrom 60c74c162fSThomas Hellstrom static void vmw_user_shader_free(struct vmw_resource *res); 61c74c162fSThomas Hellstrom static struct vmw_resource * 62c74c162fSThomas Hellstrom vmw_user_shader_base_to_res(struct ttm_base_object *base); 63c74c162fSThomas Hellstrom 64c74c162fSThomas Hellstrom static int vmw_gb_shader_create(struct vmw_resource *res); 65c74c162fSThomas Hellstrom static int vmw_gb_shader_bind(struct vmw_resource *res, 66c74c162fSThomas Hellstrom struct ttm_validate_buffer *val_buf); 67c74c162fSThomas Hellstrom static int vmw_gb_shader_unbind(struct vmw_resource *res, 68c74c162fSThomas Hellstrom bool readback, 69c74c162fSThomas Hellstrom struct ttm_validate_buffer *val_buf); 70c74c162fSThomas Hellstrom static int vmw_gb_shader_destroy(struct vmw_resource *res); 71c74c162fSThomas Hellstrom 72d80efd5cSThomas Hellstrom static int vmw_dx_shader_create(struct vmw_resource *res); 73d80efd5cSThomas Hellstrom static int vmw_dx_shader_bind(struct vmw_resource *res, 74d80efd5cSThomas Hellstrom struct ttm_validate_buffer *val_buf); 75d80efd5cSThomas Hellstrom static int vmw_dx_shader_unbind(struct vmw_resource *res, 76d80efd5cSThomas Hellstrom bool readback, 77d80efd5cSThomas Hellstrom struct ttm_validate_buffer *val_buf); 78d80efd5cSThomas Hellstrom static void vmw_dx_shader_commit_notify(struct vmw_resource *res, 79d80efd5cSThomas Hellstrom enum vmw_cmdbuf_res_state state); 80d80efd5cSThomas Hellstrom static bool vmw_shader_id_ok(u32 user_key, SVGA3dShaderType shader_type); 81d80efd5cSThomas Hellstrom static u32 vmw_shader_key(u32 user_key, SVGA3dShaderType shader_type); 82d80efd5cSThomas Hellstrom static uint64_t vmw_user_shader_size; 83d80efd5cSThomas Hellstrom 84c74c162fSThomas Hellstrom static const struct vmw_user_resource_conv user_shader_conv = { 85c74c162fSThomas Hellstrom .object_type = VMW_RES_SHADER, 86c74c162fSThomas Hellstrom .base_obj_to_res = vmw_user_shader_base_to_res, 87c74c162fSThomas Hellstrom .res_free = vmw_user_shader_free 88c74c162fSThomas Hellstrom }; 89c74c162fSThomas Hellstrom 90c74c162fSThomas Hellstrom const struct vmw_user_resource_conv *user_shader_converter = 91c74c162fSThomas Hellstrom &user_shader_conv; 92c74c162fSThomas Hellstrom 93c74c162fSThomas Hellstrom 94c74c162fSThomas Hellstrom static const struct vmw_res_func vmw_gb_shader_func = { 95c74c162fSThomas Hellstrom .res_type = vmw_res_shader, 96c74c162fSThomas Hellstrom .needs_backup = true, 97c74c162fSThomas Hellstrom .may_evict = true, 98c74c162fSThomas Hellstrom .type_name = "guest backed shaders", 99c74c162fSThomas Hellstrom .backup_placement = &vmw_mob_placement, 100c74c162fSThomas Hellstrom .create = vmw_gb_shader_create, 101c74c162fSThomas Hellstrom .destroy = vmw_gb_shader_destroy, 102c74c162fSThomas Hellstrom .bind = vmw_gb_shader_bind, 103c74c162fSThomas Hellstrom .unbind = vmw_gb_shader_unbind 104c74c162fSThomas Hellstrom }; 105c74c162fSThomas Hellstrom 106d80efd5cSThomas Hellstrom static const struct vmw_res_func vmw_dx_shader_func = { 107d80efd5cSThomas Hellstrom .res_type = vmw_res_shader, 108d80efd5cSThomas Hellstrom .needs_backup = true, 109d80efd5cSThomas Hellstrom .may_evict = false, 110d80efd5cSThomas Hellstrom .type_name = "dx shaders", 111d80efd5cSThomas Hellstrom .backup_placement = &vmw_mob_placement, 112d80efd5cSThomas Hellstrom .create = vmw_dx_shader_create, 113d80efd5cSThomas Hellstrom /* 114d80efd5cSThomas Hellstrom * The destroy callback is only called with a committed resource on 115d80efd5cSThomas Hellstrom * context destroy, in which case we destroy the cotable anyway, 116d80efd5cSThomas Hellstrom * so there's no need to destroy DX shaders separately. 117d80efd5cSThomas Hellstrom */ 118d80efd5cSThomas Hellstrom .destroy = NULL, 119d80efd5cSThomas Hellstrom .bind = vmw_dx_shader_bind, 120d80efd5cSThomas Hellstrom .unbind = vmw_dx_shader_unbind, 121d80efd5cSThomas Hellstrom .commit_notify = vmw_dx_shader_commit_notify, 122d80efd5cSThomas Hellstrom }; 123d80efd5cSThomas Hellstrom 124c74c162fSThomas Hellstrom /** 125c74c162fSThomas Hellstrom * Shader management: 126c74c162fSThomas Hellstrom */ 127c74c162fSThomas Hellstrom 128c74c162fSThomas Hellstrom static inline struct vmw_shader * 129c74c162fSThomas Hellstrom vmw_res_to_shader(struct vmw_resource *res) 130c74c162fSThomas Hellstrom { 131c74c162fSThomas Hellstrom return container_of(res, struct vmw_shader, res); 132c74c162fSThomas Hellstrom } 133c74c162fSThomas Hellstrom 134d80efd5cSThomas Hellstrom /** 135d80efd5cSThomas Hellstrom * vmw_res_to_dx_shader - typecast a struct vmw_resource to a 136d80efd5cSThomas Hellstrom * struct vmw_dx_shader 137d80efd5cSThomas Hellstrom * 138d80efd5cSThomas Hellstrom * @res: Pointer to the struct vmw_resource. 139d80efd5cSThomas Hellstrom */ 140d80efd5cSThomas Hellstrom static inline struct vmw_dx_shader * 141d80efd5cSThomas Hellstrom vmw_res_to_dx_shader(struct vmw_resource *res) 142d80efd5cSThomas Hellstrom { 143d80efd5cSThomas Hellstrom return container_of(res, struct vmw_dx_shader, res); 144d80efd5cSThomas Hellstrom } 145d80efd5cSThomas Hellstrom 146c74c162fSThomas Hellstrom static void vmw_hw_shader_destroy(struct vmw_resource *res) 147c74c162fSThomas Hellstrom { 148d80efd5cSThomas Hellstrom if (likely(res->func->destroy)) 149d80efd5cSThomas Hellstrom (void) res->func->destroy(res); 150d80efd5cSThomas Hellstrom else 151d80efd5cSThomas Hellstrom res->id = -1; 152c74c162fSThomas Hellstrom } 153c74c162fSThomas Hellstrom 154d80efd5cSThomas Hellstrom 155c74c162fSThomas Hellstrom static int vmw_gb_shader_init(struct vmw_private *dev_priv, 156c74c162fSThomas Hellstrom struct vmw_resource *res, 157c74c162fSThomas Hellstrom uint32_t size, 158c74c162fSThomas Hellstrom uint64_t offset, 159c74c162fSThomas Hellstrom SVGA3dShaderType type, 160d80efd5cSThomas Hellstrom uint8_t num_input_sig, 161d80efd5cSThomas Hellstrom uint8_t num_output_sig, 162f1d34bfdSThomas Hellstrom struct vmw_buffer_object *byte_code, 163c74c162fSThomas Hellstrom void (*res_free) (struct vmw_resource *res)) 164c74c162fSThomas Hellstrom { 165c74c162fSThomas Hellstrom struct vmw_shader *shader = vmw_res_to_shader(res); 166c74c162fSThomas Hellstrom int ret; 167c74c162fSThomas Hellstrom 168d80efd5cSThomas Hellstrom ret = vmw_resource_init(dev_priv, res, true, res_free, 169d80efd5cSThomas Hellstrom &vmw_gb_shader_func); 170c74c162fSThomas Hellstrom 171c74c162fSThomas Hellstrom if (unlikely(ret != 0)) { 172c74c162fSThomas Hellstrom if (res_free) 173c74c162fSThomas Hellstrom res_free(res); 174c74c162fSThomas Hellstrom else 175c74c162fSThomas Hellstrom kfree(res); 176c74c162fSThomas Hellstrom return ret; 177c74c162fSThomas Hellstrom } 178c74c162fSThomas Hellstrom 179c74c162fSThomas Hellstrom res->backup_size = size; 180c74c162fSThomas Hellstrom if (byte_code) { 181f1d34bfdSThomas Hellstrom res->backup = vmw_bo_reference(byte_code); 182c74c162fSThomas Hellstrom res->backup_offset = offset; 183c74c162fSThomas Hellstrom } 184c74c162fSThomas Hellstrom shader->size = size; 185c74c162fSThomas Hellstrom shader->type = type; 186d80efd5cSThomas Hellstrom shader->num_input_sig = num_input_sig; 187d80efd5cSThomas Hellstrom shader->num_output_sig = num_output_sig; 188c74c162fSThomas Hellstrom 189c74c162fSThomas Hellstrom vmw_resource_activate(res, vmw_hw_shader_destroy); 190c74c162fSThomas Hellstrom return 0; 191c74c162fSThomas Hellstrom } 192c74c162fSThomas Hellstrom 193d80efd5cSThomas Hellstrom /* 194d80efd5cSThomas Hellstrom * GB shader code: 195d80efd5cSThomas Hellstrom */ 196d80efd5cSThomas Hellstrom 197c74c162fSThomas Hellstrom static int vmw_gb_shader_create(struct vmw_resource *res) 198c74c162fSThomas Hellstrom { 199c74c162fSThomas Hellstrom struct vmw_private *dev_priv = res->dev_priv; 200c74c162fSThomas Hellstrom struct vmw_shader *shader = vmw_res_to_shader(res); 201c74c162fSThomas Hellstrom int ret; 202c74c162fSThomas Hellstrom struct { 203c74c162fSThomas Hellstrom SVGA3dCmdHeader header; 204c74c162fSThomas Hellstrom SVGA3dCmdDefineGBShader body; 205c74c162fSThomas Hellstrom } *cmd; 206c74c162fSThomas Hellstrom 207c74c162fSThomas Hellstrom if (likely(res->id != -1)) 208c74c162fSThomas Hellstrom return 0; 209c74c162fSThomas Hellstrom 210c74c162fSThomas Hellstrom ret = vmw_resource_alloc_id(res); 211c74c162fSThomas Hellstrom if (unlikely(ret != 0)) { 212c74c162fSThomas Hellstrom DRM_ERROR("Failed to allocate a shader id.\n"); 213c74c162fSThomas Hellstrom goto out_no_id; 214c74c162fSThomas Hellstrom } 215c74c162fSThomas Hellstrom 216c74c162fSThomas Hellstrom if (unlikely(res->id >= VMWGFX_NUM_GB_SHADER)) { 217c74c162fSThomas Hellstrom ret = -EBUSY; 218c74c162fSThomas Hellstrom goto out_no_fifo; 219c74c162fSThomas Hellstrom } 220c74c162fSThomas Hellstrom 221c74c162fSThomas Hellstrom cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); 222c74c162fSThomas Hellstrom if (unlikely(cmd == NULL)) { 223c74c162fSThomas Hellstrom DRM_ERROR("Failed reserving FIFO space for shader " 224c74c162fSThomas Hellstrom "creation.\n"); 225c74c162fSThomas Hellstrom ret = -ENOMEM; 226c74c162fSThomas Hellstrom goto out_no_fifo; 227c74c162fSThomas Hellstrom } 228c74c162fSThomas Hellstrom 229c74c162fSThomas Hellstrom cmd->header.id = SVGA_3D_CMD_DEFINE_GB_SHADER; 230c74c162fSThomas Hellstrom cmd->header.size = sizeof(cmd->body); 231c74c162fSThomas Hellstrom cmd->body.shid = res->id; 232c74c162fSThomas Hellstrom cmd->body.type = shader->type; 233c74c162fSThomas Hellstrom cmd->body.sizeInBytes = shader->size; 234c74c162fSThomas Hellstrom vmw_fifo_commit(dev_priv, sizeof(*cmd)); 235153b3d5bSThomas Hellstrom vmw_fifo_resource_inc(dev_priv); 236c74c162fSThomas Hellstrom 237c74c162fSThomas Hellstrom return 0; 238c74c162fSThomas Hellstrom 239c74c162fSThomas Hellstrom out_no_fifo: 240c74c162fSThomas Hellstrom vmw_resource_release_id(res); 241c74c162fSThomas Hellstrom out_no_id: 242c74c162fSThomas Hellstrom return ret; 243c74c162fSThomas Hellstrom } 244c74c162fSThomas Hellstrom 245c74c162fSThomas Hellstrom static int vmw_gb_shader_bind(struct vmw_resource *res, 246c74c162fSThomas Hellstrom struct ttm_validate_buffer *val_buf) 247c74c162fSThomas Hellstrom { 248c74c162fSThomas Hellstrom struct vmw_private *dev_priv = res->dev_priv; 249c74c162fSThomas Hellstrom struct { 250c74c162fSThomas Hellstrom SVGA3dCmdHeader header; 251c74c162fSThomas Hellstrom SVGA3dCmdBindGBShader body; 252c74c162fSThomas Hellstrom } *cmd; 253c74c162fSThomas Hellstrom struct ttm_buffer_object *bo = val_buf->bo; 254c74c162fSThomas Hellstrom 255c74c162fSThomas Hellstrom BUG_ON(bo->mem.mem_type != VMW_PL_MOB); 256c74c162fSThomas Hellstrom 257c74c162fSThomas Hellstrom cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); 258c74c162fSThomas Hellstrom if (unlikely(cmd == NULL)) { 259c74c162fSThomas Hellstrom DRM_ERROR("Failed reserving FIFO space for shader " 260c74c162fSThomas Hellstrom "binding.\n"); 261c74c162fSThomas Hellstrom return -ENOMEM; 262c74c162fSThomas Hellstrom } 263c74c162fSThomas Hellstrom 264c74c162fSThomas Hellstrom cmd->header.id = SVGA_3D_CMD_BIND_GB_SHADER; 265c74c162fSThomas Hellstrom cmd->header.size = sizeof(cmd->body); 266c74c162fSThomas Hellstrom cmd->body.shid = res->id; 267c74c162fSThomas Hellstrom cmd->body.mobid = bo->mem.start; 268b8ccd1e4SThomas Hellstrom cmd->body.offsetInBytes = res->backup_offset; 269c74c162fSThomas Hellstrom res->backup_dirty = false; 270c74c162fSThomas Hellstrom vmw_fifo_commit(dev_priv, sizeof(*cmd)); 271c74c162fSThomas Hellstrom 272c74c162fSThomas Hellstrom return 0; 273c74c162fSThomas Hellstrom } 274c74c162fSThomas Hellstrom 275c74c162fSThomas Hellstrom static int vmw_gb_shader_unbind(struct vmw_resource *res, 276c74c162fSThomas Hellstrom bool readback, 277c74c162fSThomas Hellstrom struct ttm_validate_buffer *val_buf) 278c74c162fSThomas Hellstrom { 279c74c162fSThomas Hellstrom struct vmw_private *dev_priv = res->dev_priv; 280c74c162fSThomas Hellstrom struct { 281c74c162fSThomas Hellstrom SVGA3dCmdHeader header; 282c74c162fSThomas Hellstrom SVGA3dCmdBindGBShader body; 283c74c162fSThomas Hellstrom } *cmd; 284c74c162fSThomas Hellstrom struct vmw_fence_obj *fence; 285c74c162fSThomas Hellstrom 286c74c162fSThomas Hellstrom BUG_ON(res->backup->base.mem.mem_type != VMW_PL_MOB); 287c74c162fSThomas Hellstrom 288c74c162fSThomas Hellstrom cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); 289c74c162fSThomas Hellstrom if (unlikely(cmd == NULL)) { 290c74c162fSThomas Hellstrom DRM_ERROR("Failed reserving FIFO space for shader " 291c74c162fSThomas Hellstrom "unbinding.\n"); 292c74c162fSThomas Hellstrom return -ENOMEM; 293c74c162fSThomas Hellstrom } 294c74c162fSThomas Hellstrom 295c74c162fSThomas Hellstrom cmd->header.id = SVGA_3D_CMD_BIND_GB_SHADER; 296c74c162fSThomas Hellstrom cmd->header.size = sizeof(cmd->body); 297c74c162fSThomas Hellstrom cmd->body.shid = res->id; 298c74c162fSThomas Hellstrom cmd->body.mobid = SVGA3D_INVALID_ID; 299c74c162fSThomas Hellstrom cmd->body.offsetInBytes = 0; 300c74c162fSThomas Hellstrom vmw_fifo_commit(dev_priv, sizeof(*cmd)); 301c74c162fSThomas Hellstrom 302c74c162fSThomas Hellstrom /* 303c74c162fSThomas Hellstrom * Create a fence object and fence the backup buffer. 304c74c162fSThomas Hellstrom */ 305c74c162fSThomas Hellstrom 306c74c162fSThomas Hellstrom (void) vmw_execbuf_fence_commands(NULL, dev_priv, 307c74c162fSThomas Hellstrom &fence, NULL); 308c74c162fSThomas Hellstrom 309e9431ea5SThomas Hellstrom vmw_bo_fence_single(val_buf->bo, fence); 310c74c162fSThomas Hellstrom 311c74c162fSThomas Hellstrom if (likely(fence != NULL)) 312c74c162fSThomas Hellstrom vmw_fence_obj_unreference(&fence); 313c74c162fSThomas Hellstrom 314c74c162fSThomas Hellstrom return 0; 315c74c162fSThomas Hellstrom } 316c74c162fSThomas Hellstrom 317c74c162fSThomas Hellstrom static int vmw_gb_shader_destroy(struct vmw_resource *res) 318c74c162fSThomas Hellstrom { 319c74c162fSThomas Hellstrom struct vmw_private *dev_priv = res->dev_priv; 320c74c162fSThomas Hellstrom struct { 321c74c162fSThomas Hellstrom SVGA3dCmdHeader header; 322c74c162fSThomas Hellstrom SVGA3dCmdDestroyGBShader body; 323c74c162fSThomas Hellstrom } *cmd; 324c74c162fSThomas Hellstrom 325c74c162fSThomas Hellstrom if (likely(res->id == -1)) 326c74c162fSThomas Hellstrom return 0; 327c74c162fSThomas Hellstrom 328173fb7d4SThomas Hellstrom mutex_lock(&dev_priv->binding_mutex); 329d80efd5cSThomas Hellstrom vmw_binding_res_list_scrub(&res->binding_head); 330173fb7d4SThomas Hellstrom 331c74c162fSThomas Hellstrom cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); 332c74c162fSThomas Hellstrom if (unlikely(cmd == NULL)) { 333c74c162fSThomas Hellstrom DRM_ERROR("Failed reserving FIFO space for shader " 334c74c162fSThomas Hellstrom "destruction.\n"); 3353e894a62SThomas Hellstrom mutex_unlock(&dev_priv->binding_mutex); 336c74c162fSThomas Hellstrom return -ENOMEM; 337c74c162fSThomas Hellstrom } 338c74c162fSThomas Hellstrom 339c74c162fSThomas Hellstrom cmd->header.id = SVGA_3D_CMD_DESTROY_GB_SHADER; 340c74c162fSThomas Hellstrom cmd->header.size = sizeof(cmd->body); 341c74c162fSThomas Hellstrom cmd->body.shid = res->id; 342c74c162fSThomas Hellstrom vmw_fifo_commit(dev_priv, sizeof(*cmd)); 343173fb7d4SThomas Hellstrom mutex_unlock(&dev_priv->binding_mutex); 344c74c162fSThomas Hellstrom vmw_resource_release_id(res); 345153b3d5bSThomas Hellstrom vmw_fifo_resource_dec(dev_priv); 346c74c162fSThomas Hellstrom 347c74c162fSThomas Hellstrom return 0; 348c74c162fSThomas Hellstrom } 349c74c162fSThomas Hellstrom 350d80efd5cSThomas Hellstrom /* 351d80efd5cSThomas Hellstrom * DX shader code: 352d80efd5cSThomas Hellstrom */ 353d80efd5cSThomas Hellstrom 354d80efd5cSThomas Hellstrom /** 355d80efd5cSThomas Hellstrom * vmw_dx_shader_commit_notify - Notify that a shader operation has been 356d80efd5cSThomas Hellstrom * committed to hardware from a user-supplied command stream. 357d80efd5cSThomas Hellstrom * 358d80efd5cSThomas Hellstrom * @res: Pointer to the shader resource. 359d80efd5cSThomas Hellstrom * @state: Indicating whether a creation or removal has been committed. 360d80efd5cSThomas Hellstrom * 361d80efd5cSThomas Hellstrom */ 362d80efd5cSThomas Hellstrom static void vmw_dx_shader_commit_notify(struct vmw_resource *res, 363d80efd5cSThomas Hellstrom enum vmw_cmdbuf_res_state state) 364d80efd5cSThomas Hellstrom { 365d80efd5cSThomas Hellstrom struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res); 366d80efd5cSThomas Hellstrom struct vmw_private *dev_priv = res->dev_priv; 367d80efd5cSThomas Hellstrom 368d80efd5cSThomas Hellstrom if (state == VMW_CMDBUF_RES_ADD) { 369d80efd5cSThomas Hellstrom mutex_lock(&dev_priv->binding_mutex); 370d80efd5cSThomas Hellstrom vmw_cotable_add_resource(shader->cotable, 371d80efd5cSThomas Hellstrom &shader->cotable_head); 372d80efd5cSThomas Hellstrom shader->committed = true; 373d80efd5cSThomas Hellstrom res->id = shader->id; 374d80efd5cSThomas Hellstrom mutex_unlock(&dev_priv->binding_mutex); 375d80efd5cSThomas Hellstrom } else { 376d80efd5cSThomas Hellstrom mutex_lock(&dev_priv->binding_mutex); 377d80efd5cSThomas Hellstrom list_del_init(&shader->cotable_head); 378d80efd5cSThomas Hellstrom shader->committed = false; 379d80efd5cSThomas Hellstrom res->id = -1; 380d80efd5cSThomas Hellstrom mutex_unlock(&dev_priv->binding_mutex); 381d80efd5cSThomas Hellstrom } 382d80efd5cSThomas Hellstrom } 383d80efd5cSThomas Hellstrom 384d80efd5cSThomas Hellstrom /** 385d80efd5cSThomas Hellstrom * vmw_dx_shader_unscrub - Have the device reattach a MOB to a DX shader. 386d80efd5cSThomas Hellstrom * 387d80efd5cSThomas Hellstrom * @res: The shader resource 388d80efd5cSThomas Hellstrom * 389d80efd5cSThomas Hellstrom * This function reverts a scrub operation. 390d80efd5cSThomas Hellstrom */ 391d80efd5cSThomas Hellstrom static int vmw_dx_shader_unscrub(struct vmw_resource *res) 392d80efd5cSThomas Hellstrom { 393d80efd5cSThomas Hellstrom struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res); 394d80efd5cSThomas Hellstrom struct vmw_private *dev_priv = res->dev_priv; 395d80efd5cSThomas Hellstrom struct { 396d80efd5cSThomas Hellstrom SVGA3dCmdHeader header; 397d80efd5cSThomas Hellstrom SVGA3dCmdDXBindShader body; 398d80efd5cSThomas Hellstrom } *cmd; 399d80efd5cSThomas Hellstrom 400d80efd5cSThomas Hellstrom if (!list_empty(&shader->cotable_head) || !shader->committed) 401d80efd5cSThomas Hellstrom return 0; 402d80efd5cSThomas Hellstrom 403d80efd5cSThomas Hellstrom cmd = vmw_fifo_reserve_dx(dev_priv, sizeof(*cmd), 404d80efd5cSThomas Hellstrom shader->ctx->id); 405d80efd5cSThomas Hellstrom if (unlikely(cmd == NULL)) { 406d80efd5cSThomas Hellstrom DRM_ERROR("Failed reserving FIFO space for shader " 407d80efd5cSThomas Hellstrom "scrubbing.\n"); 408d80efd5cSThomas Hellstrom return -ENOMEM; 409d80efd5cSThomas Hellstrom } 410d80efd5cSThomas Hellstrom 411d80efd5cSThomas Hellstrom cmd->header.id = SVGA_3D_CMD_DX_BIND_SHADER; 412d80efd5cSThomas Hellstrom cmd->header.size = sizeof(cmd->body); 413d80efd5cSThomas Hellstrom cmd->body.cid = shader->ctx->id; 414d80efd5cSThomas Hellstrom cmd->body.shid = shader->id; 415d80efd5cSThomas Hellstrom cmd->body.mobid = res->backup->base.mem.start; 416d80efd5cSThomas Hellstrom cmd->body.offsetInBytes = res->backup_offset; 417d80efd5cSThomas Hellstrom vmw_fifo_commit(dev_priv, sizeof(*cmd)); 418d80efd5cSThomas Hellstrom 419d80efd5cSThomas Hellstrom vmw_cotable_add_resource(shader->cotable, &shader->cotable_head); 420d80efd5cSThomas Hellstrom 421d80efd5cSThomas Hellstrom return 0; 422d80efd5cSThomas Hellstrom } 423d80efd5cSThomas Hellstrom 424d80efd5cSThomas Hellstrom /** 425d80efd5cSThomas Hellstrom * vmw_dx_shader_create - The DX shader create callback 426d80efd5cSThomas Hellstrom * 427d80efd5cSThomas Hellstrom * @res: The DX shader resource 428d80efd5cSThomas Hellstrom * 429d80efd5cSThomas Hellstrom * The create callback is called as part of resource validation and 430d80efd5cSThomas Hellstrom * makes sure that we unscrub the shader if it's previously been scrubbed. 431d80efd5cSThomas Hellstrom */ 432d80efd5cSThomas Hellstrom static int vmw_dx_shader_create(struct vmw_resource *res) 433d80efd5cSThomas Hellstrom { 434d80efd5cSThomas Hellstrom struct vmw_private *dev_priv = res->dev_priv; 435d80efd5cSThomas Hellstrom struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res); 436d80efd5cSThomas Hellstrom int ret = 0; 437d80efd5cSThomas Hellstrom 438d80efd5cSThomas Hellstrom WARN_ON_ONCE(!shader->committed); 439d80efd5cSThomas Hellstrom 440d80efd5cSThomas Hellstrom if (!list_empty(&res->mob_head)) { 441d80efd5cSThomas Hellstrom mutex_lock(&dev_priv->binding_mutex); 442d80efd5cSThomas Hellstrom ret = vmw_dx_shader_unscrub(res); 443d80efd5cSThomas Hellstrom mutex_unlock(&dev_priv->binding_mutex); 444d80efd5cSThomas Hellstrom } 445d80efd5cSThomas Hellstrom 446d80efd5cSThomas Hellstrom res->id = shader->id; 447d80efd5cSThomas Hellstrom return ret; 448d80efd5cSThomas Hellstrom } 449d80efd5cSThomas Hellstrom 450d80efd5cSThomas Hellstrom /** 451d80efd5cSThomas Hellstrom * vmw_dx_shader_bind - The DX shader bind callback 452d80efd5cSThomas Hellstrom * 453d80efd5cSThomas Hellstrom * @res: The DX shader resource 454d80efd5cSThomas Hellstrom * @val_buf: Pointer to the validate buffer. 455d80efd5cSThomas Hellstrom * 456d80efd5cSThomas Hellstrom */ 457d80efd5cSThomas Hellstrom static int vmw_dx_shader_bind(struct vmw_resource *res, 458d80efd5cSThomas Hellstrom struct ttm_validate_buffer *val_buf) 459d80efd5cSThomas Hellstrom { 460d80efd5cSThomas Hellstrom struct vmw_private *dev_priv = res->dev_priv; 461d80efd5cSThomas Hellstrom struct ttm_buffer_object *bo = val_buf->bo; 462d80efd5cSThomas Hellstrom 463d80efd5cSThomas Hellstrom BUG_ON(bo->mem.mem_type != VMW_PL_MOB); 464d80efd5cSThomas Hellstrom mutex_lock(&dev_priv->binding_mutex); 465d80efd5cSThomas Hellstrom vmw_dx_shader_unscrub(res); 466d80efd5cSThomas Hellstrom mutex_unlock(&dev_priv->binding_mutex); 467d80efd5cSThomas Hellstrom 468d80efd5cSThomas Hellstrom return 0; 469d80efd5cSThomas Hellstrom } 470d80efd5cSThomas Hellstrom 471d80efd5cSThomas Hellstrom /** 472d80efd5cSThomas Hellstrom * vmw_dx_shader_scrub - Have the device unbind a MOB from a DX shader. 473d80efd5cSThomas Hellstrom * 474d80efd5cSThomas Hellstrom * @res: The shader resource 475d80efd5cSThomas Hellstrom * 476d80efd5cSThomas Hellstrom * This function unbinds a MOB from the DX shader without requiring the 477d80efd5cSThomas Hellstrom * MOB dma_buffer to be reserved. The driver still considers the MOB bound. 478d80efd5cSThomas Hellstrom * However, once the driver eventually decides to unbind the MOB, it doesn't 479d80efd5cSThomas Hellstrom * need to access the context. 480d80efd5cSThomas Hellstrom */ 481d80efd5cSThomas Hellstrom static int vmw_dx_shader_scrub(struct vmw_resource *res) 482d80efd5cSThomas Hellstrom { 483d80efd5cSThomas Hellstrom struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res); 484d80efd5cSThomas Hellstrom struct vmw_private *dev_priv = res->dev_priv; 485d80efd5cSThomas Hellstrom struct { 486d80efd5cSThomas Hellstrom SVGA3dCmdHeader header; 487d80efd5cSThomas Hellstrom SVGA3dCmdDXBindShader body; 488d80efd5cSThomas Hellstrom } *cmd; 489d80efd5cSThomas Hellstrom 490d80efd5cSThomas Hellstrom if (list_empty(&shader->cotable_head)) 491d80efd5cSThomas Hellstrom return 0; 492d80efd5cSThomas Hellstrom 493d80efd5cSThomas Hellstrom WARN_ON_ONCE(!shader->committed); 494d80efd5cSThomas Hellstrom cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); 495d80efd5cSThomas Hellstrom if (unlikely(cmd == NULL)) { 496d80efd5cSThomas Hellstrom DRM_ERROR("Failed reserving FIFO space for shader " 497d80efd5cSThomas Hellstrom "scrubbing.\n"); 498d80efd5cSThomas Hellstrom return -ENOMEM; 499d80efd5cSThomas Hellstrom } 500d80efd5cSThomas Hellstrom 501d80efd5cSThomas Hellstrom cmd->header.id = SVGA_3D_CMD_DX_BIND_SHADER; 502d80efd5cSThomas Hellstrom cmd->header.size = sizeof(cmd->body); 503d80efd5cSThomas Hellstrom cmd->body.cid = shader->ctx->id; 504d80efd5cSThomas Hellstrom cmd->body.shid = res->id; 505d80efd5cSThomas Hellstrom cmd->body.mobid = SVGA3D_INVALID_ID; 506d80efd5cSThomas Hellstrom cmd->body.offsetInBytes = 0; 507d80efd5cSThomas Hellstrom vmw_fifo_commit(dev_priv, sizeof(*cmd)); 508d80efd5cSThomas Hellstrom res->id = -1; 509d80efd5cSThomas Hellstrom list_del_init(&shader->cotable_head); 510d80efd5cSThomas Hellstrom 511d80efd5cSThomas Hellstrom return 0; 512d80efd5cSThomas Hellstrom } 513d80efd5cSThomas Hellstrom 514d80efd5cSThomas Hellstrom /** 515d80efd5cSThomas Hellstrom * vmw_dx_shader_unbind - The dx shader unbind callback. 516d80efd5cSThomas Hellstrom * 517d80efd5cSThomas Hellstrom * @res: The shader resource 518d80efd5cSThomas Hellstrom * @readback: Whether this is a readback unbind. Currently unused. 519d80efd5cSThomas Hellstrom * @val_buf: MOB buffer information. 520d80efd5cSThomas Hellstrom */ 521d80efd5cSThomas Hellstrom static int vmw_dx_shader_unbind(struct vmw_resource *res, 522d80efd5cSThomas Hellstrom bool readback, 523d80efd5cSThomas Hellstrom struct ttm_validate_buffer *val_buf) 524d80efd5cSThomas Hellstrom { 525d80efd5cSThomas Hellstrom struct vmw_private *dev_priv = res->dev_priv; 526d80efd5cSThomas Hellstrom struct vmw_fence_obj *fence; 527d80efd5cSThomas Hellstrom int ret; 528d80efd5cSThomas Hellstrom 529d80efd5cSThomas Hellstrom BUG_ON(res->backup->base.mem.mem_type != VMW_PL_MOB); 530d80efd5cSThomas Hellstrom 531d80efd5cSThomas Hellstrom mutex_lock(&dev_priv->binding_mutex); 532d80efd5cSThomas Hellstrom ret = vmw_dx_shader_scrub(res); 533d80efd5cSThomas Hellstrom mutex_unlock(&dev_priv->binding_mutex); 534d80efd5cSThomas Hellstrom 535d80efd5cSThomas Hellstrom if (ret) 536d80efd5cSThomas Hellstrom return ret; 537d80efd5cSThomas Hellstrom 538d80efd5cSThomas Hellstrom (void) vmw_execbuf_fence_commands(NULL, dev_priv, 539d80efd5cSThomas Hellstrom &fence, NULL); 540e9431ea5SThomas Hellstrom vmw_bo_fence_single(val_buf->bo, fence); 541d80efd5cSThomas Hellstrom 542d80efd5cSThomas Hellstrom if (likely(fence != NULL)) 543d80efd5cSThomas Hellstrom vmw_fence_obj_unreference(&fence); 544d80efd5cSThomas Hellstrom 545d80efd5cSThomas Hellstrom return 0; 546d80efd5cSThomas Hellstrom } 547d80efd5cSThomas Hellstrom 548d80efd5cSThomas Hellstrom /** 549d80efd5cSThomas Hellstrom * vmw_dx_shader_cotable_list_scrub - The cotable unbind_func callback for 550d80efd5cSThomas Hellstrom * DX shaders. 551d80efd5cSThomas Hellstrom * 552d80efd5cSThomas Hellstrom * @dev_priv: Pointer to device private structure. 553d80efd5cSThomas Hellstrom * @list: The list of cotable resources. 554d80efd5cSThomas Hellstrom * @readback: Whether the call was part of a readback unbind. 555d80efd5cSThomas Hellstrom * 556d80efd5cSThomas Hellstrom * Scrubs all shader MOBs so that any subsequent shader unbind or shader 557d80efd5cSThomas Hellstrom * destroy operation won't need to swap in the context. 558d80efd5cSThomas Hellstrom */ 559d80efd5cSThomas Hellstrom void vmw_dx_shader_cotable_list_scrub(struct vmw_private *dev_priv, 560d80efd5cSThomas Hellstrom struct list_head *list, 561d80efd5cSThomas Hellstrom bool readback) 562d80efd5cSThomas Hellstrom { 563d80efd5cSThomas Hellstrom struct vmw_dx_shader *entry, *next; 564d80efd5cSThomas Hellstrom 565d80efd5cSThomas Hellstrom WARN_ON_ONCE(!mutex_is_locked(&dev_priv->binding_mutex)); 566d80efd5cSThomas Hellstrom 567d80efd5cSThomas Hellstrom list_for_each_entry_safe(entry, next, list, cotable_head) { 568d80efd5cSThomas Hellstrom WARN_ON(vmw_dx_shader_scrub(&entry->res)); 569d80efd5cSThomas Hellstrom if (!readback) 570d80efd5cSThomas Hellstrom entry->committed = false; 571d80efd5cSThomas Hellstrom } 572d80efd5cSThomas Hellstrom } 573d80efd5cSThomas Hellstrom 574d80efd5cSThomas Hellstrom /** 575d80efd5cSThomas Hellstrom * vmw_dx_shader_res_free - The DX shader free callback 576d80efd5cSThomas Hellstrom * 577d80efd5cSThomas Hellstrom * @res: The shader resource 578d80efd5cSThomas Hellstrom * 579d80efd5cSThomas Hellstrom * Frees the DX shader resource and updates memory accounting. 580d80efd5cSThomas Hellstrom */ 581d80efd5cSThomas Hellstrom static void vmw_dx_shader_res_free(struct vmw_resource *res) 582d80efd5cSThomas Hellstrom { 583d80efd5cSThomas Hellstrom struct vmw_private *dev_priv = res->dev_priv; 584d80efd5cSThomas Hellstrom struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res); 585d80efd5cSThomas Hellstrom 586d80efd5cSThomas Hellstrom vmw_resource_unreference(&shader->cotable); 587d80efd5cSThomas Hellstrom kfree(shader); 588d80efd5cSThomas Hellstrom ttm_mem_global_free(vmw_mem_glob(dev_priv), vmw_shader_dx_size); 589d80efd5cSThomas Hellstrom } 590d80efd5cSThomas Hellstrom 591d80efd5cSThomas Hellstrom /** 592d80efd5cSThomas Hellstrom * vmw_dx_shader_add - Add a shader resource as a command buffer managed 593d80efd5cSThomas Hellstrom * resource. 594d80efd5cSThomas Hellstrom * 595d80efd5cSThomas Hellstrom * @man: The command buffer resource manager. 596d80efd5cSThomas Hellstrom * @ctx: Pointer to the context resource. 597d80efd5cSThomas Hellstrom * @user_key: The id used for this shader. 598d80efd5cSThomas Hellstrom * @shader_type: The shader type. 599d80efd5cSThomas Hellstrom * @list: The list of staged command buffer managed resources. 600d80efd5cSThomas Hellstrom */ 601d80efd5cSThomas Hellstrom int vmw_dx_shader_add(struct vmw_cmdbuf_res_manager *man, 602d80efd5cSThomas Hellstrom struct vmw_resource *ctx, 603d80efd5cSThomas Hellstrom u32 user_key, 604d80efd5cSThomas Hellstrom SVGA3dShaderType shader_type, 605d80efd5cSThomas Hellstrom struct list_head *list) 606d80efd5cSThomas Hellstrom { 607d80efd5cSThomas Hellstrom struct vmw_dx_shader *shader; 608d80efd5cSThomas Hellstrom struct vmw_resource *res; 609d80efd5cSThomas Hellstrom struct vmw_private *dev_priv = ctx->dev_priv; 610279c01f6SRoger He struct ttm_operation_ctx ttm_opt_ctx = { 611279c01f6SRoger He .interruptible = true, 612279c01f6SRoger He .no_wait_gpu = false 613279c01f6SRoger He }; 614d80efd5cSThomas Hellstrom int ret; 615d80efd5cSThomas Hellstrom 616d80efd5cSThomas Hellstrom if (!vmw_shader_dx_size) 617d80efd5cSThomas Hellstrom vmw_shader_dx_size = ttm_round_pot(sizeof(*shader)); 618d80efd5cSThomas Hellstrom 619d80efd5cSThomas Hellstrom if (!vmw_shader_id_ok(user_key, shader_type)) 620d80efd5cSThomas Hellstrom return -EINVAL; 621d80efd5cSThomas Hellstrom 622d80efd5cSThomas Hellstrom ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), vmw_shader_dx_size, 623279c01f6SRoger He &ttm_opt_ctx); 624d80efd5cSThomas Hellstrom if (ret) { 625d80efd5cSThomas Hellstrom if (ret != -ERESTARTSYS) 626d80efd5cSThomas Hellstrom DRM_ERROR("Out of graphics memory for shader " 627d80efd5cSThomas Hellstrom "creation.\n"); 628d80efd5cSThomas Hellstrom return ret; 629d80efd5cSThomas Hellstrom } 630d80efd5cSThomas Hellstrom 631d80efd5cSThomas Hellstrom shader = kmalloc(sizeof(*shader), GFP_KERNEL); 632d80efd5cSThomas Hellstrom if (!shader) { 633d80efd5cSThomas Hellstrom ttm_mem_global_free(vmw_mem_glob(dev_priv), vmw_shader_dx_size); 634d80efd5cSThomas Hellstrom return -ENOMEM; 635d80efd5cSThomas Hellstrom } 636d80efd5cSThomas Hellstrom 637d80efd5cSThomas Hellstrom res = &shader->res; 638d80efd5cSThomas Hellstrom shader->ctx = ctx; 639d80efd5cSThomas Hellstrom shader->cotable = vmw_context_cotable(ctx, SVGA_COTABLE_DXSHADER); 640d80efd5cSThomas Hellstrom shader->id = user_key; 641d80efd5cSThomas Hellstrom shader->committed = false; 642d80efd5cSThomas Hellstrom INIT_LIST_HEAD(&shader->cotable_head); 643d80efd5cSThomas Hellstrom ret = vmw_resource_init(dev_priv, res, true, 644d80efd5cSThomas Hellstrom vmw_dx_shader_res_free, &vmw_dx_shader_func); 645d80efd5cSThomas Hellstrom if (ret) 646d80efd5cSThomas Hellstrom goto out_resource_init; 647d80efd5cSThomas Hellstrom 648d80efd5cSThomas Hellstrom /* 649d80efd5cSThomas Hellstrom * The user_key name-space is not per shader type for DX shaders, 650d80efd5cSThomas Hellstrom * so when hashing, use a single zero shader type. 651d80efd5cSThomas Hellstrom */ 652d80efd5cSThomas Hellstrom ret = vmw_cmdbuf_res_add(man, vmw_cmdbuf_res_shader, 653d80efd5cSThomas Hellstrom vmw_shader_key(user_key, 0), 654d80efd5cSThomas Hellstrom res, list); 655d80efd5cSThomas Hellstrom if (ret) 656d80efd5cSThomas Hellstrom goto out_resource_init; 657d80efd5cSThomas Hellstrom 658d80efd5cSThomas Hellstrom res->id = shader->id; 659d80efd5cSThomas Hellstrom vmw_resource_activate(res, vmw_hw_shader_destroy); 660d80efd5cSThomas Hellstrom 661d80efd5cSThomas Hellstrom out_resource_init: 662d80efd5cSThomas Hellstrom vmw_resource_unreference(&res); 663d80efd5cSThomas Hellstrom 664d80efd5cSThomas Hellstrom return ret; 665d80efd5cSThomas Hellstrom } 666d80efd5cSThomas Hellstrom 667d80efd5cSThomas Hellstrom 668d80efd5cSThomas Hellstrom 669c74c162fSThomas Hellstrom /** 670c74c162fSThomas Hellstrom * User-space shader management: 671c74c162fSThomas Hellstrom */ 672c74c162fSThomas Hellstrom 673c74c162fSThomas Hellstrom static struct vmw_resource * 674c74c162fSThomas Hellstrom vmw_user_shader_base_to_res(struct ttm_base_object *base) 675c74c162fSThomas Hellstrom { 676c74c162fSThomas Hellstrom return &(container_of(base, struct vmw_user_shader, base)-> 677c74c162fSThomas Hellstrom shader.res); 678c74c162fSThomas Hellstrom } 679c74c162fSThomas Hellstrom 680c74c162fSThomas Hellstrom static void vmw_user_shader_free(struct vmw_resource *res) 681c74c162fSThomas Hellstrom { 682c74c162fSThomas Hellstrom struct vmw_user_shader *ushader = 683c74c162fSThomas Hellstrom container_of(res, struct vmw_user_shader, shader.res); 684c74c162fSThomas Hellstrom struct vmw_private *dev_priv = res->dev_priv; 685c74c162fSThomas Hellstrom 686c74c162fSThomas Hellstrom ttm_base_object_kfree(ushader, base); 687c74c162fSThomas Hellstrom ttm_mem_global_free(vmw_mem_glob(dev_priv), 688c74c162fSThomas Hellstrom vmw_user_shader_size); 689c74c162fSThomas Hellstrom } 690c74c162fSThomas Hellstrom 69118e4a466SThomas Hellstrom static void vmw_shader_free(struct vmw_resource *res) 69218e4a466SThomas Hellstrom { 69318e4a466SThomas Hellstrom struct vmw_shader *shader = vmw_res_to_shader(res); 69418e4a466SThomas Hellstrom struct vmw_private *dev_priv = res->dev_priv; 69518e4a466SThomas Hellstrom 69618e4a466SThomas Hellstrom kfree(shader); 69718e4a466SThomas Hellstrom ttm_mem_global_free(vmw_mem_glob(dev_priv), 69818e4a466SThomas Hellstrom vmw_shader_size); 69918e4a466SThomas Hellstrom } 70018e4a466SThomas Hellstrom 701c74c162fSThomas Hellstrom /** 702c74c162fSThomas Hellstrom * This function is called when user space has no more references on the 703c74c162fSThomas Hellstrom * base object. It releases the base-object's reference on the resource object. 704c74c162fSThomas Hellstrom */ 705c74c162fSThomas Hellstrom 706c74c162fSThomas Hellstrom static void vmw_user_shader_base_release(struct ttm_base_object **p_base) 707c74c162fSThomas Hellstrom { 708c74c162fSThomas Hellstrom struct ttm_base_object *base = *p_base; 709c74c162fSThomas Hellstrom struct vmw_resource *res = vmw_user_shader_base_to_res(base); 710c74c162fSThomas Hellstrom 711c74c162fSThomas Hellstrom *p_base = NULL; 712c74c162fSThomas Hellstrom vmw_resource_unreference(&res); 713c74c162fSThomas Hellstrom } 714c74c162fSThomas Hellstrom 715c74c162fSThomas Hellstrom int vmw_shader_destroy_ioctl(struct drm_device *dev, void *data, 716c74c162fSThomas Hellstrom struct drm_file *file_priv) 717c74c162fSThomas Hellstrom { 718c74c162fSThomas Hellstrom struct drm_vmw_shader_arg *arg = (struct drm_vmw_shader_arg *)data; 719c74c162fSThomas Hellstrom struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 720c74c162fSThomas Hellstrom 721c74c162fSThomas Hellstrom return ttm_ref_object_base_unref(tfile, arg->handle, 722c74c162fSThomas Hellstrom TTM_REF_USAGE); 723c74c162fSThomas Hellstrom } 724c74c162fSThomas Hellstrom 72518e4a466SThomas Hellstrom static int vmw_user_shader_alloc(struct vmw_private *dev_priv, 726f1d34bfdSThomas Hellstrom struct vmw_buffer_object *buffer, 727d5bde956SThomas Hellstrom size_t shader_size, 728d5bde956SThomas Hellstrom size_t offset, 729d5bde956SThomas Hellstrom SVGA3dShaderType shader_type, 730d80efd5cSThomas Hellstrom uint8_t num_input_sig, 731d80efd5cSThomas Hellstrom uint8_t num_output_sig, 732d5bde956SThomas Hellstrom struct ttm_object_file *tfile, 733d5bde956SThomas Hellstrom u32 *handle) 734d5bde956SThomas Hellstrom { 735d5bde956SThomas Hellstrom struct vmw_user_shader *ushader; 736d5bde956SThomas Hellstrom struct vmw_resource *res, *tmp; 737279c01f6SRoger He struct ttm_operation_ctx ctx = { 738279c01f6SRoger He .interruptible = true, 739279c01f6SRoger He .no_wait_gpu = false 740279c01f6SRoger He }; 741d5bde956SThomas Hellstrom int ret; 742d5bde956SThomas Hellstrom 743d5bde956SThomas Hellstrom /* 744d5bde956SThomas Hellstrom * Approximate idr memory usage with 128 bytes. It will be limited 745d5bde956SThomas Hellstrom * by maximum number_of shaders anyway. 746d5bde956SThomas Hellstrom */ 747d5bde956SThomas Hellstrom if (unlikely(vmw_user_shader_size == 0)) 748d5bde956SThomas Hellstrom vmw_user_shader_size = 749d5bde956SThomas Hellstrom ttm_round_pot(sizeof(struct vmw_user_shader)) + 128; 750d5bde956SThomas Hellstrom 751d5bde956SThomas Hellstrom ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), 752d5bde956SThomas Hellstrom vmw_user_shader_size, 753279c01f6SRoger He &ctx); 754d5bde956SThomas Hellstrom if (unlikely(ret != 0)) { 755d5bde956SThomas Hellstrom if (ret != -ERESTARTSYS) 756d5bde956SThomas Hellstrom DRM_ERROR("Out of graphics memory for shader " 757d5bde956SThomas Hellstrom "creation.\n"); 758d5bde956SThomas Hellstrom goto out; 759d5bde956SThomas Hellstrom } 760d5bde956SThomas Hellstrom 761d5bde956SThomas Hellstrom ushader = kzalloc(sizeof(*ushader), GFP_KERNEL); 7621a4adb05SRavikant B Sharma if (unlikely(!ushader)) { 763d5bde956SThomas Hellstrom ttm_mem_global_free(vmw_mem_glob(dev_priv), 764d5bde956SThomas Hellstrom vmw_user_shader_size); 765d5bde956SThomas Hellstrom ret = -ENOMEM; 766d5bde956SThomas Hellstrom goto out; 767d5bde956SThomas Hellstrom } 768d5bde956SThomas Hellstrom 769d5bde956SThomas Hellstrom res = &ushader->shader.res; 770d5bde956SThomas Hellstrom ushader->base.shareable = false; 771d5bde956SThomas Hellstrom ushader->base.tfile = NULL; 772d5bde956SThomas Hellstrom 773d5bde956SThomas Hellstrom /* 774d5bde956SThomas Hellstrom * From here on, the destructor takes over resource freeing. 775d5bde956SThomas Hellstrom */ 776d5bde956SThomas Hellstrom 777d5bde956SThomas Hellstrom ret = vmw_gb_shader_init(dev_priv, res, shader_size, 778d80efd5cSThomas Hellstrom offset, shader_type, num_input_sig, 779d80efd5cSThomas Hellstrom num_output_sig, buffer, 780d5bde956SThomas Hellstrom vmw_user_shader_free); 781d5bde956SThomas Hellstrom if (unlikely(ret != 0)) 782d5bde956SThomas Hellstrom goto out; 783d5bde956SThomas Hellstrom 784d5bde956SThomas Hellstrom tmp = vmw_resource_reference(res); 785d5bde956SThomas Hellstrom ret = ttm_base_object_init(tfile, &ushader->base, false, 786d5bde956SThomas Hellstrom VMW_RES_SHADER, 787d5bde956SThomas Hellstrom &vmw_user_shader_base_release, NULL); 788d5bde956SThomas Hellstrom 789d5bde956SThomas Hellstrom if (unlikely(ret != 0)) { 790d5bde956SThomas Hellstrom vmw_resource_unreference(&tmp); 791d5bde956SThomas Hellstrom goto out_err; 792d5bde956SThomas Hellstrom } 793d5bde956SThomas Hellstrom 794d5bde956SThomas Hellstrom if (handle) 795d5bde956SThomas Hellstrom *handle = ushader->base.hash.key; 796d5bde956SThomas Hellstrom out_err: 797d5bde956SThomas Hellstrom vmw_resource_unreference(&res); 798d5bde956SThomas Hellstrom out: 799d5bde956SThomas Hellstrom return ret; 800d5bde956SThomas Hellstrom } 801d5bde956SThomas Hellstrom 802d5bde956SThomas Hellstrom 803b9eb1a61SThomas Hellstrom static struct vmw_resource *vmw_shader_alloc(struct vmw_private *dev_priv, 804f1d34bfdSThomas Hellstrom struct vmw_buffer_object *buffer, 80518e4a466SThomas Hellstrom size_t shader_size, 80618e4a466SThomas Hellstrom size_t offset, 80718e4a466SThomas Hellstrom SVGA3dShaderType shader_type) 80818e4a466SThomas Hellstrom { 80918e4a466SThomas Hellstrom struct vmw_shader *shader; 81018e4a466SThomas Hellstrom struct vmw_resource *res; 811279c01f6SRoger He struct ttm_operation_ctx ctx = { 812279c01f6SRoger He .interruptible = true, 813279c01f6SRoger He .no_wait_gpu = false 814279c01f6SRoger He }; 81518e4a466SThomas Hellstrom int ret; 81618e4a466SThomas Hellstrom 81718e4a466SThomas Hellstrom /* 81818e4a466SThomas Hellstrom * Approximate idr memory usage with 128 bytes. It will be limited 81918e4a466SThomas Hellstrom * by maximum number_of shaders anyway. 82018e4a466SThomas Hellstrom */ 82118e4a466SThomas Hellstrom if (unlikely(vmw_shader_size == 0)) 82218e4a466SThomas Hellstrom vmw_shader_size = 82318e4a466SThomas Hellstrom ttm_round_pot(sizeof(struct vmw_shader)) + 128; 82418e4a466SThomas Hellstrom 82518e4a466SThomas Hellstrom ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), 82618e4a466SThomas Hellstrom vmw_shader_size, 827279c01f6SRoger He &ctx); 82818e4a466SThomas Hellstrom if (unlikely(ret != 0)) { 82918e4a466SThomas Hellstrom if (ret != -ERESTARTSYS) 83018e4a466SThomas Hellstrom DRM_ERROR("Out of graphics memory for shader " 83118e4a466SThomas Hellstrom "creation.\n"); 83218e4a466SThomas Hellstrom goto out_err; 83318e4a466SThomas Hellstrom } 83418e4a466SThomas Hellstrom 83518e4a466SThomas Hellstrom shader = kzalloc(sizeof(*shader), GFP_KERNEL); 8361a4adb05SRavikant B Sharma if (unlikely(!shader)) { 83718e4a466SThomas Hellstrom ttm_mem_global_free(vmw_mem_glob(dev_priv), 83818e4a466SThomas Hellstrom vmw_shader_size); 83918e4a466SThomas Hellstrom ret = -ENOMEM; 84018e4a466SThomas Hellstrom goto out_err; 84118e4a466SThomas Hellstrom } 84218e4a466SThomas Hellstrom 84318e4a466SThomas Hellstrom res = &shader->res; 84418e4a466SThomas Hellstrom 84518e4a466SThomas Hellstrom /* 84618e4a466SThomas Hellstrom * From here on, the destructor takes over resource freeing. 84718e4a466SThomas Hellstrom */ 84818e4a466SThomas Hellstrom ret = vmw_gb_shader_init(dev_priv, res, shader_size, 849d80efd5cSThomas Hellstrom offset, shader_type, 0, 0, buffer, 85018e4a466SThomas Hellstrom vmw_shader_free); 85118e4a466SThomas Hellstrom 85218e4a466SThomas Hellstrom out_err: 85318e4a466SThomas Hellstrom return ret ? ERR_PTR(ret) : res; 85418e4a466SThomas Hellstrom } 85518e4a466SThomas Hellstrom 85618e4a466SThomas Hellstrom 857d80efd5cSThomas Hellstrom static int vmw_shader_define(struct drm_device *dev, struct drm_file *file_priv, 858d80efd5cSThomas Hellstrom enum drm_vmw_shader_type shader_type_drm, 859d80efd5cSThomas Hellstrom u32 buffer_handle, size_t size, size_t offset, 860d80efd5cSThomas Hellstrom uint8_t num_input_sig, uint8_t num_output_sig, 861d80efd5cSThomas Hellstrom uint32_t *shader_handle) 862c74c162fSThomas Hellstrom { 863c74c162fSThomas Hellstrom struct vmw_private *dev_priv = vmw_priv(dev); 864c74c162fSThomas Hellstrom struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 865f1d34bfdSThomas Hellstrom struct vmw_buffer_object *buffer = NULL; 866c74c162fSThomas Hellstrom SVGA3dShaderType shader_type; 867c74c162fSThomas Hellstrom int ret; 868c74c162fSThomas Hellstrom 869d80efd5cSThomas Hellstrom if (buffer_handle != SVGA3D_INVALID_ID) { 870f1d34bfdSThomas Hellstrom ret = vmw_user_bo_lookup(tfile, buffer_handle, 87154c12bc3SThomas Hellstrom &buffer, NULL); 872c74c162fSThomas Hellstrom if (unlikely(ret != 0)) { 873c74c162fSThomas Hellstrom DRM_ERROR("Could not find buffer for shader " 874c74c162fSThomas Hellstrom "creation.\n"); 875c74c162fSThomas Hellstrom return ret; 876c74c162fSThomas Hellstrom } 877c74c162fSThomas Hellstrom 878c74c162fSThomas Hellstrom if ((u64)buffer->base.num_pages * PAGE_SIZE < 879d80efd5cSThomas Hellstrom (u64)size + (u64)offset) { 880c74c162fSThomas Hellstrom DRM_ERROR("Illegal buffer- or shader size.\n"); 881c74c162fSThomas Hellstrom ret = -EINVAL; 882c74c162fSThomas Hellstrom goto out_bad_arg; 883c74c162fSThomas Hellstrom } 884c74c162fSThomas Hellstrom } 885c74c162fSThomas Hellstrom 886d80efd5cSThomas Hellstrom switch (shader_type_drm) { 887c74c162fSThomas Hellstrom case drm_vmw_shader_type_vs: 888c74c162fSThomas Hellstrom shader_type = SVGA3D_SHADERTYPE_VS; 889c74c162fSThomas Hellstrom break; 890c74c162fSThomas Hellstrom case drm_vmw_shader_type_ps: 891c74c162fSThomas Hellstrom shader_type = SVGA3D_SHADERTYPE_PS; 892c74c162fSThomas Hellstrom break; 893c74c162fSThomas Hellstrom default: 894c74c162fSThomas Hellstrom DRM_ERROR("Illegal shader type.\n"); 895c74c162fSThomas Hellstrom ret = -EINVAL; 896c74c162fSThomas Hellstrom goto out_bad_arg; 897c74c162fSThomas Hellstrom } 898c74c162fSThomas Hellstrom 899294adf7dSThomas Hellstrom ret = ttm_read_lock(&dev_priv->reservation_sem, true); 900c74c162fSThomas Hellstrom if (unlikely(ret != 0)) 901d5bde956SThomas Hellstrom goto out_bad_arg; 902c74c162fSThomas Hellstrom 903d80efd5cSThomas Hellstrom ret = vmw_user_shader_alloc(dev_priv, buffer, size, offset, 904d80efd5cSThomas Hellstrom shader_type, num_input_sig, 905d80efd5cSThomas Hellstrom num_output_sig, tfile, shader_handle); 906c74c162fSThomas Hellstrom 907294adf7dSThomas Hellstrom ttm_read_unlock(&dev_priv->reservation_sem); 908c74c162fSThomas Hellstrom out_bad_arg: 909f1d34bfdSThomas Hellstrom vmw_bo_unreference(&buffer); 910d5bde956SThomas Hellstrom return ret; 911d5bde956SThomas Hellstrom } 912c74c162fSThomas Hellstrom 913d5bde956SThomas Hellstrom /** 914d80efd5cSThomas Hellstrom * vmw_shader_id_ok - Check whether a compat shader user key and 91518e4a466SThomas Hellstrom * shader type are within valid bounds. 916d5bde956SThomas Hellstrom * 91718e4a466SThomas Hellstrom * @user_key: User space id of the shader. 91818e4a466SThomas Hellstrom * @shader_type: Shader type. 919d5bde956SThomas Hellstrom * 92018e4a466SThomas Hellstrom * Returns true if valid false if not. 921d5bde956SThomas Hellstrom */ 922d80efd5cSThomas Hellstrom static bool vmw_shader_id_ok(u32 user_key, SVGA3dShaderType shader_type) 923d5bde956SThomas Hellstrom { 92418e4a466SThomas Hellstrom return user_key <= ((1 << 20) - 1) && (unsigned) shader_type < 16; 925d5bde956SThomas Hellstrom } 926d5bde956SThomas Hellstrom 927d5bde956SThomas Hellstrom /** 928d80efd5cSThomas Hellstrom * vmw_shader_key - Compute a hash key suitable for a compat shader. 929d5bde956SThomas Hellstrom * 93018e4a466SThomas Hellstrom * @user_key: User space id of the shader. 93118e4a466SThomas Hellstrom * @shader_type: Shader type. 932d5bde956SThomas Hellstrom * 93318e4a466SThomas Hellstrom * Returns a hash key suitable for a command buffer managed resource 93418e4a466SThomas Hellstrom * manager hash table. 935d5bde956SThomas Hellstrom */ 936d80efd5cSThomas Hellstrom static u32 vmw_shader_key(u32 user_key, SVGA3dShaderType shader_type) 937d5bde956SThomas Hellstrom { 93818e4a466SThomas Hellstrom return user_key | (shader_type << 20); 939d5bde956SThomas Hellstrom } 940d5bde956SThomas Hellstrom 941d5bde956SThomas Hellstrom /** 942d80efd5cSThomas Hellstrom * vmw_shader_remove - Stage a compat shader for removal. 943d5bde956SThomas Hellstrom * 94418e4a466SThomas Hellstrom * @man: Pointer to the compat shader manager identifying the shader namespace. 945d5bde956SThomas Hellstrom * @user_key: The key that is used to identify the shader. The key is 946d5bde956SThomas Hellstrom * unique to the shader type. 947d5bde956SThomas Hellstrom * @shader_type: Shader type. 94818e4a466SThomas Hellstrom * @list: Caller's list of staged command buffer resource actions. 949d5bde956SThomas Hellstrom */ 950d80efd5cSThomas Hellstrom int vmw_shader_remove(struct vmw_cmdbuf_res_manager *man, 951d5bde956SThomas Hellstrom u32 user_key, SVGA3dShaderType shader_type, 952d5bde956SThomas Hellstrom struct list_head *list) 953d5bde956SThomas Hellstrom { 954d80efd5cSThomas Hellstrom struct vmw_resource *dummy; 955d80efd5cSThomas Hellstrom 956d80efd5cSThomas Hellstrom if (!vmw_shader_id_ok(user_key, shader_type)) 957d5bde956SThomas Hellstrom return -EINVAL; 958d5bde956SThomas Hellstrom 959d80efd5cSThomas Hellstrom return vmw_cmdbuf_res_remove(man, vmw_cmdbuf_res_shader, 960d80efd5cSThomas Hellstrom vmw_shader_key(user_key, shader_type), 961d80efd5cSThomas Hellstrom list, &dummy); 962d5bde956SThomas Hellstrom } 963d5bde956SThomas Hellstrom 964d5bde956SThomas Hellstrom /** 96518e4a466SThomas Hellstrom * vmw_compat_shader_add - Create a compat shader and stage it for addition 96618e4a466SThomas Hellstrom * as a command buffer managed resource. 967d5bde956SThomas Hellstrom * 96818e4a466SThomas Hellstrom * @man: Pointer to the compat shader manager identifying the shader namespace. 969d5bde956SThomas Hellstrom * @user_key: The key that is used to identify the shader. The key is 970d5bde956SThomas Hellstrom * unique to the shader type. 971d5bde956SThomas Hellstrom * @bytecode: Pointer to the bytecode of the shader. 972d5bde956SThomas Hellstrom * @shader_type: Shader type. 973d5bde956SThomas Hellstrom * @tfile: Pointer to a struct ttm_object_file that the guest-backed shader is 974d5bde956SThomas Hellstrom * to be created with. 97518e4a466SThomas Hellstrom * @list: Caller's list of staged command buffer resource actions. 976d5bde956SThomas Hellstrom * 977d5bde956SThomas Hellstrom */ 97818e4a466SThomas Hellstrom int vmw_compat_shader_add(struct vmw_private *dev_priv, 97918e4a466SThomas Hellstrom struct vmw_cmdbuf_res_manager *man, 980d5bde956SThomas Hellstrom u32 user_key, const void *bytecode, 981d5bde956SThomas Hellstrom SVGA3dShaderType shader_type, 982d5bde956SThomas Hellstrom size_t size, 983d5bde956SThomas Hellstrom struct list_head *list) 984d5bde956SThomas Hellstrom { 98519be5570SChristian König struct ttm_operation_ctx ctx = { false, true }; 986f1d34bfdSThomas Hellstrom struct vmw_buffer_object *buf; 987d5bde956SThomas Hellstrom struct ttm_bo_kmap_obj map; 988d5bde956SThomas Hellstrom bool is_iomem; 989d5bde956SThomas Hellstrom int ret; 99018e4a466SThomas Hellstrom struct vmw_resource *res; 991d5bde956SThomas Hellstrom 992d80efd5cSThomas Hellstrom if (!vmw_shader_id_ok(user_key, shader_type)) 993d5bde956SThomas Hellstrom return -EINVAL; 994d5bde956SThomas Hellstrom 995d5bde956SThomas Hellstrom /* Allocate and pin a DMA buffer */ 996d5bde956SThomas Hellstrom buf = kzalloc(sizeof(*buf), GFP_KERNEL); 9971a4adb05SRavikant B Sharma if (unlikely(!buf)) 998d5bde956SThomas Hellstrom return -ENOMEM; 999d5bde956SThomas Hellstrom 1000f1d34bfdSThomas Hellstrom ret = vmw_bo_init(dev_priv, buf, size, &vmw_sys_ne_placement, 1001f1d34bfdSThomas Hellstrom true, vmw_bo_bo_free); 1002d5bde956SThomas Hellstrom if (unlikely(ret != 0)) 1003d5bde956SThomas Hellstrom goto out; 1004d5bde956SThomas Hellstrom 1005dfd5e50eSChristian König ret = ttm_bo_reserve(&buf->base, false, true, NULL); 1006d5bde956SThomas Hellstrom if (unlikely(ret != 0)) 1007d5bde956SThomas Hellstrom goto no_reserve; 1008d5bde956SThomas Hellstrom 1009d5bde956SThomas Hellstrom /* Map and copy shader bytecode. */ 1010d5bde956SThomas Hellstrom ret = ttm_bo_kmap(&buf->base, 0, PAGE_ALIGN(size) >> PAGE_SHIFT, 1011d5bde956SThomas Hellstrom &map); 1012d5bde956SThomas Hellstrom if (unlikely(ret != 0)) { 1013d5bde956SThomas Hellstrom ttm_bo_unreserve(&buf->base); 1014d5bde956SThomas Hellstrom goto no_reserve; 1015d5bde956SThomas Hellstrom } 1016d5bde956SThomas Hellstrom 1017d5bde956SThomas Hellstrom memcpy(ttm_kmap_obj_virtual(&map, &is_iomem), bytecode, size); 1018d5bde956SThomas Hellstrom WARN_ON(is_iomem); 1019d5bde956SThomas Hellstrom 1020d5bde956SThomas Hellstrom ttm_bo_kunmap(&map); 102119be5570SChristian König ret = ttm_bo_validate(&buf->base, &vmw_sys_placement, &ctx); 1022d5bde956SThomas Hellstrom WARN_ON(ret != 0); 1023d5bde956SThomas Hellstrom ttm_bo_unreserve(&buf->base); 1024d5bde956SThomas Hellstrom 102518e4a466SThomas Hellstrom res = vmw_shader_alloc(dev_priv, buf, size, 0, shader_type); 1026d5bde956SThomas Hellstrom if (unlikely(ret != 0)) 1027d5bde956SThomas Hellstrom goto no_reserve; 1028d5bde956SThomas Hellstrom 1029d80efd5cSThomas Hellstrom ret = vmw_cmdbuf_res_add(man, vmw_cmdbuf_res_shader, 1030d80efd5cSThomas Hellstrom vmw_shader_key(user_key, shader_type), 103118e4a466SThomas Hellstrom res, list); 103218e4a466SThomas Hellstrom vmw_resource_unreference(&res); 1033d5bde956SThomas Hellstrom no_reserve: 1034f1d34bfdSThomas Hellstrom vmw_bo_unreference(&buf); 1035d5bde956SThomas Hellstrom out: 1036d5bde956SThomas Hellstrom return ret; 1037d5bde956SThomas Hellstrom } 1038d5bde956SThomas Hellstrom 1039d5bde956SThomas Hellstrom /** 1040d80efd5cSThomas Hellstrom * vmw_shader_lookup - Look up a compat shader 1041d5bde956SThomas Hellstrom * 104218e4a466SThomas Hellstrom * @man: Pointer to the command buffer managed resource manager identifying 104318e4a466SThomas Hellstrom * the shader namespace. 104418e4a466SThomas Hellstrom * @user_key: The user space id of the shader. 104518e4a466SThomas Hellstrom * @shader_type: The shader type. 1046d5bde956SThomas Hellstrom * 104718e4a466SThomas Hellstrom * Returns a refcounted pointer to a struct vmw_resource if the shader was 104818e4a466SThomas Hellstrom * found. An error pointer otherwise. 1049d5bde956SThomas Hellstrom */ 105018e4a466SThomas Hellstrom struct vmw_resource * 1051d80efd5cSThomas Hellstrom vmw_shader_lookup(struct vmw_cmdbuf_res_manager *man, 105218e4a466SThomas Hellstrom u32 user_key, 105318e4a466SThomas Hellstrom SVGA3dShaderType shader_type) 1054d5bde956SThomas Hellstrom { 1055d80efd5cSThomas Hellstrom if (!vmw_shader_id_ok(user_key, shader_type)) 105618e4a466SThomas Hellstrom return ERR_PTR(-EINVAL); 1057d5bde956SThomas Hellstrom 1058d80efd5cSThomas Hellstrom return vmw_cmdbuf_res_lookup(man, vmw_cmdbuf_res_shader, 1059d80efd5cSThomas Hellstrom vmw_shader_key(user_key, shader_type)); 1060d80efd5cSThomas Hellstrom } 1061d80efd5cSThomas Hellstrom 1062d80efd5cSThomas Hellstrom int vmw_shader_define_ioctl(struct drm_device *dev, void *data, 1063d80efd5cSThomas Hellstrom struct drm_file *file_priv) 1064d80efd5cSThomas Hellstrom { 1065d80efd5cSThomas Hellstrom struct drm_vmw_shader_create_arg *arg = 1066d80efd5cSThomas Hellstrom (struct drm_vmw_shader_create_arg *)data; 1067d80efd5cSThomas Hellstrom 1068d80efd5cSThomas Hellstrom return vmw_shader_define(dev, file_priv, arg->shader_type, 1069d80efd5cSThomas Hellstrom arg->buffer_handle, 1070d80efd5cSThomas Hellstrom arg->size, arg->offset, 1071d80efd5cSThomas Hellstrom 0, 0, 1072d80efd5cSThomas Hellstrom &arg->shader_handle); 1073c74c162fSThomas Hellstrom } 1074