xref: /netbsd-src/sys/external/bsd/drm2/dist/drm/amd/amdgpu/amdgpu_vram_mgr.c (revision 07eb61ce39682b60a0b29b81ad8b6af16527a557)
1 /*	$NetBSD: amdgpu_vram_mgr.c,v 1.4 2021/12/19 12:31:45 riastradh Exp $	*/
2 
3 /*
4  * Copyright 2016 Advanced Micro Devices, Inc.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22  * OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * Authors: Christian König
25  */
26 
27 #include <sys/cdefs.h>
28 __KERNEL_RCSID(0, "$NetBSD: amdgpu_vram_mgr.c,v 1.4 2021/12/19 12:31:45 riastradh Exp $");
29 
30 #include "amdgpu.h"
31 #include "amdgpu_vm.h"
32 #include "amdgpu_atomfirmware.h"
33 #include "atom.h"
34 
35 struct amdgpu_vram_mgr {
36 	struct drm_mm mm;
37 	spinlock_t lock;
38 	atomic64_t usage;
39 	atomic64_t vis_usage;
40 };
41 
42 #ifndef __NetBSD__		/* XXX amdgpu sysfs */
43 
44 /**
45  * DOC: mem_info_vram_total
46  *
47  * The amdgpu driver provides a sysfs API for reporting current total VRAM
48  * available on the device
49  * The file mem_info_vram_total is used for this and returns the total
50  * amount of VRAM in bytes
51  */
amdgpu_mem_info_vram_total_show(struct device * dev,struct device_attribute * attr,char * buf)52 static ssize_t amdgpu_mem_info_vram_total_show(struct device *dev,
53 		struct device_attribute *attr, char *buf)
54 {
55 	struct drm_device *ddev = dev_get_drvdata(dev);
56 	struct amdgpu_device *adev = ddev->dev_private;
57 
58 	return snprintf(buf, PAGE_SIZE, "%llu\n", adev->gmc.real_vram_size);
59 }
60 
61 /**
62  * DOC: mem_info_vis_vram_total
63  *
64  * The amdgpu driver provides a sysfs API for reporting current total
65  * visible VRAM available on the device
66  * The file mem_info_vis_vram_total is used for this and returns the total
67  * amount of visible VRAM in bytes
68  */
amdgpu_mem_info_vis_vram_total_show(struct device * dev,struct device_attribute * attr,char * buf)69 static ssize_t amdgpu_mem_info_vis_vram_total_show(struct device *dev,
70 		struct device_attribute *attr, char *buf)
71 {
72 	struct drm_device *ddev = dev_get_drvdata(dev);
73 	struct amdgpu_device *adev = ddev->dev_private;
74 
75 	return snprintf(buf, PAGE_SIZE, "%llu\n", adev->gmc.visible_vram_size);
76 }
77 
78 /**
79  * DOC: mem_info_vram_used
80  *
81  * The amdgpu driver provides a sysfs API for reporting current total VRAM
82  * available on the device
83  * The file mem_info_vram_used is used for this and returns the total
84  * amount of currently used VRAM in bytes
85  */
amdgpu_mem_info_vram_used_show(struct device * dev,struct device_attribute * attr,char * buf)86 static ssize_t amdgpu_mem_info_vram_used_show(struct device *dev,
87 		struct device_attribute *attr, char *buf)
88 {
89 	struct drm_device *ddev = dev_get_drvdata(dev);
90 	struct amdgpu_device *adev = ddev->dev_private;
91 
92 	return snprintf(buf, PAGE_SIZE, "%llu\n",
93 		amdgpu_vram_mgr_usage(&adev->mman.bdev.man[TTM_PL_VRAM]));
94 }
95 
96 /**
97  * DOC: mem_info_vis_vram_used
98  *
99  * The amdgpu driver provides a sysfs API for reporting current total of
100  * used visible VRAM
101  * The file mem_info_vis_vram_used is used for this and returns the total
102  * amount of currently used visible VRAM in bytes
103  */
amdgpu_mem_info_vis_vram_used_show(struct device * dev,struct device_attribute * attr,char * buf)104 static ssize_t amdgpu_mem_info_vis_vram_used_show(struct device *dev,
105 		struct device_attribute *attr, char *buf)
106 {
107 	struct drm_device *ddev = dev_get_drvdata(dev);
108 	struct amdgpu_device *adev = ddev->dev_private;
109 
110 	return snprintf(buf, PAGE_SIZE, "%llu\n",
111 		amdgpu_vram_mgr_vis_usage(&adev->mman.bdev.man[TTM_PL_VRAM]));
112 }
113 
amdgpu_mem_info_vram_vendor(struct device * dev,struct device_attribute * attr,char * buf)114 static ssize_t amdgpu_mem_info_vram_vendor(struct device *dev,
115 						 struct device_attribute *attr,
116 						 char *buf)
117 {
118 	struct drm_device *ddev = dev_get_drvdata(dev);
119 	struct amdgpu_device *adev = ddev->dev_private;
120 
121 	switch (adev->gmc.vram_vendor) {
122 	case SAMSUNG:
123 		return snprintf(buf, PAGE_SIZE, "samsung\n");
124 	case INFINEON:
125 		return snprintf(buf, PAGE_SIZE, "infineon\n");
126 	case ELPIDA:
127 		return snprintf(buf, PAGE_SIZE, "elpida\n");
128 	case ETRON:
129 		return snprintf(buf, PAGE_SIZE, "etron\n");
130 	case NANYA:
131 		return snprintf(buf, PAGE_SIZE, "nanya\n");
132 	case HYNIX:
133 		return snprintf(buf, PAGE_SIZE, "hynix\n");
134 	case MOSEL:
135 		return snprintf(buf, PAGE_SIZE, "mosel\n");
136 	case WINBOND:
137 		return snprintf(buf, PAGE_SIZE, "winbond\n");
138 	case ESMT:
139 		return snprintf(buf, PAGE_SIZE, "esmt\n");
140 	case MICRON:
141 		return snprintf(buf, PAGE_SIZE, "micron\n");
142 	default:
143 		return snprintf(buf, PAGE_SIZE, "unknown\n");
144 	}
145 }
146 
147 static DEVICE_ATTR(mem_info_vram_total, S_IRUGO,
148 		   amdgpu_mem_info_vram_total_show, NULL);
149 static DEVICE_ATTR(mem_info_vis_vram_total, S_IRUGO,
150 		   amdgpu_mem_info_vis_vram_total_show,NULL);
151 static DEVICE_ATTR(mem_info_vram_used, S_IRUGO,
152 		   amdgpu_mem_info_vram_used_show, NULL);
153 static DEVICE_ATTR(mem_info_vis_vram_used, S_IRUGO,
154 		   amdgpu_mem_info_vis_vram_used_show, NULL);
155 static DEVICE_ATTR(mem_info_vram_vendor, S_IRUGO,
156 		   amdgpu_mem_info_vram_vendor, NULL);
157 
158 #endif	/* __NetBSD__ */
159 
160 /**
161  * amdgpu_vram_mgr_init - init VRAM manager and DRM MM
162  *
163  * @man: TTM memory type manager
164  * @p_size: maximum size of VRAM
165  *
166  * Allocate and initialize the VRAM manager.
167  */
amdgpu_vram_mgr_init(struct ttm_mem_type_manager * man,unsigned long p_size)168 static int amdgpu_vram_mgr_init(struct ttm_mem_type_manager *man,
169 				unsigned long p_size)
170 {
171 	struct amdgpu_device *adev = amdgpu_ttm_adev(man->bdev);
172 	struct amdgpu_vram_mgr *mgr;
173 	int ret;
174 
175 	mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
176 	if (!mgr)
177 		return -ENOMEM;
178 
179 	drm_mm_init(&mgr->mm, 0, p_size);
180 	spin_lock_init(&mgr->lock);
181 	man->priv = mgr;
182 
183 #ifdef __NetBSD__	     /* XXX amdgpu sysfs */
184 	__USE(adev);
185 	__USE(ret);
186 #else
187 	/* Add the two VRAM-related sysfs files */
188 	ret = device_create_file(adev->dev, &dev_attr_mem_info_vram_total);
189 	if (ret) {
190 		DRM_ERROR("Failed to create device file mem_info_vram_total\n");
191 		return ret;
192 	}
193 	ret = device_create_file(adev->dev, &dev_attr_mem_info_vis_vram_total);
194 	if (ret) {
195 		DRM_ERROR("Failed to create device file mem_info_vis_vram_total\n");
196 		return ret;
197 	}
198 	ret = device_create_file(adev->dev, &dev_attr_mem_info_vram_used);
199 	if (ret) {
200 		DRM_ERROR("Failed to create device file mem_info_vram_used\n");
201 		return ret;
202 	}
203 	ret = device_create_file(adev->dev, &dev_attr_mem_info_vis_vram_used);
204 	if (ret) {
205 		DRM_ERROR("Failed to create device file mem_info_vis_vram_used\n");
206 		return ret;
207 	}
208 	ret = device_create_file(adev->dev, &dev_attr_mem_info_vram_vendor);
209 	if (ret) {
210 		DRM_ERROR("Failed to create device file mem_info_vram_vendor\n");
211 		return ret;
212 	}
213 #endif	/* __NetBSD__ */
214 
215 	return 0;
216 }
217 
218 /**
219  * amdgpu_vram_mgr_fini - free and destroy VRAM manager
220  *
221  * @man: TTM memory type manager
222  *
223  * Destroy and free the VRAM manager, returns -EBUSY if ranges are still
224  * allocated inside it.
225  */
amdgpu_vram_mgr_fini(struct ttm_mem_type_manager * man)226 static int amdgpu_vram_mgr_fini(struct ttm_mem_type_manager *man)
227 {
228 	struct amdgpu_device *adev = amdgpu_ttm_adev(man->bdev);
229 	struct amdgpu_vram_mgr *mgr = man->priv;
230 
231 	spin_lock(&mgr->lock);
232 	drm_mm_takedown(&mgr->mm);
233 	spin_unlock(&mgr->lock);
234 	spin_lock_destroy(&mgr->lock);
235 	kfree(mgr);
236 	man->priv = NULL;
237 #ifdef __NetBSD__		/* XXX amdgpu sysfs */
238 	__USE(adev);
239 #else
240 	device_remove_file(adev->dev, &dev_attr_mem_info_vram_total);
241 	device_remove_file(adev->dev, &dev_attr_mem_info_vis_vram_total);
242 	device_remove_file(adev->dev, &dev_attr_mem_info_vram_used);
243 	device_remove_file(adev->dev, &dev_attr_mem_info_vis_vram_used);
244 	device_remove_file(adev->dev, &dev_attr_mem_info_vram_vendor);
245 #endif
246 	return 0;
247 }
248 
249 /**
250  * amdgpu_vram_mgr_vis_size - Calculate visible node size
251  *
252  * @adev: amdgpu device structure
253  * @node: MM node structure
254  *
255  * Calculate how many bytes of the MM node are inside visible VRAM
256  */
amdgpu_vram_mgr_vis_size(struct amdgpu_device * adev,struct drm_mm_node * node)257 static u64 amdgpu_vram_mgr_vis_size(struct amdgpu_device *adev,
258 				    struct drm_mm_node *node)
259 {
260 	uint64_t start = node->start << PAGE_SHIFT;
261 	uint64_t end = (node->size + node->start) << PAGE_SHIFT;
262 
263 	if (start >= adev->gmc.visible_vram_size)
264 		return 0;
265 
266 	return (end > adev->gmc.visible_vram_size ?
267 		adev->gmc.visible_vram_size : end) - start;
268 }
269 
270 /**
271  * amdgpu_vram_mgr_bo_visible_size - CPU visible BO size
272  *
273  * @bo: &amdgpu_bo buffer object (must be in VRAM)
274  *
275  * Returns:
276  * How much of the given &amdgpu_bo buffer object lies in CPU visible VRAM.
277  */
amdgpu_vram_mgr_bo_visible_size(struct amdgpu_bo * bo)278 u64 amdgpu_vram_mgr_bo_visible_size(struct amdgpu_bo *bo)
279 {
280 	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
281 	struct ttm_mem_reg *mem = &bo->tbo.mem;
282 	struct drm_mm_node *nodes = mem->mm_node;
283 	unsigned pages = mem->num_pages;
284 	u64 usage;
285 
286 	if (amdgpu_gmc_vram_full_visible(&adev->gmc))
287 		return amdgpu_bo_size(bo);
288 
289 	if (mem->start >= adev->gmc.visible_vram_size >> PAGE_SHIFT)
290 		return 0;
291 
292 	for (usage = 0; nodes && pages; pages -= nodes->size, nodes++)
293 		usage += amdgpu_vram_mgr_vis_size(adev, nodes);
294 
295 	return usage;
296 }
297 
298 /**
299  * amdgpu_vram_mgr_virt_start - update virtual start address
300  *
301  * @mem: ttm_mem_reg to update
302  * @node: just allocated node
303  *
304  * Calculate a virtual BO start address to easily check if everything is CPU
305  * accessible.
306  */
amdgpu_vram_mgr_virt_start(struct ttm_mem_reg * mem,struct drm_mm_node * node)307 static void amdgpu_vram_mgr_virt_start(struct ttm_mem_reg *mem,
308 				       struct drm_mm_node *node)
309 {
310 	unsigned long start;
311 
312 	start = node->start + node->size;
313 	if (start > mem->num_pages)
314 		start -= mem->num_pages;
315 	else
316 		start = 0;
317 	mem->start = max(mem->start, start);
318 }
319 
320 /**
321  * amdgpu_vram_mgr_new - allocate new ranges
322  *
323  * @man: TTM memory type manager
324  * @tbo: TTM BO we need this range for
325  * @place: placement flags and restrictions
326  * @mem: the resulting mem object
327  *
328  * Allocate VRAM for the given BO.
329  */
amdgpu_vram_mgr_new(struct ttm_mem_type_manager * man,struct ttm_buffer_object * tbo,const struct ttm_place * place,struct ttm_mem_reg * mem)330 static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man,
331 			       struct ttm_buffer_object *tbo,
332 			       const struct ttm_place *place,
333 			       struct ttm_mem_reg *mem)
334 {
335 	struct amdgpu_device *adev = amdgpu_ttm_adev(man->bdev);
336 	struct amdgpu_vram_mgr *mgr = man->priv;
337 	struct drm_mm *mm = &mgr->mm;
338 	struct drm_mm_node *nodes;
339 	enum drm_mm_insert_mode mode;
340 	unsigned long lpfn, num_nodes, pages_per_node, pages_left;
341 	uint64_t vis_usage = 0, mem_bytes, max_bytes;
342 	unsigned i;
343 	int r;
344 
345 	lpfn = place->lpfn;
346 	if (!lpfn)
347 		lpfn = man->size;
348 
349 	max_bytes = adev->gmc.mc_vram_size;
350 	if (tbo->type != ttm_bo_type_kernel)
351 		max_bytes -= AMDGPU_VM_RESERVED_VRAM;
352 
353 	/* bail out quickly if there's likely not enough VRAM for this BO */
354 	mem_bytes = (u64)mem->num_pages << PAGE_SHIFT;
355 	if (atomic64_add_return(mem_bytes, &mgr->usage) > max_bytes) {
356 		atomic64_sub(mem_bytes, &mgr->usage);
357 		mem->mm_node = NULL;
358 		return 0;
359 	}
360 
361 	if (place->flags & TTM_PL_FLAG_CONTIGUOUS) {
362 		pages_per_node = ~0ul;
363 		num_nodes = 1;
364 	} else {
365 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
366 		pages_per_node = HPAGE_PMD_NR;
367 #else
368 		/* default to 2MB */
369 		pages_per_node = (2UL << (20UL - PAGE_SHIFT));
370 #endif
371 		pages_per_node = max((uint32_t)pages_per_node, mem->page_alignment);
372 		num_nodes = DIV_ROUND_UP(mem->num_pages, pages_per_node);
373 	}
374 
375 	nodes = kvmalloc_array((uint32_t)num_nodes, sizeof(*nodes),
376 			       GFP_KERNEL | __GFP_ZERO);
377 	if (!nodes) {
378 		atomic64_sub(mem_bytes, &mgr->usage);
379 		return -ENOMEM;
380 	}
381 
382 	mode = DRM_MM_INSERT_BEST;
383 	if (place->flags & TTM_PL_FLAG_TOPDOWN)
384 		mode = DRM_MM_INSERT_HIGH;
385 
386 	mem->start = 0;
387 	pages_left = mem->num_pages;
388 
389 	spin_lock(&mgr->lock);
390 	for (i = 0; pages_left >= pages_per_node; ++i) {
391 		unsigned long pages = rounddown_pow_of_two(pages_left);
392 
393 		r = drm_mm_insert_node_in_range(mm, &nodes[i], pages,
394 						pages_per_node, 0,
395 						place->fpfn, lpfn,
396 						mode);
397 		if (unlikely(r))
398 			break;
399 
400 		vis_usage += amdgpu_vram_mgr_vis_size(adev, &nodes[i]);
401 		amdgpu_vram_mgr_virt_start(mem, &nodes[i]);
402 		pages_left -= pages;
403 	}
404 
405 	for (; pages_left; ++i) {
406 		unsigned long pages = min(pages_left, pages_per_node);
407 		uint32_t alignment = mem->page_alignment;
408 
409 		if (pages == pages_per_node)
410 			alignment = pages_per_node;
411 
412 		r = drm_mm_insert_node_in_range(mm, &nodes[i],
413 						pages, alignment, 0,
414 						place->fpfn, lpfn,
415 						mode);
416 		if (unlikely(r))
417 			goto error;
418 
419 		vis_usage += amdgpu_vram_mgr_vis_size(adev, &nodes[i]);
420 		amdgpu_vram_mgr_virt_start(mem, &nodes[i]);
421 		pages_left -= pages;
422 	}
423 	spin_unlock(&mgr->lock);
424 
425 	atomic64_add(vis_usage, &mgr->vis_usage);
426 
427 	mem->mm_node = nodes;
428 
429 	return 0;
430 
431 error:
432 	while (i--)
433 		drm_mm_remove_node(&nodes[i]);
434 	spin_unlock(&mgr->lock);
435 	atomic64_sub(mem->num_pages << PAGE_SHIFT, &mgr->usage);
436 
437 	kvfree(nodes);
438 	return r == -ENOSPC ? 0 : r;
439 }
440 
441 /**
442  * amdgpu_vram_mgr_del - free ranges
443  *
444  * @man: TTM memory type manager
445  * @tbo: TTM BO we need this range for
446  * @place: placement flags and restrictions
447  * @mem: TTM memory object
448  *
449  * Free the allocated VRAM again.
450  */
amdgpu_vram_mgr_del(struct ttm_mem_type_manager * man,struct ttm_mem_reg * mem)451 static void amdgpu_vram_mgr_del(struct ttm_mem_type_manager *man,
452 				struct ttm_mem_reg *mem)
453 {
454 	struct amdgpu_device *adev = amdgpu_ttm_adev(man->bdev);
455 	struct amdgpu_vram_mgr *mgr = man->priv;
456 	struct drm_mm_node *nodes = mem->mm_node;
457 	uint64_t usage = 0, vis_usage = 0;
458 	unsigned pages = mem->num_pages;
459 
460 	if (!mem->mm_node)
461 		return;
462 
463 	spin_lock(&mgr->lock);
464 	while (pages) {
465 		pages -= nodes->size;
466 		drm_mm_remove_node(nodes);
467 		usage += nodes->size << PAGE_SHIFT;
468 		vis_usage += amdgpu_vram_mgr_vis_size(adev, nodes);
469 		++nodes;
470 	}
471 	spin_unlock(&mgr->lock);
472 
473 	atomic64_sub(usage, &mgr->usage);
474 	atomic64_sub(vis_usage, &mgr->vis_usage);
475 
476 	kvfree(mem->mm_node);
477 	mem->mm_node = NULL;
478 }
479 
480 /**
481  * amdgpu_vram_mgr_usage - how many bytes are used in this domain
482  *
483  * @man: TTM memory type manager
484  *
485  * Returns how many bytes are used in this domain.
486  */
amdgpu_vram_mgr_usage(struct ttm_mem_type_manager * man)487 uint64_t amdgpu_vram_mgr_usage(struct ttm_mem_type_manager *man)
488 {
489 	struct amdgpu_vram_mgr *mgr = man->priv;
490 
491 	return atomic64_read(&mgr->usage);
492 }
493 
494 /**
495  * amdgpu_vram_mgr_vis_usage - how many bytes are used in the visible part
496  *
497  * @man: TTM memory type manager
498  *
499  * Returns how many bytes are used in the visible part of VRAM
500  */
amdgpu_vram_mgr_vis_usage(struct ttm_mem_type_manager * man)501 uint64_t amdgpu_vram_mgr_vis_usage(struct ttm_mem_type_manager *man)
502 {
503 	struct amdgpu_vram_mgr *mgr = man->priv;
504 
505 	return atomic64_read(&mgr->vis_usage);
506 }
507 
508 /**
509  * amdgpu_vram_mgr_debug - dump VRAM table
510  *
511  * @man: TTM memory type manager
512  * @printer: DRM printer to use
513  *
514  * Dump the table content using printk.
515  */
amdgpu_vram_mgr_debug(struct ttm_mem_type_manager * man,struct drm_printer * printer)516 static void amdgpu_vram_mgr_debug(struct ttm_mem_type_manager *man,
517 				  struct drm_printer *printer)
518 {
519 	struct amdgpu_vram_mgr *mgr = man->priv;
520 
521 	spin_lock(&mgr->lock);
522 	drm_mm_print(&mgr->mm, printer);
523 	spin_unlock(&mgr->lock);
524 
525 	drm_printf(printer, "man size:%"PRIu64" pages, ram usage:%"PRIu64"MB, vis usage:%"PRIu64"MB\n",
526 		   man->size, amdgpu_vram_mgr_usage(man) >> 20,
527 		   amdgpu_vram_mgr_vis_usage(man) >> 20);
528 }
529 
530 const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func = {
531 	.init		= amdgpu_vram_mgr_init,
532 	.takedown	= amdgpu_vram_mgr_fini,
533 	.get_node	= amdgpu_vram_mgr_new,
534 	.put_node	= amdgpu_vram_mgr_del,
535 	.debug		= amdgpu_vram_mgr_debug
536 };
537