diff options
author | Takashi Iwai <tiwai@suse.de> | 2013-12-19 06:22:11 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-12-19 06:22:11 -0500 |
commit | 356f402da0f989b16e4b6849e88dba5df0e25944 (patch) | |
tree | d1d41d07abf30bdd7fe1498f6eb239eaced6d9b3 /drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | |
parent | 3a6c5d8ad0a9253aafb76df3577edcb68c09b939 (diff) | |
parent | 96b7fe0119b932ad25451d2b6357e727bbe6a309 (diff) |
Merge tag 'asoc-v3.13-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Fixes for v3.13
The fixes here are all driver specific ones, none of which particularly
stand out but all of which are useful to users of those drivers.
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_resource.c')
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 118 |
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 | */ | ||
363 | static 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 | |||
355 | void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo) | 387 | void 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 | ||
394 | static 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 | |||
362 | int vmw_dmabuf_init(struct vmw_private *dev_priv, | 401 | int 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 | ||
386 | static 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 | |||
393 | static void vmw_user_dmabuf_release(struct ttm_base_object **p_base) | 427 | static 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 | */ | ||
784 | int vmw_dumb_create(struct drm_file *file_priv, | 829 | int 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 | ||
825 | out_no_base_object: | 851 | vmw_dmabuf_unreference(&dma_buf); |
826 | ttm_bo_unref(&tmp); | ||
827 | out_no_dmabuf: | 852 | out_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 | */ | ||
832 | int vmw_dumb_map_offset(struct drm_file *file_priv, | 867 | int 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 | */ | ||
849 | int vmw_dumb_destroy(struct drm_file *file_priv, | 893 | int 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) |