diff options
author | Felix Kuehling <Felix.Kuehling@amd.com> | 2018-11-20 21:00:29 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2018-12-07 18:13:54 -0500 |
commit | 1dde0ea95b782425b95455d487cb44991525a1d1 (patch) | |
tree | 2033a93a0417699fca78f5e42f1a7512e80c5a76 /drivers/gpu/drm/amd/amdgpu | |
parent | 3704d56e1a64bb0e951815f91149ae7bb726aa76 (diff) |
drm/amdkfd: Add DMABuf import functionality
This is used for interoperability between ROCm compute and graphics
APIs. It allows importing graphics driver BOs into the ROCm SVM
address space for zero-copy GPU access.
The API is split into two steps (query and import) to allow user mode
to manage the virtual address space allocation for the imported buffer.
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 57 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 55 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c | 4 |
5 files changed, 126 insertions, 3 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index 68b29a210eaa..68e4cf1b655c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include "amdgpu.h" | 26 | #include "amdgpu.h" |
27 | #include "amdgpu_gfx.h" | 27 | #include "amdgpu_gfx.h" |
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/dma-buf.h> | ||
29 | 30 | ||
30 | const struct kgd2kfd_calls *kgd2kfd; | 31 | const struct kgd2kfd_calls *kgd2kfd; |
31 | 32 | ||
@@ -433,6 +434,62 @@ void amdgpu_amdkfd_get_cu_info(struct kgd_dev *kgd, struct kfd_cu_info *cu_info) | |||
433 | cu_info->lds_size = acu_info.lds_size; | 434 | cu_info->lds_size = acu_info.lds_size; |
434 | } | 435 | } |
435 | 436 | ||
437 | int amdgpu_amdkfd_get_dmabuf_info(struct kgd_dev *kgd, int dma_buf_fd, | ||
438 | struct kgd_dev **dma_buf_kgd, | ||
439 | uint64_t *bo_size, void *metadata_buffer, | ||
440 | size_t buffer_size, uint32_t *metadata_size, | ||
441 | uint32_t *flags) | ||
442 | { | ||
443 | struct amdgpu_device *adev = (struct amdgpu_device *)kgd; | ||
444 | struct dma_buf *dma_buf; | ||
445 | struct drm_gem_object *obj; | ||
446 | struct amdgpu_bo *bo; | ||
447 | uint64_t metadata_flags; | ||
448 | int r = -EINVAL; | ||
449 | |||
450 | dma_buf = dma_buf_get(dma_buf_fd); | ||
451 | if (IS_ERR(dma_buf)) | ||
452 | return PTR_ERR(dma_buf); | ||
453 | |||
454 | if (dma_buf->ops != &amdgpu_dmabuf_ops) | ||
455 | /* Can't handle non-graphics buffers */ | ||
456 | goto out_put; | ||
457 | |||
458 | obj = dma_buf->priv; | ||
459 | if (obj->dev->driver != adev->ddev->driver) | ||
460 | /* Can't handle buffers from different drivers */ | ||
461 | goto out_put; | ||
462 | |||
463 | adev = obj->dev->dev_private; | ||
464 | bo = gem_to_amdgpu_bo(obj); | ||
465 | if (!(bo->preferred_domains & (AMDGPU_GEM_DOMAIN_VRAM | | ||
466 | AMDGPU_GEM_DOMAIN_GTT))) | ||
467 | /* Only VRAM and GTT BOs are supported */ | ||
468 | goto out_put; | ||
469 | |||
470 | r = 0; | ||
471 | if (dma_buf_kgd) | ||
472 | *dma_buf_kgd = (struct kgd_dev *)adev; | ||
473 | if (bo_size) | ||
474 | *bo_size = amdgpu_bo_size(bo); | ||
475 | if (metadata_size) | ||
476 | *metadata_size = bo->metadata_size; | ||
477 | if (metadata_buffer) | ||
478 | r = amdgpu_bo_get_metadata(bo, metadata_buffer, buffer_size, | ||
479 | metadata_size, &metadata_flags); | ||
480 | if (flags) { | ||
481 | *flags = (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM) ? | ||
482 | ALLOC_MEM_FLAGS_VRAM : ALLOC_MEM_FLAGS_GTT; | ||
483 | |||
484 | if (bo->flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) | ||
485 | *flags |= ALLOC_MEM_FLAGS_PUBLIC; | ||
486 | } | ||
487 | |||
488 | out_put: | ||
489 | dma_buf_put(dma_buf); | ||
490 | return r; | ||
491 | } | ||
492 | |||
436 | uint64_t amdgpu_amdkfd_get_vram_usage(struct kgd_dev *kgd) | 493 | uint64_t amdgpu_amdkfd_get_vram_usage(struct kgd_dev *kgd) |
437 | { | 494 | { |
438 | struct amdgpu_device *adev = (struct amdgpu_device *)kgd; | 495 | struct amdgpu_device *adev = (struct amdgpu_device *)kgd; |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h index 131c6e5e6f10..70429f7aa9a8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | |||
@@ -149,6 +149,11 @@ uint64_t amdgpu_amdkfd_get_gpu_clock_counter(struct kgd_dev *kgd); | |||
149 | 149 | ||
150 | uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct kgd_dev *kgd); | 150 | uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct kgd_dev *kgd); |
151 | void amdgpu_amdkfd_get_cu_info(struct kgd_dev *kgd, struct kfd_cu_info *cu_info); | 151 | void amdgpu_amdkfd_get_cu_info(struct kgd_dev *kgd, struct kfd_cu_info *cu_info); |
152 | int amdgpu_amdkfd_get_dmabuf_info(struct kgd_dev *kgd, int dma_buf_fd, | ||
153 | struct kgd_dev **dmabuf_kgd, | ||
154 | uint64_t *bo_size, void *metadata_buffer, | ||
155 | size_t buffer_size, uint32_t *metadata_size, | ||
156 | uint32_t *flags); | ||
152 | uint64_t amdgpu_amdkfd_get_vram_usage(struct kgd_dev *kgd); | 157 | uint64_t amdgpu_amdkfd_get_vram_usage(struct kgd_dev *kgd); |
153 | uint64_t amdgpu_amdkfd_get_hive_id(struct kgd_dev *kgd); | 158 | uint64_t amdgpu_amdkfd_get_hive_id(struct kgd_dev *kgd); |
154 | 159 | ||
@@ -200,6 +205,12 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *process_info, | |||
200 | int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct kgd_dev *kgd, | 205 | int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct kgd_dev *kgd, |
201 | struct kfd_vm_fault_info *info); | 206 | struct kfd_vm_fault_info *info); |
202 | 207 | ||
208 | int amdgpu_amdkfd_gpuvm_import_dmabuf(struct kgd_dev *kgd, | ||
209 | struct dma_buf *dmabuf, | ||
210 | uint64_t va, void *vm, | ||
211 | struct kgd_mem **mem, uint64_t *size, | ||
212 | uint64_t *mmap_offset); | ||
213 | |||
203 | void amdgpu_amdkfd_gpuvm_init_mem_limits(void); | 214 | void amdgpu_amdkfd_gpuvm_init_mem_limits(void); |
204 | void amdgpu_amdkfd_unreserve_memory_limit(struct amdgpu_bo *bo); | 215 | void amdgpu_amdkfd_unreserve_memory_limit(struct amdgpu_bo *bo); |
205 | 216 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 5fb60e1d713a..a0a500d45886 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/list.h> | 25 | #include <linux/list.h> |
26 | #include <linux/pagemap.h> | 26 | #include <linux/pagemap.h> |
27 | #include <linux/sched/mm.h> | 27 | #include <linux/sched/mm.h> |
28 | #include <linux/dma-buf.h> | ||
28 | #include <drm/drmP.h> | 29 | #include <drm/drmP.h> |
29 | #include "amdgpu_object.h" | 30 | #include "amdgpu_object.h" |
30 | #include "amdgpu_vm.h" | 31 | #include "amdgpu_vm.h" |
@@ -1664,6 +1665,60 @@ int amdgpu_amdkfd_gpuvm_get_vm_fault_info(struct kgd_dev *kgd, | |||
1664 | return 0; | 1665 | return 0; |
1665 | } | 1666 | } |
1666 | 1667 | ||
1668 | int amdgpu_amdkfd_gpuvm_import_dmabuf(struct kgd_dev *kgd, | ||
1669 | struct dma_buf *dma_buf, | ||
1670 | uint64_t va, void *vm, | ||
1671 | struct kgd_mem **mem, uint64_t *size, | ||
1672 | uint64_t *mmap_offset) | ||
1673 | { | ||
1674 | struct amdgpu_device *adev = (struct amdgpu_device *)kgd; | ||
1675 | struct drm_gem_object *obj; | ||
1676 | struct amdgpu_bo *bo; | ||
1677 | struct amdgpu_vm *avm = (struct amdgpu_vm *)vm; | ||
1678 | |||
1679 | if (dma_buf->ops != &amdgpu_dmabuf_ops) | ||
1680 | /* Can't handle non-graphics buffers */ | ||
1681 | return -EINVAL; | ||
1682 | |||
1683 | obj = dma_buf->priv; | ||
1684 | if (obj->dev->dev_private != adev) | ||
1685 | /* Can't handle buffers from other devices */ | ||
1686 | return -EINVAL; | ||
1687 | |||
1688 | bo = gem_to_amdgpu_bo(obj); | ||
1689 | if (!(bo->preferred_domains & (AMDGPU_GEM_DOMAIN_VRAM | | ||
1690 | AMDGPU_GEM_DOMAIN_GTT))) | ||
1691 | /* Only VRAM and GTT BOs are supported */ | ||
1692 | return -EINVAL; | ||
1693 | |||
1694 | *mem = kzalloc(sizeof(struct kgd_mem), GFP_KERNEL); | ||
1695 | if (!*mem) | ||
1696 | return -ENOMEM; | ||
1697 | |||
1698 | if (size) | ||
1699 | *size = amdgpu_bo_size(bo); | ||
1700 | |||
1701 | if (mmap_offset) | ||
1702 | *mmap_offset = amdgpu_bo_mmap_offset(bo); | ||
1703 | |||
1704 | INIT_LIST_HEAD(&(*mem)->bo_va_list); | ||
1705 | mutex_init(&(*mem)->lock); | ||
1706 | (*mem)->mapping_flags = | ||
1707 | AMDGPU_VM_PAGE_READABLE | AMDGPU_VM_PAGE_WRITEABLE | | ||
1708 | AMDGPU_VM_PAGE_EXECUTABLE | AMDGPU_VM_MTYPE_NC; | ||
1709 | |||
1710 | (*mem)->bo = amdgpu_bo_ref(bo); | ||
1711 | (*mem)->va = va; | ||
1712 | (*mem)->domain = (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM) ? | ||
1713 | AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT; | ||
1714 | (*mem)->mapped_to_gpu_memory = 0; | ||
1715 | (*mem)->process_info = avm->process_info; | ||
1716 | add_kgd_mem_to_kfd_bo_list(*mem, avm->process_info, false); | ||
1717 | amdgpu_sync_create(&(*mem)->sync); | ||
1718 | |||
1719 | return 0; | ||
1720 | } | ||
1721 | |||
1667 | /* Evict a userptr BO by stopping the queues if necessary | 1722 | /* Evict a userptr BO by stopping the queues if necessary |
1668 | * | 1723 | * |
1669 | * Runs in MMU notifier, may be in RECLAIM_FS context. This means it | 1724 | * Runs in MMU notifier, may be in RECLAIM_FS context. This means it |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h index d63daba9b17c..f1ddfc50bcc7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h | |||
@@ -54,6 +54,8 @@ void *amdgpu_gem_prime_vmap(struct drm_gem_object *obj); | |||
54 | void amdgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); | 54 | void amdgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); |
55 | int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma); | 55 | int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma); |
56 | 56 | ||
57 | extern const struct dma_buf_ops amdgpu_dmabuf_ops; | ||
58 | |||
57 | /* | 59 | /* |
58 | * GEM objects. | 60 | * GEM objects. |
59 | */ | 61 | */ |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c index 3e44d889f7af..71913a18d142 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c | |||
@@ -39,8 +39,6 @@ | |||
39 | #include <drm/amdgpu_drm.h> | 39 | #include <drm/amdgpu_drm.h> |
40 | #include <linux/dma-buf.h> | 40 | #include <linux/dma-buf.h> |
41 | 41 | ||
42 | static const struct dma_buf_ops amdgpu_dmabuf_ops; | ||
43 | |||
44 | /** | 42 | /** |
45 | * amdgpu_gem_prime_get_sg_table - &drm_driver.gem_prime_get_sg_table | 43 | * amdgpu_gem_prime_get_sg_table - &drm_driver.gem_prime_get_sg_table |
46 | * implementation | 44 | * implementation |
@@ -332,7 +330,7 @@ static int amdgpu_gem_begin_cpu_access(struct dma_buf *dma_buf, | |||
332 | return ret; | 330 | return ret; |
333 | } | 331 | } |
334 | 332 | ||
335 | static const struct dma_buf_ops amdgpu_dmabuf_ops = { | 333 | const struct dma_buf_ops amdgpu_dmabuf_ops = { |
336 | .attach = amdgpu_gem_map_attach, | 334 | .attach = amdgpu_gem_map_attach, |
337 | .detach = amdgpu_gem_map_detach, | 335 | .detach = amdgpu_gem_map_detach, |
338 | .map_dma_buf = drm_gem_map_dma_buf, | 336 | .map_dma_buf = drm_gem_map_dma_buf, |