Rev 4569 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4569 | Rev 5078 | ||
---|---|---|---|
Line 27... | Line 27... | ||
27 | 27 | ||
28 | #include "vmwgfx_drv.h" |
28 | #include "vmwgfx_drv.h" |
29 | #include "vmwgfx_resource_priv.h" |
29 | #include "vmwgfx_resource_priv.h" |
Line -... | Line 30... | ||
- | 30 | #include "ttm/ttm_placement.h" |
|
- | 31 | ||
- | 32 | #define VMW_COMPAT_SHADER_HT_ORDER 12 |
|
30 | #include "ttm/ttm_placement.h" |
33 | |
31 | 34 | #if 0 |
|
32 | struct vmw_shader { |
35 | struct vmw_shader { |
33 | struct vmw_resource res; |
36 | struct vmw_resource res; |
34 | SVGA3dShaderType type; |
37 | SVGA3dShaderType type; |
Line 38... | Line 41... | ||
38 | struct vmw_user_shader { |
41 | struct vmw_user_shader { |
39 | struct ttm_base_object base; |
42 | struct ttm_base_object base; |
40 | struct vmw_shader shader; |
43 | struct vmw_shader shader; |
41 | }; |
44 | }; |
Line -... | Line 45... | ||
- | 45 | ||
- | 46 | /** |
|
- | 47 | * enum vmw_compat_shader_state - Staging state for compat shaders |
|
- | 48 | */ |
|
- | 49 | enum vmw_compat_shader_state { |
|
- | 50 | VMW_COMPAT_COMMITED, |
|
- | 51 | VMW_COMPAT_ADD, |
|
- | 52 | VMW_COMPAT_DEL |
|
- | 53 | }; |
|
- | 54 | ||
- | 55 | /** |
|
- | 56 | * struct vmw_compat_shader - Metadata for compat shaders. |
|
- | 57 | * |
|
- | 58 | * @handle: The TTM handle of the guest backed shader. |
|
- | 59 | * @tfile: The struct ttm_object_file the guest backed shader is registered |
|
- | 60 | * with. |
|
- | 61 | * @hash: Hash item for lookup. |
|
- | 62 | * @head: List head for staging lists or the compat shader manager list. |
|
- | 63 | * @state: Staging state. |
|
- | 64 | * |
|
- | 65 | * The structure is protected by the cmdbuf lock. |
|
- | 66 | */ |
|
- | 67 | struct vmw_compat_shader { |
|
- | 68 | u32 handle; |
|
- | 69 | struct ttm_object_file *tfile; |
|
- | 70 | struct drm_hash_item hash; |
|
- | 71 | struct list_head head; |
|
- | 72 | enum vmw_compat_shader_state state; |
|
- | 73 | }; |
|
- | 74 | ||
- | 75 | /** |
|
- | 76 | * struct vmw_compat_shader_manager - Compat shader manager. |
|
- | 77 | * |
|
- | 78 | * @shaders: Hash table containing staged and commited compat shaders |
|
- | 79 | * @list: List of commited shaders. |
|
- | 80 | * @dev_priv: Pointer to a device private structure. |
|
- | 81 | * |
|
- | 82 | * @shaders and @list are protected by the cmdbuf mutex for now. |
|
- | 83 | */ |
|
- | 84 | struct vmw_compat_shader_manager { |
|
- | 85 | struct drm_open_hash shaders; |
|
- | 86 | struct list_head list; |
|
- | 87 | struct vmw_private *dev_priv; |
|
- | 88 | }; |
|
42 | 89 | ||
43 | static void vmw_user_shader_free(struct vmw_resource *res); |
90 | static void vmw_user_shader_free(struct vmw_resource *res); |
44 | static struct vmw_resource * |
91 | static struct vmw_resource * |
Line 45... | Line 92... | ||
45 | vmw_user_shader_base_to_res(struct ttm_base_object *base); |
92 | vmw_user_shader_base_to_res(struct ttm_base_object *base); |
Line 50... | Line 97... | ||
50 | static int vmw_gb_shader_unbind(struct vmw_resource *res, |
97 | static int vmw_gb_shader_unbind(struct vmw_resource *res, |
51 | bool readback, |
98 | bool readback, |
52 | struct ttm_validate_buffer *val_buf); |
99 | struct ttm_validate_buffer *val_buf); |
53 | static int vmw_gb_shader_destroy(struct vmw_resource *res); |
100 | static int vmw_gb_shader_destroy(struct vmw_resource *res); |
Line 54... | Line -... | ||
54 | - | ||
55 | static uint64_t vmw_user_shader_size; |
- | |
56 | 101 | ||
57 | static const struct vmw_user_resource_conv user_shader_conv = { |
102 | static const struct vmw_user_resource_conv user_shader_conv = { |
58 | .object_type = VMW_RES_SHADER, |
103 | .object_type = VMW_RES_SHADER, |
59 | .base_obj_to_res = vmw_user_shader_base_to_res, |
104 | .base_obj_to_res = vmw_user_shader_base_to_res, |
60 | .res_free = vmw_user_shader_free |
105 | .res_free = vmw_user_shader_free |
Line 256... | Line 301... | ||
256 | 301 | ||
257 | if (likely(res->id == -1)) |
302 | if (likely(res->id == -1)) |
Line 258... | Line 303... | ||
258 | return 0; |
303 | return 0; |
259 | 304 | ||
Line 260... | Line 305... | ||
260 | mutex_lock(&dev_priv->binding_mutex); |
305 | mutex_lock(&dev_priv->binding_mutex); |
261 | vmw_context_binding_res_list_kill(&res->binding_head); |
306 | vmw_context_binding_res_list_scrub(&res->binding_head); |
262 | 307 | ||
263 | cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); |
308 | cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); |
Line 294... | Line 339... | ||
294 | { |
339 | { |
295 | struct vmw_user_shader *ushader = |
340 | struct vmw_user_shader *ushader = |
296 | container_of(res, struct vmw_user_shader, shader.res); |
341 | container_of(res, struct vmw_user_shader, shader.res); |
297 | struct vmw_private *dev_priv = res->dev_priv; |
342 | struct vmw_private *dev_priv = res->dev_priv; |
Line 298... | Line 343... | ||
298 | 343 | ||
299 | // ttm_base_object_kfree(ushader, base); |
344 | ttm_base_object_kfree(ushader, base); |
300 | // ttm_mem_global_free(vmw_mem_glob(dev_priv), |
345 | ttm_mem_global_free(vmw_mem_glob(dev_priv), |
301 | // vmw_user_shader_size); |
346 | vmw_user_shader_size); |
Line 302... | Line 347... | ||
302 | } |
347 | } |
303 | 348 | ||
304 | /** |
349 | /** |
Line 323... | Line 368... | ||
323 | 368 | ||
324 | return ttm_ref_object_base_unref(tfile, arg->handle, |
369 | return ttm_ref_object_base_unref(tfile, arg->handle, |
325 | TTM_REF_USAGE); |
370 | TTM_REF_USAGE); |
Line -... | Line 371... | ||
- | 371 | } |
|
- | 372 | ||
- | 373 | static int vmw_user_shader_alloc(struct vmw_private *dev_priv, |
|
- | 374 | struct vmw_dma_buffer *buffer, |
|
- | 375 | size_t shader_size, |
|
- | 376 | size_t offset, |
|
- | 377 | SVGA3dShaderType shader_type, |
|
- | 378 | struct ttm_object_file *tfile, |
|
- | 379 | u32 *handle) |
|
- | 380 | { |
|
- | 381 | struct vmw_user_shader *ushader; |
|
- | 382 | struct vmw_resource *res, *tmp; |
|
- | 383 | int ret; |
|
- | 384 | ||
- | 385 | /* |
|
- | 386 | * Approximate idr memory usage with 128 bytes. It will be limited |
|
- | 387 | * by maximum number_of shaders anyway. |
|
- | 388 | */ |
|
- | 389 | if (unlikely(vmw_user_shader_size == 0)) |
|
- | 390 | vmw_user_shader_size = |
|
- | 391 | ttm_round_pot(sizeof(struct vmw_user_shader)) + 128; |
|
- | 392 | ||
- | 393 | ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), |
|
- | 394 | vmw_user_shader_size, |
|
- | 395 | false, true); |
|
- | 396 | if (unlikely(ret != 0)) { |
|
- | 397 | if (ret != -ERESTARTSYS) |
|
- | 398 | DRM_ERROR("Out of graphics memory for shader " |
|
- | 399 | "creation.\n"); |
|
- | 400 | goto out; |
|
- | 401 | } |
|
- | 402 | ||
- | 403 | ushader = kzalloc(sizeof(*ushader), GFP_KERNEL); |
|
- | 404 | if (unlikely(ushader == NULL)) { |
|
- | 405 | ttm_mem_global_free(vmw_mem_glob(dev_priv), |
|
- | 406 | vmw_user_shader_size); |
|
- | 407 | ret = -ENOMEM; |
|
- | 408 | goto out; |
|
- | 409 | } |
|
- | 410 | ||
- | 411 | res = &ushader->shader.res; |
|
- | 412 | ushader->base.shareable = false; |
|
- | 413 | ushader->base.tfile = NULL; |
|
- | 414 | ||
- | 415 | /* |
|
- | 416 | * From here on, the destructor takes over resource freeing. |
|
- | 417 | */ |
|
- | 418 | ||
- | 419 | ret = vmw_gb_shader_init(dev_priv, res, shader_size, |
|
- | 420 | offset, shader_type, buffer, |
|
- | 421 | vmw_user_shader_free); |
|
- | 422 | if (unlikely(ret != 0)) |
|
- | 423 | goto out; |
|
- | 424 | ||
- | 425 | tmp = vmw_resource_reference(res); |
|
- | 426 | ret = ttm_base_object_init(tfile, &ushader->base, false, |
|
- | 427 | VMW_RES_SHADER, |
|
- | 428 | &vmw_user_shader_base_release, NULL); |
|
- | 429 | ||
- | 430 | if (unlikely(ret != 0)) { |
|
- | 431 | vmw_resource_unreference(&tmp); |
|
- | 432 | goto out_err; |
|
- | 433 | } |
|
- | 434 | ||
- | 435 | if (handle) |
|
- | 436 | *handle = ushader->base.hash.key; |
|
326 | } |
437 | out_err: |
- | 438 | vmw_resource_unreference(&res); |
|
- | 439 | out: |
|
- | 440 | return ret; |
|
- | 441 | } |
|
327 | 442 | ||
328 | #if 0 |
443 | |
329 | int vmw_shader_define_ioctl(struct drm_device *dev, void *data, |
444 | int vmw_shader_define_ioctl(struct drm_device *dev, void *data, |
330 | struct drm_file *file_priv) |
445 | struct drm_file *file_priv) |
331 | { |
- | |
332 | struct vmw_private *dev_priv = vmw_priv(dev); |
- | |
333 | struct vmw_user_shader *ushader; |
- | |
334 | struct vmw_resource *res; |
446 | { |
335 | struct vmw_resource *tmp; |
447 | struct vmw_private *dev_priv = vmw_priv(dev); |
336 | struct drm_vmw_shader_create_arg *arg = |
448 | struct drm_vmw_shader_create_arg *arg = |
337 | (struct drm_vmw_shader_create_arg *)data; |
- | |
338 | struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; |
449 | (struct drm_vmw_shader_create_arg *)data; |
339 | struct vmw_master *vmaster = vmw_master(file_priv->master); |
450 | struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; |
340 | struct vmw_dma_buffer *buffer = NULL; |
451 | struct vmw_dma_buffer *buffer = NULL; |
Line 341... | Line 452... | ||
341 | SVGA3dShaderType shader_type; |
452 | SVGA3dShaderType shader_type; |
Line 372... | Line 483... | ||
372 | DRM_ERROR("Illegal shader type.\n"); |
483 | DRM_ERROR("Illegal shader type.\n"); |
373 | ret = -EINVAL; |
484 | ret = -EINVAL; |
374 | goto out_bad_arg; |
485 | goto out_bad_arg; |
375 | } |
486 | } |
Line 376... | Line -... | ||
376 | - | ||
377 | /* |
487 | |
378 | * Approximate idr memory usage with 128 bytes. It will be limited |
488 | ret = ttm_read_lock(&dev_priv->reservation_sem, true); |
379 | * by maximum number_of shaders anyway. |
489 | if (unlikely(ret != 0)) |
Line 380... | Line 490... | ||
380 | */ |
490 | goto out_bad_arg; |
381 | 491 | ||
382 | if (unlikely(vmw_user_shader_size == 0)) |
- | |
Line 383... | Line 492... | ||
383 | vmw_user_shader_size = ttm_round_pot(sizeof(*ushader)) |
492 | ret = vmw_user_shader_alloc(dev_priv, buffer, arg->size, arg->offset, |
- | 493 | shader_type, tfile, &arg->shader_handle); |
|
384 | + 128; |
494 | |
385 | 495 | ttm_read_unlock(&dev_priv->reservation_sem); |
|
- | 496 | out_bad_arg: |
|
Line -... | Line 497... | ||
- | 497 | vmw_dmabuf_unreference(&buffer); |
|
386 | ret = ttm_read_lock(&vmaster->lock, true); |
498 | return ret; |
387 | if (unlikely(ret != 0)) |
499 | } |
- | 500 | ||
388 | return ret; |
501 | /** |
389 | 502 | * vmw_compat_shader_id_ok - Check whether a compat shader user key and |
|
- | 503 | * shader type are within valid bounds. |
|
390 | ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), |
504 | * |
- | 505 | * @user_key: User space id of the shader. |
|
391 | vmw_user_shader_size, |
506 | * @shader_type: Shader type. |
- | 507 | * |
|
392 | false, true); |
508 | * Returns true if valid false if not. |
393 | if (unlikely(ret != 0)) { |
- | |
394 | if (ret != -ERESTARTSYS) |
509 | */ |
Line -... | Line 510... | ||
- | 510 | static bool vmw_compat_shader_id_ok(u32 user_key, SVGA3dShaderType shader_type) |
|
- | 511 | { |
|
- | 512 | return user_key <= ((1 << 20) - 1) && (unsigned) shader_type < 16; |
|
395 | DRM_ERROR("Out of graphics memory for shader" |
513 | } |
396 | " creation.\n"); |
514 | |
- | 515 | /** |
|
397 | goto out_unlock; |
516 | * vmw_compat_shader_key - Compute a hash key suitable for a compat shader. |
398 | } |
517 | * |
399 | 518 | * @user_key: User space id of the shader. |
|
- | 519 | * @shader_type: Shader type. |
|
- | 520 | * |
|
400 | ushader = kzalloc(sizeof(*ushader), GFP_KERNEL); |
521 | * Returns a hash key suitable for a command buffer managed resource |
401 | if (unlikely(ushader == NULL)) { |
522 | * manager hash table. |
Line -... | Line 523... | ||
- | 523 | */ |
|
- | 524 | static u32 vmw_compat_shader_key(u32 user_key, SVGA3dShaderType shader_type) |
|
- | 525 | { |
|
- | 526 | return user_key | (shader_type << 20); |
|
- | 527 | } |
|
402 | ttm_mem_global_free(vmw_mem_glob(dev_priv), |
528 | |
403 | vmw_user_shader_size); |
529 | /** |
- | 530 | * vmw_compat_shader_remove - Stage a compat shader for removal. |
|
- | 531 | * |
|
- | 532 | * @man: Pointer to the compat shader manager identifying the shader namespace. |
|
- | 533 | * @user_key: The key that is used to identify the shader. The key is |
|
404 | ret = -ENOMEM; |
534 | * unique to the shader type. |
- | 535 | * @shader_type: Shader type. |
|
- | 536 | * @list: Caller's list of staged command buffer resource actions. |
|
- | 537 | */ |
|
- | 538 | int vmw_compat_shader_remove(struct vmw_cmdbuf_res_manager *man, |
|
- | 539 | u32 user_key, SVGA3dShaderType shader_type, |
|
- | 540 | struct list_head *list) |
|
- | 541 | { |
|
- | 542 | if (!vmw_compat_shader_id_ok(user_key, shader_type)) |
|
- | 543 | return -EINVAL; |
|
Line 405... | Line 544... | ||
405 | goto out_unlock; |
544 | |
- | 545 | return vmw_cmdbuf_res_remove(man, vmw_cmdbuf_res_compat_shader, |
|
- | 546 | vmw_compat_shader_key(user_key, |
|
- | 547 | shader_type), |
|
- | 548 | list); |
|
- | 549 | } |
|
- | 550 | ||
- | 551 | /** |
|
- | 552 | * vmw_compat_shader_add - Create a compat shader and stage it for addition |
|
- | 553 | * as a command buffer managed resource. |
|
- | 554 | * |
|
406 | } |
555 | * @man: Pointer to the compat shader manager identifying the shader namespace. |
- | 556 | * @user_key: The key that is used to identify the shader. The key is |
|
407 | 557 | * unique to the shader type. |
|
- | 558 | * @bytecode: Pointer to the bytecode of the shader. |
|
- | 559 | * @shader_type: Shader type. |
|
- | 560 | * @tfile: Pointer to a struct ttm_object_file that the guest-backed shader is |
|
- | 561 | * to be created with. |
|
- | 562 | * @list: Caller's list of staged command buffer resource actions. |
|
- | 563 | * |
|
- | 564 | */ |
|
- | 565 | int vmw_compat_shader_add(struct vmw_private *dev_priv, |
|
- | 566 | struct vmw_cmdbuf_res_manager *man, |
|
- | 567 | u32 user_key, const void *bytecode, |
|
- | 568 | SVGA3dShaderType shader_type, |
|
- | 569 | size_t size, |
|
Line 408... | Line 570... | ||
408 | res = &ushader->shader.res; |
570 | struct list_head *list) |
- | 571 | { |
|
- | 572 | struct vmw_dma_buffer *buf; |
|
409 | ushader->base.shareable = false; |
573 | struct ttm_bo_kmap_obj map; |
- | 574 | bool is_iomem; |
|
- | 575 | int ret; |
|
- | 576 | struct vmw_resource *res; |
|
- | 577 | ||
- | 578 | if (!vmw_compat_shader_id_ok(user_key, shader_type)) |
|
410 | ushader->base.tfile = NULL; |
579 | return -EINVAL; |
411 | 580 | ||
412 | /* |
581 | /* Allocate and pin a DMA buffer */ |
Line 413... | Line -... | ||
413 | * From here on, the destructor takes over resource freeing. |
- | |
414 | */ |
582 | buf = kzalloc(sizeof(*buf), GFP_KERNEL); |
415 | 583 | if (unlikely(buf == NULL)) |
|
416 | ret = vmw_gb_shader_init(dev_priv, res, arg->size, |
584 | return -ENOMEM; |
Line -... | Line 585... | ||
- | 585 | ||
- | 586 | ret = vmw_dmabuf_init(dev_priv, buf, size, &vmw_sys_ne_placement, |
|
- | 587 | true, vmw_dmabuf_bo_free); |
|
417 | arg->offset, shader_type, buffer, |
588 | if (unlikely(ret != 0)) |
418 | vmw_user_shader_free); |
589 | goto out; |
419 | if (unlikely(ret != 0)) |
590 | |
420 | goto out_unlock; |
591 | ret = ttm_bo_reserve(&buf->base, false, true, false, NULL); |
Line 421... | Line 592... | ||
421 | 592 | if (unlikely(ret != 0)) |
|
422 | tmp = vmw_resource_reference(res); |
593 | goto no_reserve; |
- | 594 | ||
423 | ret = ttm_base_object_init(tfile, &ushader->base, false, |
595 | /* Map and copy shader bytecode. */ |
- | 596 | ret = ttm_bo_kmap(&buf->base, 0, PAGE_ALIGN(size) >> PAGE_SHIFT, |
|
424 | VMW_RES_SHADER, |
597 | &map); |
425 | &vmw_user_shader_base_release, NULL); |
598 | if (unlikely(ret != 0)) { |
- | 599 | ttm_bo_unreserve(&buf->base); |
|
- | 600 | goto no_reserve; |
|
426 | 601 | } |
|
427 | if (unlikely(ret != 0)) { |
602 | |
Line -... | Line 603... | ||
- | 603 | memcpy(ttm_kmap_obj_virtual(&map, &is_iomem), bytecode, size); |
|
- | 604 | WARN_ON(is_iomem); |
|
- | 605 | ||
- | 606 | ttm_bo_kunmap(&map); |
|
- | 607 | ret = ttm_bo_validate(&buf->base, &vmw_sys_placement, false, true); |
|
- | 608 | WARN_ON(ret != 0); |
|
- | 609 | ttm_bo_unreserve(&buf->base); |
|
428 | vmw_resource_unreference(&tmp); |
610 | |
- | 611 | res = vmw_shader_alloc(dev_priv, buf, size, 0, shader_type); |
|
Line -... | Line 612... | ||
- | 612 | if (unlikely(ret != 0)) |
|
- | 613 | goto no_reserve; |
|
- | 614 | ||
- | 615 | ret = vmw_cmdbuf_res_add(man, vmw_cmdbuf_res_compat_shader, |
|
- | 616 | vmw_compat_shader_key(user_key, shader_type), |
|
- | 617 | res, list); |
|
- | 618 | vmw_resource_unreference(&res); |
|
- | 619 | no_reserve: |
|
- | 620 | vmw_dmabuf_unreference(&buf); |
|
- | 621 | out: |
|
- | 622 | return ret; |
|
- | 623 | } |
|
- | 624 | ||
- | 625 | /** |
|
- | 626 | * vmw_compat_shader_lookup - Look up a compat shader |
|
- | 627 | * |
|
- | 628 | * @man: Pointer to the command buffer managed resource manager identifying |
|
- | 629 | * the shader namespace. |
|
- | 630 | * @user_key: The user space id of the shader. |
|
- | 631 | * @shader_type: The shader type. |
|
- | 632 | * |
|
- | 633 | * Returns a refcounted pointer to a struct vmw_resource if the shader was |
|
429 | goto out_err; |
634 | * found. An error pointer otherwise. |
430 | } |
635 | */ |