aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_resource.c')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_resource.c165
1 files changed, 105 insertions, 60 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index 252501a54def..9b5ea2ac7ddf 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -35,7 +35,7 @@
35#define VMW_RES_EVICT_ERR_COUNT 10 35#define VMW_RES_EVICT_ERR_COUNT 10
36 36
37struct vmw_user_dma_buffer { 37struct vmw_user_dma_buffer {
38 struct ttm_base_object base; 38 struct ttm_prime_object prime;
39 struct vmw_dma_buffer dma; 39 struct vmw_dma_buffer dma;
40}; 40};
41 41
@@ -297,7 +297,7 @@ int vmw_user_resource_lookup_handle(struct vmw_private *dev_priv,
297 if (unlikely(base == NULL)) 297 if (unlikely(base == NULL))
298 return -EINVAL; 298 return -EINVAL;
299 299
300 if (unlikely(base->object_type != converter->object_type)) 300 if (unlikely(ttm_base_object_type(base) != converter->object_type))
301 goto out_bad_resource; 301 goto out_bad_resource;
302 302
303 res = converter->base_obj_to_res(base); 303 res = converter->base_obj_to_res(base);
@@ -352,6 +352,38 @@ int vmw_user_lookup_handle(struct vmw_private *dev_priv,
352/** 352/**
353 * Buffer management. 353 * Buffer management.
354 */ 354 */
355
356/**
357 * vmw_dmabuf_acc_size - Calculate the pinned memory usage of buffers
358 *
359 * @dev_priv: Pointer to a struct vmw_private identifying the device.
360 * @size: The requested buffer size.
361 * @user: Whether this is an ordinary dma buffer or a user dma buffer.
362 */
363static size_t vmw_dmabuf_acc_size(struct vmw_private *dev_priv, size_t size,
364 bool user)
365{
366 static size_t struct_size, user_struct_size;
367 size_t num_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
368 size_t page_array_size = ttm_round_pot(num_pages * sizeof(void *));
369
370 if (unlikely(struct_size == 0)) {
371 size_t backend_size = ttm_round_pot(vmw_tt_size);
372
373 struct_size = backend_size +
374 ttm_round_pot(sizeof(struct vmw_dma_buffer));
375 user_struct_size = backend_size +
376 ttm_round_pot(sizeof(struct vmw_user_dma_buffer));
377 }
378
379 if (dev_priv->map_mode == vmw_dma_alloc_coherent)
380 page_array_size +=
381 ttm_round_pot(num_pages * sizeof(dma_addr_t));
382
383 return ((user) ? user_struct_size : struct_size) +
384 page_array_size;
385}
386
355void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo) 387void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo)
356{ 388{
357 struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo); 389 struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
@@ -359,6 +391,13 @@ void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo)
359 kfree(vmw_bo); 391 kfree(vmw_bo);
360} 392}
361 393
394static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo)
395{
396 struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo);
397
398 ttm_prime_object_kfree(vmw_user_bo, prime);
399}
400
362int vmw_dmabuf_init(struct vmw_private *dev_priv, 401int vmw_dmabuf_init(struct vmw_private *dev_priv,
363 struct vmw_dma_buffer *vmw_bo, 402 struct vmw_dma_buffer *vmw_bo,
364 size_t size, struct ttm_placement *placement, 403 size_t size, struct ttm_placement *placement,
@@ -368,28 +407,23 @@ int vmw_dmabuf_init(struct vmw_private *dev_priv,
368 struct ttm_bo_device *bdev = &dev_priv->bdev; 407 struct ttm_bo_device *bdev = &dev_priv->bdev;
369 size_t acc_size; 408 size_t acc_size;
370 int ret; 409 int ret;
410 bool user = (bo_free == &vmw_user_dmabuf_destroy);
371 411
372 BUG_ON(!bo_free); 412 BUG_ON(!bo_free && (!user && (bo_free != vmw_dmabuf_bo_free)));
373 413
374 acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct vmw_dma_buffer)); 414 acc_size = vmw_dmabuf_acc_size(dev_priv, size, user);
375 memset(vmw_bo, 0, sizeof(*vmw_bo)); 415 memset(vmw_bo, 0, sizeof(*vmw_bo));
376 416
377 INIT_LIST_HEAD(&vmw_bo->res_list); 417 INIT_LIST_HEAD(&vmw_bo->res_list);
378 418
379 ret = ttm_bo_init(bdev, &vmw_bo->base, size, 419 ret = ttm_bo_init(bdev, &vmw_bo->base, size,
380 ttm_bo_type_device, placement, 420 (user) ? ttm_bo_type_device :
421 ttm_bo_type_kernel, placement,
381 0, interruptible, 422 0, interruptible,
382 NULL, acc_size, NULL, bo_free); 423 NULL, acc_size, NULL, bo_free);
383 return ret; 424 return ret;
384} 425}
385 426
386static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo)
387{
388 struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo);
389
390 ttm_base_object_kfree(vmw_user_bo, base);
391}
392
393static void vmw_user_dmabuf_release(struct ttm_base_object **p_base) 427static void vmw_user_dmabuf_release(struct ttm_base_object **p_base)
394{ 428{
395 struct vmw_user_dma_buffer *vmw_user_bo; 429 struct vmw_user_dma_buffer *vmw_user_bo;
@@ -401,7 +435,8 @@ static void vmw_user_dmabuf_release(struct ttm_base_object **p_base)
401 if (unlikely(base == NULL)) 435 if (unlikely(base == NULL))
402 return; 436 return;
403 437
404 vmw_user_bo = container_of(base, struct vmw_user_dma_buffer, base); 438 vmw_user_bo = container_of(base, struct vmw_user_dma_buffer,
439 prime.base);
405 bo = &vmw_user_bo->dma.base; 440 bo = &vmw_user_bo->dma.base;
406 ttm_bo_unref(&bo); 441 ttm_bo_unref(&bo);
407} 442}
@@ -442,18 +477,19 @@ int vmw_user_dmabuf_alloc(struct vmw_private *dev_priv,
442 return ret; 477 return ret;
443 478
444 tmp = ttm_bo_reference(&user_bo->dma.base); 479 tmp = ttm_bo_reference(&user_bo->dma.base);
445 ret = ttm_base_object_init(tfile, 480 ret = ttm_prime_object_init(tfile,
446 &user_bo->base, 481 size,
447 shareable, 482 &user_bo->prime,
448 ttm_buffer_type, 483 shareable,
449 &vmw_user_dmabuf_release, NULL); 484 ttm_buffer_type,
485 &vmw_user_dmabuf_release, NULL);
450 if (unlikely(ret != 0)) { 486 if (unlikely(ret != 0)) {
451 ttm_bo_unref(&tmp); 487 ttm_bo_unref(&tmp);
452 goto out_no_base_object; 488 goto out_no_base_object;
453 } 489 }
454 490
455 *p_dma_buf = &user_bo->dma; 491 *p_dma_buf = &user_bo->dma;
456 *handle = user_bo->base.hash.key; 492 *handle = user_bo->prime.base.hash.key;
457 493
458out_no_base_object: 494out_no_base_object:
459 return ret; 495 return ret;
@@ -475,8 +511,8 @@ int vmw_user_dmabuf_verify_access(struct ttm_buffer_object *bo,
475 return -EPERM; 511 return -EPERM;
476 512
477 vmw_user_bo = vmw_user_dma_buffer(bo); 513 vmw_user_bo = vmw_user_dma_buffer(bo);
478 return (vmw_user_bo->base.tfile == tfile || 514 return (vmw_user_bo->prime.base.tfile == tfile ||
479 vmw_user_bo->base.shareable) ? 0 : -EPERM; 515 vmw_user_bo->prime.base.shareable) ? 0 : -EPERM;
480} 516}
481 517
482int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data, 518int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,
@@ -538,14 +574,15 @@ int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile,
538 return -ESRCH; 574 return -ESRCH;
539 } 575 }
540 576
541 if (unlikely(base->object_type != ttm_buffer_type)) { 577 if (unlikely(ttm_base_object_type(base) != ttm_buffer_type)) {
542 ttm_base_object_unref(&base); 578 ttm_base_object_unref(&base);
543 printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n", 579 printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n",
544 (unsigned long)handle); 580 (unsigned long)handle);
545 return -EINVAL; 581 return -EINVAL;
546 } 582 }
547 583
548 vmw_user_bo = container_of(base, struct vmw_user_dma_buffer, base); 584 vmw_user_bo = container_of(base, struct vmw_user_dma_buffer,
585 prime.base);
549 (void)ttm_bo_reference(&vmw_user_bo->dma.base); 586 (void)ttm_bo_reference(&vmw_user_bo->dma.base);
550 ttm_base_object_unref(&base); 587 ttm_base_object_unref(&base);
551 *out = &vmw_user_bo->dma; 588 *out = &vmw_user_bo->dma;
@@ -562,7 +599,8 @@ int vmw_user_dmabuf_reference(struct ttm_object_file *tfile,
562 return -EINVAL; 599 return -EINVAL;
563 600
564 user_bo = container_of(dma_buf, struct vmw_user_dma_buffer, dma); 601 user_bo = container_of(dma_buf, struct vmw_user_dma_buffer, dma);
565 return ttm_ref_object_add(tfile, &user_bo->base, TTM_REF_USAGE, NULL); 602 return ttm_ref_object_add(tfile, &user_bo->prime.base,
603 TTM_REF_USAGE, NULL);
566} 604}
567 605
568/* 606/*
@@ -777,53 +815,55 @@ err_ref:
777} 815}
778 816
779 817
818/**
819 * vmw_dumb_create - Create a dumb kms buffer
820 *
821 * @file_priv: Pointer to a struct drm_file identifying the caller.
822 * @dev: Pointer to the drm device.
823 * @args: Pointer to a struct drm_mode_create_dumb structure
824 *
825 * This is a driver callback for the core drm create_dumb functionality.
826 * Note that this is very similar to the vmw_dmabuf_alloc ioctl, except
827 * that the arguments have a different format.
828 */
780int vmw_dumb_create(struct drm_file *file_priv, 829int vmw_dumb_create(struct drm_file *file_priv,
781 struct drm_device *dev, 830 struct drm_device *dev,
782 struct drm_mode_create_dumb *args) 831 struct drm_mode_create_dumb *args)
783{ 832{
784 struct vmw_private *dev_priv = vmw_priv(dev); 833 struct vmw_private *dev_priv = vmw_priv(dev);
785 struct vmw_master *vmaster = vmw_master(file_priv->master); 834 struct vmw_master *vmaster = vmw_master(file_priv->master);
786 struct vmw_user_dma_buffer *vmw_user_bo; 835 struct vmw_dma_buffer *dma_buf;
787 struct ttm_buffer_object *tmp;
788 int ret; 836 int ret;
789 837
790 args->pitch = args->width * ((args->bpp + 7) / 8); 838 args->pitch = args->width * ((args->bpp + 7) / 8);
791 args->size = args->pitch * args->height; 839 args->size = args->pitch * args->height;
792 840
793 vmw_user_bo = kzalloc(sizeof(*vmw_user_bo), GFP_KERNEL);
794 if (vmw_user_bo == NULL)
795 return -ENOMEM;
796
797 ret = ttm_read_lock(&vmaster->lock, true); 841 ret = ttm_read_lock(&vmaster->lock, true);
798 if (ret != 0) { 842 if (unlikely(ret != 0))
799 kfree(vmw_user_bo);
800 return ret; 843 return ret;
801 }
802 844
803 ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, args->size, 845 ret = vmw_user_dmabuf_alloc(dev_priv, vmw_fpriv(file_priv)->tfile,
804 &vmw_vram_sys_placement, true, 846 args->size, false, &args->handle,
805 &vmw_user_dmabuf_destroy); 847 &dma_buf);
806 if (ret != 0)
807 goto out_no_dmabuf;
808
809 tmp = ttm_bo_reference(&vmw_user_bo->dma.base);
810 ret = ttm_base_object_init(vmw_fpriv(file_priv)->tfile,
811 &vmw_user_bo->base,
812 false,
813 ttm_buffer_type,
814 &vmw_user_dmabuf_release, NULL);
815 if (unlikely(ret != 0)) 848 if (unlikely(ret != 0))
816 goto out_no_base_object; 849 goto out_no_dmabuf;
817
818 args->handle = vmw_user_bo->base.hash.key;
819 850
820out_no_base_object: 851 vmw_dmabuf_unreference(&dma_buf);
821 ttm_bo_unref(&tmp);
822out_no_dmabuf: 852out_no_dmabuf:
823 ttm_read_unlock(&vmaster->lock); 853 ttm_read_unlock(&vmaster->lock);
824 return ret; 854 return ret;
825} 855}
826 856
857/**
858 * vmw_dumb_map_offset - Return the address space offset of a dumb buffer
859 *
860 * @file_priv: Pointer to a struct drm_file identifying the caller.
861 * @dev: Pointer to the drm device.
862 * @handle: Handle identifying the dumb buffer.
863 * @offset: The address space offset returned.
864 *
865 * This is a driver callback for the core drm dumb_map_offset functionality.
866 */
827int vmw_dumb_map_offset(struct drm_file *file_priv, 867int vmw_dumb_map_offset(struct drm_file *file_priv,
828 struct drm_device *dev, uint32_t handle, 868 struct drm_device *dev, uint32_t handle,
829 uint64_t *offset) 869 uint64_t *offset)
@@ -841,6 +881,15 @@ int vmw_dumb_map_offset(struct drm_file *file_priv,
841 return 0; 881 return 0;
842} 882}
843 883
884/**
885 * vmw_dumb_destroy - Destroy a dumb boffer
886 *
887 * @file_priv: Pointer to a struct drm_file identifying the caller.
888 * @dev: Pointer to the drm device.
889 * @handle: Handle identifying the dumb buffer.
890 *
891 * This is a driver callback for the core drm dumb_destroy functionality.
892 */
844int vmw_dumb_destroy(struct drm_file *file_priv, 893int vmw_dumb_destroy(struct drm_file *file_priv,
845 struct drm_device *dev, 894 struct drm_device *dev,
846 uint32_t handle) 895 uint32_t handle)
@@ -994,7 +1043,6 @@ void vmw_resource_unreserve(struct vmw_resource *res,
994 */ 1043 */
995static int 1044static int
996vmw_resource_check_buffer(struct vmw_resource *res, 1045vmw_resource_check_buffer(struct vmw_resource *res,
997 struct ww_acquire_ctx *ticket,
998 bool interruptible, 1046 bool interruptible,
999 struct ttm_validate_buffer *val_buf) 1047 struct ttm_validate_buffer *val_buf)
1000{ 1048{
@@ -1011,7 +1059,7 @@ vmw_resource_check_buffer(struct vmw_resource *res,
1011 INIT_LIST_HEAD(&val_list); 1059 INIT_LIST_HEAD(&val_list);
1012 val_buf->bo = ttm_bo_reference(&res->backup->base); 1060 val_buf->bo = ttm_bo_reference(&res->backup->base);
1013 list_add_tail(&val_buf->head, &val_list); 1061 list_add_tail(&val_buf->head, &val_list);
1014 ret = ttm_eu_reserve_buffers(ticket, &val_list); 1062 ret = ttm_eu_reserve_buffers(NULL, &val_list);
1015 if (unlikely(ret != 0)) 1063 if (unlikely(ret != 0))
1016 goto out_no_reserve; 1064 goto out_no_reserve;
1017 1065
@@ -1029,7 +1077,7 @@ vmw_resource_check_buffer(struct vmw_resource *res,
1029 return 0; 1077 return 0;
1030 1078
1031out_no_validate: 1079out_no_validate:
1032 ttm_eu_backoff_reservation(ticket, &val_list); 1080 ttm_eu_backoff_reservation(NULL, &val_list);
1033out_no_reserve: 1081out_no_reserve:
1034 ttm_bo_unref(&val_buf->bo); 1082 ttm_bo_unref(&val_buf->bo);
1035 if (backup_dirty) 1083 if (backup_dirty)
@@ -1074,8 +1122,7 @@ int vmw_resource_reserve(struct vmw_resource *res, bool no_backup)
1074 * @val_buf: Backup buffer information. 1122 * @val_buf: Backup buffer information.
1075 */ 1123 */
1076static void 1124static void
1077vmw_resource_backoff_reservation(struct ww_acquire_ctx *ticket, 1125vmw_resource_backoff_reservation(struct ttm_validate_buffer *val_buf)
1078 struct ttm_validate_buffer *val_buf)
1079{ 1126{
1080 struct list_head val_list; 1127 struct list_head val_list;
1081 1128
@@ -1084,7 +1131,7 @@ vmw_resource_backoff_reservation(struct ww_acquire_ctx *ticket,
1084 1131
1085 INIT_LIST_HEAD(&val_list); 1132 INIT_LIST_HEAD(&val_list);
1086 list_add_tail(&val_buf->head, &val_list); 1133 list_add_tail(&val_buf->head, &val_list);
1087 ttm_eu_backoff_reservation(ticket, &val_list); 1134 ttm_eu_backoff_reservation(NULL, &val_list);
1088 ttm_bo_unref(&val_buf->bo); 1135 ttm_bo_unref(&val_buf->bo);
1089} 1136}
1090 1137
@@ -1099,14 +1146,12 @@ int vmw_resource_do_evict(struct vmw_resource *res, bool interruptible)
1099{ 1146{
1100 struct ttm_validate_buffer val_buf; 1147 struct ttm_validate_buffer val_buf;
1101 const struct vmw_res_func *func = res->func; 1148 const struct vmw_res_func *func = res->func;
1102 struct ww_acquire_ctx ticket;
1103 int ret; 1149 int ret;
1104 1150
1105 BUG_ON(!func->may_evict); 1151 BUG_ON(!func->may_evict);
1106 1152
1107 val_buf.bo = NULL; 1153 val_buf.bo = NULL;
1108 ret = vmw_resource_check_buffer(res, &ticket, interruptible, 1154 ret = vmw_resource_check_buffer(res, interruptible, &val_buf);
1109 &val_buf);
1110 if (unlikely(ret != 0)) 1155 if (unlikely(ret != 0))
1111 return ret; 1156 return ret;
1112 1157
@@ -1121,7 +1166,7 @@ int vmw_resource_do_evict(struct vmw_resource *res, bool interruptible)
1121 res->backup_dirty = true; 1166 res->backup_dirty = true;
1122 res->res_dirty = false; 1167 res->res_dirty = false;
1123out_no_unbind: 1168out_no_unbind:
1124 vmw_resource_backoff_reservation(&ticket, &val_buf); 1169 vmw_resource_backoff_reservation(&val_buf);
1125 1170
1126 return ret; 1171 return ret;
1127} 1172}