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.c118
1 files changed, 81 insertions, 37 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index efe2b74c5eb1..9b5ea2ac7ddf 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -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_prime_object_kfree(vmw_user_bo, prime);
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;
@@ -781,54 +815,55 @@ err_ref:
781} 815}
782 816
783 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 */
784int vmw_dumb_create(struct drm_file *file_priv, 829int vmw_dumb_create(struct drm_file *file_priv,
785 struct drm_device *dev, 830 struct drm_device *dev,
786 struct drm_mode_create_dumb *args) 831 struct drm_mode_create_dumb *args)
787{ 832{
788 struct vmw_private *dev_priv = vmw_priv(dev); 833 struct vmw_private *dev_priv = vmw_priv(dev);
789 struct vmw_master *vmaster = vmw_master(file_priv->master); 834 struct vmw_master *vmaster = vmw_master(file_priv->master);
790 struct vmw_user_dma_buffer *vmw_user_bo; 835 struct vmw_dma_buffer *dma_buf;
791 struct ttm_buffer_object *tmp;
792 int ret; 836 int ret;
793 837
794 args->pitch = args->width * ((args->bpp + 7) / 8); 838 args->pitch = args->width * ((args->bpp + 7) / 8);
795 args->size = args->pitch * args->height; 839 args->size = args->pitch * args->height;
796 840
797 vmw_user_bo = kzalloc(sizeof(*vmw_user_bo), GFP_KERNEL);
798 if (vmw_user_bo == NULL)
799 return -ENOMEM;
800
801 ret = ttm_read_lock(&vmaster->lock, true); 841 ret = ttm_read_lock(&vmaster->lock, true);
802 if (ret != 0) { 842 if (unlikely(ret != 0))
803 kfree(vmw_user_bo);
804 return ret; 843 return ret;
805 }
806 844
807 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,
808 &vmw_vram_sys_placement, true, 846 args->size, false, &args->handle,
809 &vmw_user_dmabuf_destroy); 847 &dma_buf);
810 if (ret != 0)
811 goto out_no_dmabuf;
812
813 tmp = ttm_bo_reference(&vmw_user_bo->dma.base);
814 ret = ttm_prime_object_init(vmw_fpriv(file_priv)->tfile,
815 args->size,
816 &vmw_user_bo->prime,
817 false,
818 ttm_buffer_type,
819 &vmw_user_dmabuf_release, NULL);
820 if (unlikely(ret != 0)) 848 if (unlikely(ret != 0))
821 goto out_no_base_object; 849 goto out_no_dmabuf;
822
823 args->handle = vmw_user_bo->prime.base.hash.key;
824 850
825out_no_base_object: 851 vmw_dmabuf_unreference(&dma_buf);
826 ttm_bo_unref(&tmp);
827out_no_dmabuf: 852out_no_dmabuf:
828 ttm_read_unlock(&vmaster->lock); 853 ttm_read_unlock(&vmaster->lock);
829 return ret; 854 return ret;
830} 855}
831 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 */
832int vmw_dumb_map_offset(struct drm_file *file_priv, 867int vmw_dumb_map_offset(struct drm_file *file_priv,
833 struct drm_device *dev, uint32_t handle, 868 struct drm_device *dev, uint32_t handle,
834 uint64_t *offset) 869 uint64_t *offset)
@@ -846,6 +881,15 @@ int vmw_dumb_map_offset(struct drm_file *file_priv,
846 return 0; 881 return 0;
847} 882}
848 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 */
849int vmw_dumb_destroy(struct drm_file *file_priv, 893int vmw_dumb_destroy(struct drm_file *file_priv,
850 struct drm_device *dev, 894 struct drm_device *dev,
851 uint32_t handle) 895 uint32_t handle)