aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1521-drm-amdgpu-Impose-KFD-memory-usage-limits.patch
blob: c4775782c173571dedc473e289dac5337215a6a5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
From 681b5e4b64faf63d9913b6b7e9a6d93619a112f1 Mon Sep 17 00:00:00 2001
From: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
Date: Tue, 26 Jul 2016 18:59:10 -0400
Subject: [PATCH 1521/4131] drm/amdgpu: Impose KFD memory usage limits

Change-Id: Ic51260e6b8a7513dfa9a60ddd5c459f6b19da05a
Signed-off-by: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>

 Conflicts:
	drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c       |  2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h       |  2 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 99 ++++++++++++++++++++++++
 3 files changed, 102 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
index 0bf1fb3..f18cbfa 100755
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
@@ -59,7 +59,7 @@ int amdgpu_amdkfd_init(void)
 #else
 	ret = -ENOENT;
 #endif
-
+	amdgpu_amdkfd_gpuvm_init_mem_limits();
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
index a291577..2db28e5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
@@ -205,5 +205,7 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf(struct kgd_dev *kgd, int dma_buf_fd,
 int amdgpu_amdkfd_gpuvm_evict_mem(struct kgd_mem *mem, struct mm_struct *mm);
 int amdgpu_amdkfd_gpuvm_restore_mem(struct kgd_mem *mem, struct mm_struct *mm);
 
+void amdgpu_amdkfd_gpuvm_init_mem_limits(void);
+
 #endif /* AMDGPU_AMDKFD_H_INCLUDED */
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index 2abce72..eed9aca 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -43,6 +43,18 @@
  * a HW bug. */
 #define VI_BO_SIZE_ALIGN (0x8000)
 
+/* Impose limit on how much memory KFD can use */
+struct kfd_mem_usage_limit {
+	uint64_t max_system_mem_limit;
+	uint64_t max_userptr_mem_limit;
+	int64_t system_mem_used;
+	int64_t userptr_mem_used;
+	spinlock_t mem_limit_lock;
+};
+
+static struct kfd_mem_usage_limit kfd_mem_limit;
+
+
 static inline struct amdgpu_device *get_amdgpu_device(struct kgd_dev *kgd)
 {
 	return (struct amdgpu_device *)kgd;
@@ -66,6 +78,85 @@ static bool check_if_add_bo_to_vm(struct amdgpu_vm *avm,
 	return true;
 }
 
+/* Set memory usage limits. Current, limits are
+ *  System (kernel) memory - 1/4th System RAM
+ *  Userptr memory - 3/4th System RAM
+ */
+void amdgpu_amdkfd_gpuvm_init_mem_limits(void)
+{
+	struct sysinfo si;
+	uint64_t mem;
+
+	si_meminfo(&si);
+	mem = si.totalram - si.totalhigh;
+	mem *= si.mem_unit;
+
+	spin_lock_init(&kfd_mem_limit.mem_limit_lock);
+	kfd_mem_limit.max_system_mem_limit = (mem >> 2) - (mem >> 4);
+	kfd_mem_limit.max_userptr_mem_limit = mem - (mem >> 4);
+	pr_debug("Kernel memory limit %lluM, userptr limit %lluM\n",
+		(kfd_mem_limit.max_system_mem_limit >> 20),
+		(kfd_mem_limit.max_userptr_mem_limit >> 20));
+}
+
+static int check_and_reserve_system_mem_limit(struct amdgpu_device *adev,
+					      uint64_t size, u32 domain)
+{
+	size_t acc_size;
+	int ret = 0;
+
+	acc_size = ttm_bo_dma_acc_size(&adev->mman.bdev, size,
+				       sizeof(struct amdgpu_bo));
+
+	spin_lock(&kfd_mem_limit.mem_limit_lock);
+	if (domain == AMDGPU_GEM_DOMAIN_GTT) {
+		if (kfd_mem_limit.system_mem_used + (acc_size + size) >
+			kfd_mem_limit.max_system_mem_limit) {
+			ret = -ENOMEM;
+			goto err_no_mem;
+		}
+		kfd_mem_limit.system_mem_used += (acc_size + size);
+
+	} else if (domain == AMDGPU_GEM_DOMAIN_CPU) {
+		if ((kfd_mem_limit.system_mem_used + acc_size >
+			kfd_mem_limit.max_system_mem_limit) &&
+			(kfd_mem_limit.userptr_mem_used + (size + acc_size) >
+			kfd_mem_limit.max_userptr_mem_limit)) {
+			ret = -ENOMEM;
+			goto err_no_mem;
+		}
+		kfd_mem_limit.system_mem_used += acc_size;
+		kfd_mem_limit.userptr_mem_used += size;
+	}
+
+err_no_mem:
+	spin_unlock(&kfd_mem_limit.mem_limit_lock);
+	return ret;
+}
+
+static void unreserve_system_memory_limit(struct amdgpu_bo *bo)
+{
+	spin_lock(&kfd_mem_limit.mem_limit_lock);
+
+	if (bo->prefered_domains == AMDGPU_GEM_DOMAIN_GTT)
+		kfd_mem_limit.system_mem_used -=
+			(bo->tbo.acc_size + amdgpu_bo_size(bo));
+	else if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm)) {
+		kfd_mem_limit.system_mem_used -= bo->tbo.acc_size;
+		kfd_mem_limit.userptr_mem_used -= amdgpu_bo_size(bo);
+	}
+	if (kfd_mem_limit.system_mem_used < 0) {
+		pr_warn("kfd system memory size ref. error\n");
+		kfd_mem_limit.system_mem_used = 0;
+	}
+	if (kfd_mem_limit.userptr_mem_used < 0) {
+		pr_warn("kfd userptr memory size ref. error\n");
+		kfd_mem_limit.userptr_mem_used = 0;
+	}
+
+	spin_unlock(&kfd_mem_limit.mem_limit_lock);
+}
+
 static int add_bo_to_vm(struct amdgpu_device *adev, struct kgd_mem *mem,
 		struct amdgpu_vm *avm, bool is_aql,
 		struct kfd_bo_va_list **p_bo_va_entry)
@@ -359,6 +450,13 @@ static int __alloc_memory_of_gpu(struct kgd_dev *kgd, uint64_t va,
 	pr_debug("amdkfd: allocating BO on domain %d with size %llu\n",
 				alloc_domain, size);
 
+	ret = check_and_reserve_system_mem_limit(adev, size, alloc_domain);
+	if (ret) {
+		pr_err("amdkfd: Insufficient system memory\n");
+		goto err_bo_create;
+	}
+
+
 	/* Allocate buffer object. Userptr objects need to start out
 	 * in the CPU domain, get moved to GTT when pinned. */
 	ret = amdgpu_bo_create(adev, size, byte_align, false,
@@ -944,6 +1042,7 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
 	}
 
 	/* Free the BO*/
+	unreserve_system_memory_limit(mem->data2.bo);
 	bo_list_entry = &mem->data2.bo_list_entry;
 	mutex_lock(&master_vm->lock);
 	list_del(&bo_list_entry->tv.head);
-- 
2.7.4