1 /*
2  * Copyright 2016 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: Christian König
23  */
24 
25 #include <drm/drmP.h>
26 #include "amdgpu.h"
27 
28 struct amdgpu_gtt_mgr {
29 	struct drm_mm mm;
30 	struct spinlock lock;
31 	atomic64_t available;
32 };
33 
34 struct amdgpu_gtt_node {
35 	struct drm_mm_node node;
36 	struct ttm_buffer_object *tbo;
37 };
38 
39 /**
40  * amdgpu_gtt_mgr_init - init GTT manager and DRM MM
41  *
42  * @man: TTM memory type manager
43  * @p_size: maximum size of GTT
44  *
45  * Allocate and initialize the GTT manager.
46  */
47 static int amdgpu_gtt_mgr_init(struct ttm_mem_type_manager *man,
48 			       unsigned long p_size)
49 {
50 	struct amdgpu_device *adev = amdgpu_ttm_adev(man->bdev);
51 	struct amdgpu_gtt_mgr *mgr;
52 	uint64_t start, size;
53 
54 	mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
55 	if (!mgr)
56 		return -ENOMEM;
57 
58 	start = AMDGPU_GTT_MAX_TRANSFER_SIZE * AMDGPU_GTT_NUM_TRANSFER_WINDOWS;
59 	size = (adev->gmc.gart_size >> PAGE_SHIFT) - start;
60 	drm_mm_init(&mgr->mm, start, size);
61 	spin_init(&mgr->lock, "aggmml");
62 	atomic64_set(&mgr->available, p_size);
63 	man->priv = mgr;
64 	return 0;
65 }
66 
67 /**
68  * amdgpu_gtt_mgr_fini - free and destroy GTT manager
69  *
70  * @man: TTM memory type manager
71  *
72  * Destroy and free the GTT manager, returns -EBUSY if ranges are still
73  * allocated inside it.
74  */
75 static int amdgpu_gtt_mgr_fini(struct ttm_mem_type_manager *man)
76 {
77 	struct amdgpu_gtt_mgr *mgr = man->priv;
78 	spin_lock(&mgr->lock);
79 	drm_mm_takedown(&mgr->mm);
80 	spin_unlock(&mgr->lock);
81 	kfree(mgr);
82 	man->priv = NULL;
83 	return 0;
84 }
85 
86 /**
87  * amdgpu_gtt_mgr_has_gart_addr - Check if mem has address space
88  *
89  * @mem: the mem object to check
90  *
91  * Check if a mem object has already address space allocated.
92  */
93 bool amdgpu_gtt_mgr_has_gart_addr(struct ttm_mem_reg *mem)
94 {
95 	struct amdgpu_gtt_node *node = mem->mm_node;
96 
97 	return (node->node.start != AMDGPU_BO_INVALID_OFFSET);
98 }
99 
100 /**
101  * amdgpu_gtt_mgr_alloc - allocate new ranges
102  *
103  * @man: TTM memory type manager
104  * @tbo: TTM BO we need this range for
105  * @place: placement flags and restrictions
106  * @mem: the resulting mem object
107  *
108  * Allocate the address space for a node.
109  */
110 static int amdgpu_gtt_mgr_alloc(struct ttm_mem_type_manager *man,
111 				struct ttm_buffer_object *tbo,
112 				const struct ttm_place *place,
113 				struct ttm_mem_reg *mem)
114 {
115 	struct amdgpu_device *adev = amdgpu_ttm_adev(man->bdev);
116 	struct amdgpu_gtt_mgr *mgr = man->priv;
117 	struct amdgpu_gtt_node *node = mem->mm_node;
118 	enum drm_mm_insert_mode mode;
119 	unsigned long fpfn, lpfn;
120 	int r;
121 
122 	if (amdgpu_gtt_mgr_has_gart_addr(mem))
123 		return 0;
124 
125 	if (place)
126 		fpfn = place->fpfn;
127 	else
128 		fpfn = 0;
129 
130 	if (place && place->lpfn)
131 		lpfn = place->lpfn;
132 	else
133 		lpfn = adev->gart.num_cpu_pages;
134 
135 	mode = DRM_MM_INSERT_BEST;
136 	if (place && place->flags & TTM_PL_FLAG_TOPDOWN)
137 		mode = DRM_MM_INSERT_HIGH;
138 
139 	spin_lock(&mgr->lock);
140 	r = drm_mm_insert_node_in_range(&mgr->mm, &node->node, mem->num_pages,
141 					mem->page_alignment, 0, fpfn, lpfn,
142 					mode);
143 	spin_unlock(&mgr->lock);
144 
145 	if (!r)
146 		mem->start = node->node.start;
147 
148 	return r;
149 }
150 
151 /**
152  * amdgpu_gtt_mgr_new - allocate a new node
153  *
154  * @man: TTM memory type manager
155  * @tbo: TTM BO we need this range for
156  * @place: placement flags and restrictions
157  * @mem: the resulting mem object
158  *
159  * Dummy, allocate the node but no space for it yet.
160  */
161 static int amdgpu_gtt_mgr_new(struct ttm_mem_type_manager *man,
162 			      struct ttm_buffer_object *tbo,
163 			      const struct ttm_place *place,
164 			      struct ttm_mem_reg *mem)
165 {
166 	struct amdgpu_gtt_mgr *mgr = man->priv;
167 	struct amdgpu_gtt_node *node;
168 	int r;
169 
170 	spin_lock(&mgr->lock);
171 	if ((&tbo->mem == mem || tbo->mem.mem_type != TTM_PL_TT) &&
172 	    atomic64_read(&mgr->available) < mem->num_pages) {
173 		spin_unlock(&mgr->lock);
174 		return 0;
175 	}
176 	atomic64_sub(mem->num_pages, &mgr->available);
177 	spin_unlock(&mgr->lock);
178 
179 	node = kzalloc(sizeof(*node), GFP_KERNEL);
180 	if (!node) {
181 		r = -ENOMEM;
182 		goto err_out;
183 	}
184 
185 	node->node.start = AMDGPU_BO_INVALID_OFFSET;
186 	node->node.size = mem->num_pages;
187 	node->tbo = tbo;
188 	mem->mm_node = node;
189 
190 	if (place->fpfn || place->lpfn || place->flags & TTM_PL_FLAG_TOPDOWN) {
191 		r = amdgpu_gtt_mgr_alloc(man, tbo, place, mem);
192 		if (unlikely(r)) {
193 			kfree(node);
194 			mem->mm_node = NULL;
195 			r = 0;
196 			goto err_out;
197 		}
198 	} else {
199 		mem->start = node->node.start;
200 	}
201 
202 	return 0;
203 err_out:
204 	atomic64_add(mem->num_pages, &mgr->available);
205 
206 	return r;
207 }
208 
209 /**
210  * amdgpu_gtt_mgr_del - free ranges
211  *
212  * @man: TTM memory type manager
213  * @tbo: TTM BO we need this range for
214  * @place: placement flags and restrictions
215  * @mem: TTM memory object
216  *
217  * Free the allocated GTT again.
218  */
219 static void amdgpu_gtt_mgr_del(struct ttm_mem_type_manager *man,
220 			       struct ttm_mem_reg *mem)
221 {
222 	struct amdgpu_gtt_mgr *mgr = man->priv;
223 	struct amdgpu_gtt_node *node = mem->mm_node;
224 
225 	if (!node)
226 		return;
227 
228 	spin_lock(&mgr->lock);
229 	if (node->node.start != AMDGPU_BO_INVALID_OFFSET)
230 		drm_mm_remove_node(&node->node);
231 	spin_unlock(&mgr->lock);
232 	atomic64_add(mem->num_pages, &mgr->available);
233 
234 	kfree(node);
235 	mem->mm_node = NULL;
236 }
237 
238 /**
239  * amdgpu_gtt_mgr_usage - return usage of GTT domain
240  *
241  * @man: TTM memory type manager
242  *
243  * Return how many bytes are used in the GTT domain
244  */
245 uint64_t amdgpu_gtt_mgr_usage(struct ttm_mem_type_manager *man)
246 {
247 	struct amdgpu_gtt_mgr *mgr = man->priv;
248 	s64 result = man->size - atomic64_read(&mgr->available);
249 
250 	return (result > 0 ? result : 0) * PAGE_SIZE;
251 }
252 
253 int amdgpu_gtt_mgr_recover(struct ttm_mem_type_manager *man)
254 {
255 	struct amdgpu_gtt_mgr *mgr = man->priv;
256 	struct amdgpu_gtt_node *node;
257 	struct drm_mm_node *mm_node;
258 	int r = 0;
259 
260 	spin_lock(&mgr->lock);
261 	drm_mm_for_each_node(mm_node, &mgr->mm) {
262 		node = container_of(mm_node, struct amdgpu_gtt_node, node);
263 		r = amdgpu_ttm_recover_gart(node->tbo);
264 		if (r)
265 			break;
266 	}
267 	spin_unlock(&mgr->lock);
268 
269 	return r;
270 }
271 
272 /**
273  * amdgpu_gtt_mgr_debug - dump VRAM table
274  *
275  * @man: TTM memory type manager
276  * @printer: DRM printer to use
277  *
278  * Dump the table content using printk.
279  */
280 static void amdgpu_gtt_mgr_debug(struct ttm_mem_type_manager *man,
281 				 struct drm_printer *printer)
282 {
283 	struct amdgpu_gtt_mgr *mgr = man->priv;
284 
285 	spin_lock(&mgr->lock);
286 	drm_mm_print(&mgr->mm, printer);
287 	spin_unlock(&mgr->lock);
288 
289 	drm_printf(printer, "man size:%lu pages, gtt available:%lld pages, usage:%luMB\n",
290 		   man->size, (u64)atomic64_read(&mgr->available),
291 		   amdgpu_gtt_mgr_usage(man) >> 20);
292 }
293 
294 const struct ttm_mem_type_manager_func amdgpu_gtt_mgr_func = {
295 	.init = amdgpu_gtt_mgr_init,
296 	.takedown = amdgpu_gtt_mgr_fini,
297 	.get_node = amdgpu_gtt_mgr_new,
298 	.put_node = amdgpu_gtt_mgr_del,
299 	.debug = amdgpu_gtt_mgr_debug
300 };
301