0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #include <drm/ttm/ttm_placement.h>
0029
0030 #include "vmwgfx_drv.h"
0031 #include "vmwgfx_resource_priv.h"
0032 #include "vmwgfx_binding.h"
0033
0034 struct vmw_shader {
0035 struct vmw_resource res;
0036 SVGA3dShaderType type;
0037 uint32_t size;
0038 uint8_t num_input_sig;
0039 uint8_t num_output_sig;
0040 };
0041
0042 struct vmw_user_shader {
0043 struct ttm_base_object base;
0044 struct vmw_shader shader;
0045 };
0046
0047 struct vmw_dx_shader {
0048 struct vmw_resource res;
0049 struct vmw_resource *ctx;
0050 struct vmw_resource *cotable;
0051 u32 id;
0052 bool committed;
0053 struct list_head cotable_head;
0054 };
0055
0056 static void vmw_user_shader_free(struct vmw_resource *res);
0057 static struct vmw_resource *
0058 vmw_user_shader_base_to_res(struct ttm_base_object *base);
0059
0060 static int vmw_gb_shader_create(struct vmw_resource *res);
0061 static int vmw_gb_shader_bind(struct vmw_resource *res,
0062 struct ttm_validate_buffer *val_buf);
0063 static int vmw_gb_shader_unbind(struct vmw_resource *res,
0064 bool readback,
0065 struct ttm_validate_buffer *val_buf);
0066 static int vmw_gb_shader_destroy(struct vmw_resource *res);
0067
0068 static int vmw_dx_shader_create(struct vmw_resource *res);
0069 static int vmw_dx_shader_bind(struct vmw_resource *res,
0070 struct ttm_validate_buffer *val_buf);
0071 static int vmw_dx_shader_unbind(struct vmw_resource *res,
0072 bool readback,
0073 struct ttm_validate_buffer *val_buf);
0074 static void vmw_dx_shader_commit_notify(struct vmw_resource *res,
0075 enum vmw_cmdbuf_res_state state);
0076 static bool vmw_shader_id_ok(u32 user_key, SVGA3dShaderType shader_type);
0077 static u32 vmw_shader_key(u32 user_key, SVGA3dShaderType shader_type);
0078
0079 static const struct vmw_user_resource_conv user_shader_conv = {
0080 .object_type = VMW_RES_SHADER,
0081 .base_obj_to_res = vmw_user_shader_base_to_res,
0082 .res_free = vmw_user_shader_free
0083 };
0084
0085 const struct vmw_user_resource_conv *user_shader_converter =
0086 &user_shader_conv;
0087
0088
0089 static const struct vmw_res_func vmw_gb_shader_func = {
0090 .res_type = vmw_res_shader,
0091 .needs_backup = true,
0092 .may_evict = true,
0093 .prio = 3,
0094 .dirty_prio = 3,
0095 .type_name = "guest backed shaders",
0096 .backup_placement = &vmw_mob_placement,
0097 .create = vmw_gb_shader_create,
0098 .destroy = vmw_gb_shader_destroy,
0099 .bind = vmw_gb_shader_bind,
0100 .unbind = vmw_gb_shader_unbind
0101 };
0102
0103 static const struct vmw_res_func vmw_dx_shader_func = {
0104 .res_type = vmw_res_shader,
0105 .needs_backup = true,
0106 .may_evict = true,
0107 .prio = 3,
0108 .dirty_prio = 3,
0109 .type_name = "dx shaders",
0110 .backup_placement = &vmw_mob_placement,
0111 .create = vmw_dx_shader_create,
0112
0113
0114
0115
0116
0117 .destroy = NULL,
0118 .bind = vmw_dx_shader_bind,
0119 .unbind = vmw_dx_shader_unbind,
0120 .commit_notify = vmw_dx_shader_commit_notify,
0121 };
0122
0123
0124
0125
0126
0127 static inline struct vmw_shader *
0128 vmw_res_to_shader(struct vmw_resource *res)
0129 {
0130 return container_of(res, struct vmw_shader, res);
0131 }
0132
0133
0134
0135
0136
0137
0138
0139 static inline struct vmw_dx_shader *
0140 vmw_res_to_dx_shader(struct vmw_resource *res)
0141 {
0142 return container_of(res, struct vmw_dx_shader, res);
0143 }
0144
0145 static void vmw_hw_shader_destroy(struct vmw_resource *res)
0146 {
0147 if (likely(res->func->destroy))
0148 (void) res->func->destroy(res);
0149 else
0150 res->id = -1;
0151 }
0152
0153
0154 static int vmw_gb_shader_init(struct vmw_private *dev_priv,
0155 struct vmw_resource *res,
0156 uint32_t size,
0157 uint64_t offset,
0158 SVGA3dShaderType type,
0159 uint8_t num_input_sig,
0160 uint8_t num_output_sig,
0161 struct vmw_buffer_object *byte_code,
0162 void (*res_free) (struct vmw_resource *res))
0163 {
0164 struct vmw_shader *shader = vmw_res_to_shader(res);
0165 int ret;
0166
0167 ret = vmw_resource_init(dev_priv, res, true, res_free,
0168 &vmw_gb_shader_func);
0169
0170 if (unlikely(ret != 0)) {
0171 if (res_free)
0172 res_free(res);
0173 else
0174 kfree(res);
0175 return ret;
0176 }
0177
0178 res->backup_size = size;
0179 if (byte_code) {
0180 res->backup = vmw_bo_reference(byte_code);
0181 res->backup_offset = offset;
0182 }
0183 shader->size = size;
0184 shader->type = type;
0185 shader->num_input_sig = num_input_sig;
0186 shader->num_output_sig = num_output_sig;
0187
0188 res->hw_destroy = vmw_hw_shader_destroy;
0189 return 0;
0190 }
0191
0192
0193
0194
0195
0196 static int vmw_gb_shader_create(struct vmw_resource *res)
0197 {
0198 struct vmw_private *dev_priv = res->dev_priv;
0199 struct vmw_shader *shader = vmw_res_to_shader(res);
0200 int ret;
0201 struct {
0202 SVGA3dCmdHeader header;
0203 SVGA3dCmdDefineGBShader body;
0204 } *cmd;
0205
0206 if (likely(res->id != -1))
0207 return 0;
0208
0209 ret = vmw_resource_alloc_id(res);
0210 if (unlikely(ret != 0)) {
0211 DRM_ERROR("Failed to allocate a shader id.\n");
0212 goto out_no_id;
0213 }
0214
0215 if (unlikely(res->id >= VMWGFX_NUM_GB_SHADER)) {
0216 ret = -EBUSY;
0217 goto out_no_fifo;
0218 }
0219
0220 cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));
0221 if (unlikely(cmd == NULL)) {
0222 ret = -ENOMEM;
0223 goto out_no_fifo;
0224 }
0225
0226 cmd->header.id = SVGA_3D_CMD_DEFINE_GB_SHADER;
0227 cmd->header.size = sizeof(cmd->body);
0228 cmd->body.shid = res->id;
0229 cmd->body.type = shader->type;
0230 cmd->body.sizeInBytes = shader->size;
0231 vmw_cmd_commit(dev_priv, sizeof(*cmd));
0232 vmw_fifo_resource_inc(dev_priv);
0233
0234 return 0;
0235
0236 out_no_fifo:
0237 vmw_resource_release_id(res);
0238 out_no_id:
0239 return ret;
0240 }
0241
0242 static int vmw_gb_shader_bind(struct vmw_resource *res,
0243 struct ttm_validate_buffer *val_buf)
0244 {
0245 struct vmw_private *dev_priv = res->dev_priv;
0246 struct {
0247 SVGA3dCmdHeader header;
0248 SVGA3dCmdBindGBShader body;
0249 } *cmd;
0250 struct ttm_buffer_object *bo = val_buf->bo;
0251
0252 BUG_ON(bo->resource->mem_type != VMW_PL_MOB);
0253
0254 cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));
0255 if (unlikely(cmd == NULL))
0256 return -ENOMEM;
0257
0258 cmd->header.id = SVGA_3D_CMD_BIND_GB_SHADER;
0259 cmd->header.size = sizeof(cmd->body);
0260 cmd->body.shid = res->id;
0261 cmd->body.mobid = bo->resource->start;
0262 cmd->body.offsetInBytes = res->backup_offset;
0263 res->backup_dirty = false;
0264 vmw_cmd_commit(dev_priv, sizeof(*cmd));
0265
0266 return 0;
0267 }
0268
0269 static int vmw_gb_shader_unbind(struct vmw_resource *res,
0270 bool readback,
0271 struct ttm_validate_buffer *val_buf)
0272 {
0273 struct vmw_private *dev_priv = res->dev_priv;
0274 struct {
0275 SVGA3dCmdHeader header;
0276 SVGA3dCmdBindGBShader body;
0277 } *cmd;
0278 struct vmw_fence_obj *fence;
0279
0280 BUG_ON(res->backup->base.resource->mem_type != VMW_PL_MOB);
0281
0282 cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));
0283 if (unlikely(cmd == NULL))
0284 return -ENOMEM;
0285
0286 cmd->header.id = SVGA_3D_CMD_BIND_GB_SHADER;
0287 cmd->header.size = sizeof(cmd->body);
0288 cmd->body.shid = res->id;
0289 cmd->body.mobid = SVGA3D_INVALID_ID;
0290 cmd->body.offsetInBytes = 0;
0291 vmw_cmd_commit(dev_priv, sizeof(*cmd));
0292
0293
0294
0295
0296
0297 (void) vmw_execbuf_fence_commands(NULL, dev_priv,
0298 &fence, NULL);
0299
0300 vmw_bo_fence_single(val_buf->bo, fence);
0301
0302 if (likely(fence != NULL))
0303 vmw_fence_obj_unreference(&fence);
0304
0305 return 0;
0306 }
0307
0308 static int vmw_gb_shader_destroy(struct vmw_resource *res)
0309 {
0310 struct vmw_private *dev_priv = res->dev_priv;
0311 struct {
0312 SVGA3dCmdHeader header;
0313 SVGA3dCmdDestroyGBShader body;
0314 } *cmd;
0315
0316 if (likely(res->id == -1))
0317 return 0;
0318
0319 mutex_lock(&dev_priv->binding_mutex);
0320 vmw_binding_res_list_scrub(&res->binding_head);
0321
0322 cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));
0323 if (unlikely(cmd == NULL)) {
0324 mutex_unlock(&dev_priv->binding_mutex);
0325 return -ENOMEM;
0326 }
0327
0328 cmd->header.id = SVGA_3D_CMD_DESTROY_GB_SHADER;
0329 cmd->header.size = sizeof(cmd->body);
0330 cmd->body.shid = res->id;
0331 vmw_cmd_commit(dev_priv, sizeof(*cmd));
0332 mutex_unlock(&dev_priv->binding_mutex);
0333 vmw_resource_release_id(res);
0334 vmw_fifo_resource_dec(dev_priv);
0335
0336 return 0;
0337 }
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351 static void vmw_dx_shader_commit_notify(struct vmw_resource *res,
0352 enum vmw_cmdbuf_res_state state)
0353 {
0354 struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res);
0355 struct vmw_private *dev_priv = res->dev_priv;
0356
0357 if (state == VMW_CMDBUF_RES_ADD) {
0358 mutex_lock(&dev_priv->binding_mutex);
0359 vmw_cotable_add_resource(shader->cotable,
0360 &shader->cotable_head);
0361 shader->committed = true;
0362 res->id = shader->id;
0363 mutex_unlock(&dev_priv->binding_mutex);
0364 } else {
0365 mutex_lock(&dev_priv->binding_mutex);
0366 list_del_init(&shader->cotable_head);
0367 shader->committed = false;
0368 res->id = -1;
0369 mutex_unlock(&dev_priv->binding_mutex);
0370 }
0371 }
0372
0373
0374
0375
0376
0377
0378
0379
0380 static int vmw_dx_shader_unscrub(struct vmw_resource *res)
0381 {
0382 struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res);
0383 struct vmw_private *dev_priv = res->dev_priv;
0384 struct {
0385 SVGA3dCmdHeader header;
0386 SVGA3dCmdDXBindShader body;
0387 } *cmd;
0388
0389 if (!list_empty(&shader->cotable_head) || !shader->committed)
0390 return 0;
0391
0392 cmd = VMW_CMD_CTX_RESERVE(dev_priv, sizeof(*cmd), shader->ctx->id);
0393 if (unlikely(cmd == NULL))
0394 return -ENOMEM;
0395
0396 cmd->header.id = SVGA_3D_CMD_DX_BIND_SHADER;
0397 cmd->header.size = sizeof(cmd->body);
0398 cmd->body.cid = shader->ctx->id;
0399 cmd->body.shid = shader->id;
0400 cmd->body.mobid = res->backup->base.resource->start;
0401 cmd->body.offsetInBytes = res->backup_offset;
0402 vmw_cmd_commit(dev_priv, sizeof(*cmd));
0403
0404 vmw_cotable_add_resource(shader->cotable, &shader->cotable_head);
0405
0406 return 0;
0407 }
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417 static int vmw_dx_shader_create(struct vmw_resource *res)
0418 {
0419 struct vmw_private *dev_priv = res->dev_priv;
0420 struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res);
0421 int ret = 0;
0422
0423 WARN_ON_ONCE(!shader->committed);
0424
0425 if (vmw_resource_mob_attached(res)) {
0426 mutex_lock(&dev_priv->binding_mutex);
0427 ret = vmw_dx_shader_unscrub(res);
0428 mutex_unlock(&dev_priv->binding_mutex);
0429 }
0430
0431 res->id = shader->id;
0432 return ret;
0433 }
0434
0435
0436
0437
0438
0439
0440
0441
0442 static int vmw_dx_shader_bind(struct vmw_resource *res,
0443 struct ttm_validate_buffer *val_buf)
0444 {
0445 struct vmw_private *dev_priv = res->dev_priv;
0446 struct ttm_buffer_object *bo = val_buf->bo;
0447
0448 BUG_ON(bo->resource->mem_type != VMW_PL_MOB);
0449 mutex_lock(&dev_priv->binding_mutex);
0450 vmw_dx_shader_unscrub(res);
0451 mutex_unlock(&dev_priv->binding_mutex);
0452
0453 return 0;
0454 }
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466 static int vmw_dx_shader_scrub(struct vmw_resource *res)
0467 {
0468 struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res);
0469 struct vmw_private *dev_priv = res->dev_priv;
0470 struct {
0471 SVGA3dCmdHeader header;
0472 SVGA3dCmdDXBindShader body;
0473 } *cmd;
0474
0475 if (list_empty(&shader->cotable_head))
0476 return 0;
0477
0478 WARN_ON_ONCE(!shader->committed);
0479 cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));
0480 if (unlikely(cmd == NULL))
0481 return -ENOMEM;
0482
0483 cmd->header.id = SVGA_3D_CMD_DX_BIND_SHADER;
0484 cmd->header.size = sizeof(cmd->body);
0485 cmd->body.cid = shader->ctx->id;
0486 cmd->body.shid = res->id;
0487 cmd->body.mobid = SVGA3D_INVALID_ID;
0488 cmd->body.offsetInBytes = 0;
0489 vmw_cmd_commit(dev_priv, sizeof(*cmd));
0490 res->id = -1;
0491 list_del_init(&shader->cotable_head);
0492
0493 return 0;
0494 }
0495
0496
0497
0498
0499
0500
0501
0502
0503 static int vmw_dx_shader_unbind(struct vmw_resource *res,
0504 bool readback,
0505 struct ttm_validate_buffer *val_buf)
0506 {
0507 struct vmw_private *dev_priv = res->dev_priv;
0508 struct vmw_fence_obj *fence;
0509 int ret;
0510
0511 BUG_ON(res->backup->base.resource->mem_type != VMW_PL_MOB);
0512
0513 mutex_lock(&dev_priv->binding_mutex);
0514 ret = vmw_dx_shader_scrub(res);
0515 mutex_unlock(&dev_priv->binding_mutex);
0516
0517 if (ret)
0518 return ret;
0519
0520 (void) vmw_execbuf_fence_commands(NULL, dev_priv,
0521 &fence, NULL);
0522 vmw_bo_fence_single(val_buf->bo, fence);
0523
0524 if (likely(fence != NULL))
0525 vmw_fence_obj_unreference(&fence);
0526
0527 return 0;
0528 }
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540
0541 void vmw_dx_shader_cotable_list_scrub(struct vmw_private *dev_priv,
0542 struct list_head *list,
0543 bool readback)
0544 {
0545 struct vmw_dx_shader *entry, *next;
0546
0547 lockdep_assert_held_once(&dev_priv->binding_mutex);
0548
0549 list_for_each_entry_safe(entry, next, list, cotable_head) {
0550 WARN_ON(vmw_dx_shader_scrub(&entry->res));
0551 if (!readback)
0552 entry->committed = false;
0553 }
0554 }
0555
0556
0557
0558
0559
0560
0561
0562
0563 static void vmw_dx_shader_res_free(struct vmw_resource *res)
0564 {
0565 struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res);
0566
0567 vmw_resource_unreference(&shader->cotable);
0568 kfree(shader);
0569 }
0570
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580
0581 int vmw_dx_shader_add(struct vmw_cmdbuf_res_manager *man,
0582 struct vmw_resource *ctx,
0583 u32 user_key,
0584 SVGA3dShaderType shader_type,
0585 struct list_head *list)
0586 {
0587 struct vmw_dx_shader *shader;
0588 struct vmw_resource *res;
0589 struct vmw_private *dev_priv = ctx->dev_priv;
0590 int ret;
0591
0592 if (!vmw_shader_id_ok(user_key, shader_type))
0593 return -EINVAL;
0594
0595 shader = kmalloc(sizeof(*shader), GFP_KERNEL);
0596 if (!shader) {
0597 return -ENOMEM;
0598 }
0599
0600 res = &shader->res;
0601 shader->ctx = ctx;
0602 shader->cotable = vmw_resource_reference
0603 (vmw_context_cotable(ctx, SVGA_COTABLE_DXSHADER));
0604 shader->id = user_key;
0605 shader->committed = false;
0606 INIT_LIST_HEAD(&shader->cotable_head);
0607 ret = vmw_resource_init(dev_priv, res, true,
0608 vmw_dx_shader_res_free, &vmw_dx_shader_func);
0609 if (ret)
0610 goto out_resource_init;
0611
0612
0613
0614
0615
0616 ret = vmw_cmdbuf_res_add(man, vmw_cmdbuf_res_shader,
0617 vmw_shader_key(user_key, 0),
0618 res, list);
0619 if (ret)
0620 goto out_resource_init;
0621
0622 res->id = shader->id;
0623 res->hw_destroy = vmw_hw_shader_destroy;
0624
0625 out_resource_init:
0626 vmw_resource_unreference(&res);
0627
0628 return ret;
0629 }
0630
0631
0632
0633
0634
0635
0636
0637 static struct vmw_resource *
0638 vmw_user_shader_base_to_res(struct ttm_base_object *base)
0639 {
0640 return &(container_of(base, struct vmw_user_shader, base)->
0641 shader.res);
0642 }
0643
0644 static void vmw_user_shader_free(struct vmw_resource *res)
0645 {
0646 struct vmw_user_shader *ushader =
0647 container_of(res, struct vmw_user_shader, shader.res);
0648
0649 ttm_base_object_kfree(ushader, base);
0650 }
0651
0652 static void vmw_shader_free(struct vmw_resource *res)
0653 {
0654 struct vmw_shader *shader = vmw_res_to_shader(res);
0655
0656 kfree(shader);
0657 }
0658
0659
0660
0661
0662
0663
0664 static void vmw_user_shader_base_release(struct ttm_base_object **p_base)
0665 {
0666 struct ttm_base_object *base = *p_base;
0667 struct vmw_resource *res = vmw_user_shader_base_to_res(base);
0668
0669 *p_base = NULL;
0670 vmw_resource_unreference(&res);
0671 }
0672
0673 int vmw_shader_destroy_ioctl(struct drm_device *dev, void *data,
0674 struct drm_file *file_priv)
0675 {
0676 struct drm_vmw_shader_arg *arg = (struct drm_vmw_shader_arg *)data;
0677 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
0678
0679 return ttm_ref_object_base_unref(tfile, arg->handle);
0680 }
0681
0682 static int vmw_user_shader_alloc(struct vmw_private *dev_priv,
0683 struct vmw_buffer_object *buffer,
0684 size_t shader_size,
0685 size_t offset,
0686 SVGA3dShaderType shader_type,
0687 uint8_t num_input_sig,
0688 uint8_t num_output_sig,
0689 struct ttm_object_file *tfile,
0690 u32 *handle)
0691 {
0692 struct vmw_user_shader *ushader;
0693 struct vmw_resource *res, *tmp;
0694 int ret;
0695
0696 ushader = kzalloc(sizeof(*ushader), GFP_KERNEL);
0697 if (unlikely(!ushader)) {
0698 ret = -ENOMEM;
0699 goto out;
0700 }
0701
0702 res = &ushader->shader.res;
0703 ushader->base.shareable = false;
0704 ushader->base.tfile = NULL;
0705
0706
0707
0708
0709
0710 ret = vmw_gb_shader_init(dev_priv, res, shader_size,
0711 offset, shader_type, num_input_sig,
0712 num_output_sig, buffer,
0713 vmw_user_shader_free);
0714 if (unlikely(ret != 0))
0715 goto out;
0716
0717 tmp = vmw_resource_reference(res);
0718 ret = ttm_base_object_init(tfile, &ushader->base, false,
0719 VMW_RES_SHADER,
0720 &vmw_user_shader_base_release);
0721
0722 if (unlikely(ret != 0)) {
0723 vmw_resource_unreference(&tmp);
0724 goto out_err;
0725 }
0726
0727 if (handle)
0728 *handle = ushader->base.handle;
0729 out_err:
0730 vmw_resource_unreference(&res);
0731 out:
0732 return ret;
0733 }
0734
0735
0736 static struct vmw_resource *vmw_shader_alloc(struct vmw_private *dev_priv,
0737 struct vmw_buffer_object *buffer,
0738 size_t shader_size,
0739 size_t offset,
0740 SVGA3dShaderType shader_type)
0741 {
0742 struct vmw_shader *shader;
0743 struct vmw_resource *res;
0744 int ret;
0745
0746 shader = kzalloc(sizeof(*shader), GFP_KERNEL);
0747 if (unlikely(!shader)) {
0748 ret = -ENOMEM;
0749 goto out_err;
0750 }
0751
0752 res = &shader->res;
0753
0754
0755
0756
0757 ret = vmw_gb_shader_init(dev_priv, res, shader_size,
0758 offset, shader_type, 0, 0, buffer,
0759 vmw_shader_free);
0760
0761 out_err:
0762 return ret ? ERR_PTR(ret) : res;
0763 }
0764
0765
0766 static int vmw_shader_define(struct drm_device *dev, struct drm_file *file_priv,
0767 enum drm_vmw_shader_type shader_type_drm,
0768 u32 buffer_handle, size_t size, size_t offset,
0769 uint8_t num_input_sig, uint8_t num_output_sig,
0770 uint32_t *shader_handle)
0771 {
0772 struct vmw_private *dev_priv = vmw_priv(dev);
0773 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
0774 struct vmw_buffer_object *buffer = NULL;
0775 SVGA3dShaderType shader_type;
0776 int ret;
0777
0778 if (buffer_handle != SVGA3D_INVALID_ID) {
0779 ret = vmw_user_bo_lookup(file_priv, buffer_handle, &buffer);
0780 if (unlikely(ret != 0)) {
0781 VMW_DEBUG_USER("Couldn't find buffer for shader creation.\n");
0782 return ret;
0783 }
0784
0785 if ((u64)buffer->base.base.size < (u64)size + (u64)offset) {
0786 VMW_DEBUG_USER("Illegal buffer- or shader size.\n");
0787 ret = -EINVAL;
0788 goto out_bad_arg;
0789 }
0790 }
0791
0792 switch (shader_type_drm) {
0793 case drm_vmw_shader_type_vs:
0794 shader_type = SVGA3D_SHADERTYPE_VS;
0795 break;
0796 case drm_vmw_shader_type_ps:
0797 shader_type = SVGA3D_SHADERTYPE_PS;
0798 break;
0799 default:
0800 VMW_DEBUG_USER("Illegal shader type.\n");
0801 ret = -EINVAL;
0802 goto out_bad_arg;
0803 }
0804
0805 ret = vmw_user_shader_alloc(dev_priv, buffer, size, offset,
0806 shader_type, num_input_sig,
0807 num_output_sig, tfile, shader_handle);
0808 out_bad_arg:
0809 vmw_bo_unreference(&buffer);
0810 return ret;
0811 }
0812
0813
0814
0815
0816
0817
0818
0819
0820
0821
0822 static bool vmw_shader_id_ok(u32 user_key, SVGA3dShaderType shader_type)
0823 {
0824 return user_key <= ((1 << 20) - 1) && (unsigned) shader_type < 16;
0825 }
0826
0827
0828
0829
0830
0831
0832
0833
0834
0835
0836 static u32 vmw_shader_key(u32 user_key, SVGA3dShaderType shader_type)
0837 {
0838 return user_key | (shader_type << 20);
0839 }
0840
0841
0842
0843
0844
0845
0846
0847
0848
0849
0850 int vmw_shader_remove(struct vmw_cmdbuf_res_manager *man,
0851 u32 user_key, SVGA3dShaderType shader_type,
0852 struct list_head *list)
0853 {
0854 struct vmw_resource *dummy;
0855
0856 if (!vmw_shader_id_ok(user_key, shader_type))
0857 return -EINVAL;
0858
0859 return vmw_cmdbuf_res_remove(man, vmw_cmdbuf_res_shader,
0860 vmw_shader_key(user_key, shader_type),
0861 list, &dummy);
0862 }
0863
0864
0865
0866
0867
0868
0869
0870
0871
0872
0873
0874
0875
0876
0877
0878 int vmw_compat_shader_add(struct vmw_private *dev_priv,
0879 struct vmw_cmdbuf_res_manager *man,
0880 u32 user_key, const void *bytecode,
0881 SVGA3dShaderType shader_type,
0882 size_t size,
0883 struct list_head *list)
0884 {
0885 struct ttm_operation_ctx ctx = { false, true };
0886 struct vmw_buffer_object *buf;
0887 struct ttm_bo_kmap_obj map;
0888 bool is_iomem;
0889 int ret;
0890 struct vmw_resource *res;
0891
0892 if (!vmw_shader_id_ok(user_key, shader_type))
0893 return -EINVAL;
0894
0895 ret = vmw_bo_create(dev_priv, size, &vmw_sys_placement,
0896 true, true, vmw_bo_bo_free, &buf);
0897 if (unlikely(ret != 0))
0898 goto out;
0899
0900 ret = ttm_bo_reserve(&buf->base, false, true, NULL);
0901 if (unlikely(ret != 0))
0902 goto no_reserve;
0903
0904
0905 ret = ttm_bo_kmap(&buf->base, 0, PFN_UP(size), &map);
0906 if (unlikely(ret != 0)) {
0907 ttm_bo_unreserve(&buf->base);
0908 goto no_reserve;
0909 }
0910
0911 memcpy(ttm_kmap_obj_virtual(&map, &is_iomem), bytecode, size);
0912 WARN_ON(is_iomem);
0913
0914 ttm_bo_kunmap(&map);
0915 ret = ttm_bo_validate(&buf->base, &vmw_sys_placement, &ctx);
0916 WARN_ON(ret != 0);
0917 ttm_bo_unreserve(&buf->base);
0918
0919 res = vmw_shader_alloc(dev_priv, buf, size, 0, shader_type);
0920 if (unlikely(ret != 0))
0921 goto no_reserve;
0922
0923 ret = vmw_cmdbuf_res_add(man, vmw_cmdbuf_res_shader,
0924 vmw_shader_key(user_key, shader_type),
0925 res, list);
0926 vmw_resource_unreference(&res);
0927 no_reserve:
0928 vmw_bo_unreference(&buf);
0929 out:
0930 return ret;
0931 }
0932
0933
0934
0935
0936
0937
0938
0939
0940
0941
0942
0943
0944 struct vmw_resource *
0945 vmw_shader_lookup(struct vmw_cmdbuf_res_manager *man,
0946 u32 user_key,
0947 SVGA3dShaderType shader_type)
0948 {
0949 if (!vmw_shader_id_ok(user_key, shader_type))
0950 return ERR_PTR(-EINVAL);
0951
0952 return vmw_cmdbuf_res_lookup(man, vmw_cmdbuf_res_shader,
0953 vmw_shader_key(user_key, shader_type));
0954 }
0955
0956 int vmw_shader_define_ioctl(struct drm_device *dev, void *data,
0957 struct drm_file *file_priv)
0958 {
0959 struct drm_vmw_shader_create_arg *arg =
0960 (struct drm_vmw_shader_create_arg *)data;
0961
0962 return vmw_shader_define(dev, file_priv, arg->shader_type,
0963 arg->buffer_handle,
0964 arg->size, arg->offset,
0965 0, 0,
0966 &arg->shader_handle);
0967 }