aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c75
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h14
5 files changed, 91 insertions, 4 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
index b9dbbf9cb8b0..dc7e25cce741 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
@@ -169,6 +169,8 @@ static const struct kfd2kgd_calls kfd2kgd = {
169 .get_vmem_size = get_vmem_size, 169 .get_vmem_size = get_vmem_size,
170 .get_gpu_clock_counter = get_gpu_clock_counter, 170 .get_gpu_clock_counter = get_gpu_clock_counter,
171 .get_max_engine_clock_in_mhz = get_max_engine_clock_in_mhz, 171 .get_max_engine_clock_in_mhz = get_max_engine_clock_in_mhz,
172 .alloc_pasid = amdgpu_vm_alloc_pasid,
173 .free_pasid = amdgpu_vm_free_pasid,
172 .program_sh_mem_settings = kgd_program_sh_mem_settings, 174 .program_sh_mem_settings = kgd_program_sh_mem_settings,
173 .set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping, 175 .set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping,
174 .init_pipeline = kgd_init_pipeline, 176 .init_pipeline = kgd_init_pipeline,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c
index 309f2419c6d8..c678c69936a0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c
@@ -128,6 +128,8 @@ static const struct kfd2kgd_calls kfd2kgd = {
128 .get_vmem_size = get_vmem_size, 128 .get_vmem_size = get_vmem_size,
129 .get_gpu_clock_counter = get_gpu_clock_counter, 129 .get_gpu_clock_counter = get_gpu_clock_counter,
130 .get_max_engine_clock_in_mhz = get_max_engine_clock_in_mhz, 130 .get_max_engine_clock_in_mhz = get_max_engine_clock_in_mhz,
131 .alloc_pasid = amdgpu_vm_alloc_pasid,
132 .free_pasid = amdgpu_vm_free_pasid,
131 .program_sh_mem_settings = kgd_program_sh_mem_settings, 133 .program_sh_mem_settings = kgd_program_sh_mem_settings,
132 .set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping, 134 .set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping,
133 .init_pipeline = kgd_init_pipeline, 135 .init_pipeline = kgd_init_pipeline,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index e16229000a98..79d9ab43d42c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -825,7 +825,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
825 } 825 }
826 826
827 r = amdgpu_vm_init(adev, &fpriv->vm, 827 r = amdgpu_vm_init(adev, &fpriv->vm,
828 AMDGPU_VM_CONTEXT_GFX); 828 AMDGPU_VM_CONTEXT_GFX, 0);
829 if (r) { 829 if (r) {
830 kfree(fpriv); 830 kfree(fpriv);
831 goto out_suspend; 831 goto out_suspend;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 2196bca7331c..9b795915cab1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -27,12 +27,59 @@
27 */ 27 */
28#include <linux/dma-fence-array.h> 28#include <linux/dma-fence-array.h>
29#include <linux/interval_tree_generic.h> 29#include <linux/interval_tree_generic.h>
30#include <linux/idr.h>
30#include <drm/drmP.h> 31#include <drm/drmP.h>
31#include <drm/amdgpu_drm.h> 32#include <drm/amdgpu_drm.h>
32#include "amdgpu.h" 33#include "amdgpu.h"
33#include "amdgpu_trace.h" 34#include "amdgpu_trace.h"
34 35
35/* 36/*
37 * PASID manager
38 *
39 * PASIDs are global address space identifiers that can be shared
40 * between the GPU, an IOMMU and the driver. VMs on different devices
41 * may use the same PASID if they share the same address
42 * space. Therefore PASIDs are allocated using a global IDA. VMs are
43 * looked up from the PASID per amdgpu_device.
44 */
45static DEFINE_IDA(amdgpu_vm_pasid_ida);
46
47/**
48 * amdgpu_vm_alloc_pasid - Allocate a PASID
49 * @bits: Maximum width of the PASID in bits, must be at least 1
50 *
51 * Allocates a PASID of the given width while keeping smaller PASIDs
52 * available if possible.
53 *
54 * Returns a positive integer on success. Returns %-EINVAL if bits==0.
55 * Returns %-ENOSPC if no PASID was available. Returns %-ENOMEM on
56 * memory allocation failure.
57 */
58int amdgpu_vm_alloc_pasid(unsigned int bits)
59{
60 int pasid = -EINVAL;
61
62 for (bits = min(bits, 31U); bits > 0; bits--) {
63 pasid = ida_simple_get(&amdgpu_vm_pasid_ida,
64 1U << (bits - 1), 1U << bits,
65 GFP_KERNEL);
66 if (pasid != -ENOSPC)
67 break;
68 }
69
70 return pasid;
71}
72
73/**
74 * amdgpu_vm_free_pasid - Free a PASID
75 * @pasid: PASID to free
76 */
77void amdgpu_vm_free_pasid(unsigned int pasid)
78{
79 ida_simple_remove(&amdgpu_vm_pasid_ida, pasid);
80}
81
82/*
36 * GPUVM 83 * GPUVM
37 * GPUVM is similar to the legacy gart on older asics, however 84 * GPUVM is similar to the legacy gart on older asics, however
38 * rather than there being a single global gart table 85 * rather than there being a single global gart table
@@ -2539,7 +2586,7 @@ void amdgpu_vm_adjust_size(struct amdgpu_device *adev, uint64_t vm_size, uint32_
2539 * Init @vm fields. 2586 * Init @vm fields.
2540 */ 2587 */
2541int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, 2588int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
2542 int vm_context) 2589 int vm_context, unsigned int pasid)
2543{ 2590{
2544 const unsigned align = min(AMDGPU_VM_PTB_ALIGN_SIZE, 2591 const unsigned align = min(AMDGPU_VM_PTB_ALIGN_SIZE,
2545 AMDGPU_VM_PTE_COUNT(adev) * 8); 2592 AMDGPU_VM_PTE_COUNT(adev) * 8);
@@ -2620,6 +2667,19 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
2620 goto error_free_root; 2667 goto error_free_root;
2621 } 2668 }
2622 2669
2670 if (pasid) {
2671 unsigned long flags;
2672
2673 spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags);
2674 r = idr_alloc(&adev->vm_manager.pasid_idr, vm, pasid, pasid + 1,
2675 GFP_ATOMIC);
2676 spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);
2677 if (r < 0)
2678 goto error_free_root;
2679
2680 vm->pasid = pasid;
2681 }
2682
2623 return 0; 2683 return 0;
2624 2684
2625error_free_root: 2685error_free_root:
@@ -2673,6 +2733,14 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)
2673 bool prt_fini_needed = !!adev->gart.gart_funcs->set_prt; 2733 bool prt_fini_needed = !!adev->gart.gart_funcs->set_prt;
2674 int i; 2734 int i;
2675 2735
2736 if (vm->pasid) {
2737 unsigned long flags;
2738
2739 spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags);
2740 idr_remove(&adev->vm_manager.pasid_idr, vm->pasid);
2741 spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);
2742 }
2743
2676 amd_sched_entity_fini(vm->entity.sched, &vm->entity); 2744 amd_sched_entity_fini(vm->entity.sched, &vm->entity);
2677 2745
2678 if (!RB_EMPTY_ROOT(&vm->va)) { 2746 if (!RB_EMPTY_ROOT(&vm->va)) {
@@ -2752,6 +2820,8 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev)
2752 adev->vm_manager.vm_update_mode = 0; 2820 adev->vm_manager.vm_update_mode = 0;
2753#endif 2821#endif
2754 2822
2823 idr_init(&adev->vm_manager.pasid_idr);
2824 spin_lock_init(&adev->vm_manager.pasid_lock);
2755} 2825}
2756 2826
2757/** 2827/**
@@ -2765,6 +2835,9 @@ void amdgpu_vm_manager_fini(struct amdgpu_device *adev)
2765{ 2835{
2766 unsigned i, j; 2836 unsigned i, j;
2767 2837
2838 WARN_ON(!idr_is_empty(&adev->vm_manager.pasid_idr));
2839 idr_destroy(&adev->vm_manager.pasid_idr);
2840
2768 for (i = 0; i < AMDGPU_MAX_VMHUBS; ++i) { 2841 for (i = 0; i < AMDGPU_MAX_VMHUBS; ++i) {
2769 struct amdgpu_vm_id_manager *id_mgr = 2842 struct amdgpu_vm_id_manager *id_mgr =
2770 &adev->vm_manager.id_mgr[i]; 2843 &adev->vm_manager.id_mgr[i];
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
index 48c58ae4bb3a..7873dfa8c0f9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
@@ -25,6 +25,7 @@
25#define __AMDGPU_VM_H__ 25#define __AMDGPU_VM_H__
26 26
27#include <linux/rbtree.h> 27#include <linux/rbtree.h>
28#include <linux/idr.h>
28 29
29#include "gpu_scheduler.h" 30#include "gpu_scheduler.h"
30#include "amdgpu_sync.h" 31#include "amdgpu_sync.h"
@@ -148,8 +149,9 @@ struct amdgpu_vm {
148 /* Scheduler entity for page table updates */ 149 /* Scheduler entity for page table updates */
149 struct amd_sched_entity entity; 150 struct amd_sched_entity entity;
150 151
151 /* client id */ 152 /* client id and PASID (TODO: replace client_id with PASID) */
152 u64 client_id; 153 u64 client_id;
154 unsigned int pasid;
153 /* dedicated to vm */ 155 /* dedicated to vm */
154 struct amdgpu_vm_id *reserved_vmid[AMDGPU_MAX_VMHUBS]; 156 struct amdgpu_vm_id *reserved_vmid[AMDGPU_MAX_VMHUBS];
155 157
@@ -220,12 +222,20 @@ struct amdgpu_vm_manager {
220 * BIT1[= 0] Compute updated by SDMA [= 1] by CPU 222 * BIT1[= 0] Compute updated by SDMA [= 1] by CPU
221 */ 223 */
222 int vm_update_mode; 224 int vm_update_mode;
225
226 /* PASID to VM mapping, will be used in interrupt context to
227 * look up VM of a page fault
228 */
229 struct idr pasid_idr;
230 spinlock_t pasid_lock;
223}; 231};
224 232
233int amdgpu_vm_alloc_pasid(unsigned int bits);
234void amdgpu_vm_free_pasid(unsigned int pasid);
225void amdgpu_vm_manager_init(struct amdgpu_device *adev); 235void amdgpu_vm_manager_init(struct amdgpu_device *adev);
226void amdgpu_vm_manager_fini(struct amdgpu_device *adev); 236void amdgpu_vm_manager_fini(struct amdgpu_device *adev);
227int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, 237int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
228 int vm_context); 238 int vm_context, unsigned int pasid);
229void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm); 239void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm);
230void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, 240void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm,
231 struct list_head *validated, 241 struct list_head *validated,