Commit 267501ec authored by Christian König's avatar Christian König
Browse files

drm/amdgpu: switch the VRAM backend to self alloc

parent f700b18c
Loading
Loading
Loading
Loading
+30 −21
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@
 */

#include <linux/dma-mapping.h>
#include <drm/ttm/ttm_range_manager.h>

#include "amdgpu.h"
#include "amdgpu_vm.h"
#include "amdgpu_res_cursor.h"
@@ -371,9 +373,9 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
	struct amdgpu_vram_mgr *mgr = to_vram_mgr(man);
	struct amdgpu_device *adev = to_amdgpu_device(mgr);
	uint64_t vis_usage = 0, mem_bytes, max_bytes;
	struct ttm_range_mgr_node *node;
	struct drm_mm *mm = &mgr->mm;
	enum drm_mm_insert_mode mode;
	struct drm_mm_node *nodes;
	unsigned i;
	int r;

@@ -388,8 +390,8 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
	/* bail out quickly if there's likely not enough VRAM for this BO */
	mem_bytes = (u64)mem->num_pages << PAGE_SHIFT;
	if (atomic64_add_return(mem_bytes, &mgr->usage) > max_bytes) {
		atomic64_sub(mem_bytes, &mgr->usage);
		return -ENOSPC;
		r = -ENOSPC;
		goto error_sub;
	}

	if (place->flags & TTM_PL_FLAG_CONTIGUOUS) {
@@ -407,13 +409,15 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
		num_nodes = DIV_ROUND_UP(mem->num_pages, pages_per_node);
	}

	nodes = kvmalloc_array((uint32_t)num_nodes, sizeof(*nodes),
	node = kvmalloc(struct_size(node, mm_nodes, num_nodes),
			GFP_KERNEL | __GFP_ZERO);
	if (!nodes) {
		atomic64_sub(mem_bytes, &mgr->usage);
		return -ENOMEM;
	if (!node) {
		r = -ENOMEM;
		goto error_sub;
	}

	ttm_resource_init(tbo, place, &node->base);

	mode = DRM_MM_INSERT_BEST;
	if (place->flags & TTM_PL_FLAG_TOPDOWN)
		mode = DRM_MM_INSERT_HIGH;
@@ -432,8 +436,9 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
		if (pages >= pages_per_node)
			alignment = pages_per_node;

		r = drm_mm_insert_node_in_range(mm, &nodes[i], pages, alignment,
						0, place->fpfn, lpfn, mode);
		r = drm_mm_insert_node_in_range(mm, &node->mm_nodes[i], pages,
						alignment, 0, place->fpfn,
						lpfn, mode);
		if (unlikely(r)) {
			if (pages > pages_per_node) {
				if (is_power_of_2(pages))
@@ -442,11 +447,11 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
					pages = rounddown_pow_of_two(pages);
				continue;
			}
			goto error;
			goto error_free;
		}

		vis_usage += amdgpu_vram_mgr_vis_size(adev, &nodes[i]);
		amdgpu_vram_mgr_virt_start(mem, &nodes[i]);
		vis_usage += amdgpu_vram_mgr_vis_size(adev, &node->mm_nodes[i]);
		amdgpu_vram_mgr_virt_start(mem, &node->mm_nodes[i]);
		pages_left -= pages;
		++i;

@@ -459,16 +464,17 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
		mem->placement |= TTM_PL_FLAG_CONTIGUOUS;

	atomic64_add(vis_usage, &mgr->vis_usage);
	mem->mm_node = nodes;
	mem->mm_node = &node->mm_nodes[0];
	return 0;

error:
error_free:
	while (i--)
		drm_mm_remove_node(&nodes[i]);
		drm_mm_remove_node(&node->mm_nodes[i]);
	spin_unlock(&mgr->lock);
	atomic64_sub(mem->num_pages << PAGE_SHIFT, &mgr->usage);
	kvfree(node);

	kvfree(nodes);
error_sub:
	atomic64_sub(mem_bytes, &mgr->usage);
	return r;
}

@@ -485,13 +491,17 @@ static void amdgpu_vram_mgr_del(struct ttm_resource_manager *man,
{
	struct amdgpu_vram_mgr *mgr = to_vram_mgr(man);
	struct amdgpu_device *adev = to_amdgpu_device(mgr);
	struct drm_mm_node *nodes = mem->mm_node;
	struct ttm_range_mgr_node *node;
	uint64_t usage = 0, vis_usage = 0;
	unsigned pages = mem->num_pages;
	struct drm_mm_node *nodes;

	if (!mem->mm_node)
		return;

	node = to_ttm_range_mgr_node(mem);
	nodes = &node->mm_nodes[0];

	spin_lock(&mgr->lock);
	while (pages) {
		pages -= nodes->size;
@@ -506,8 +516,7 @@ static void amdgpu_vram_mgr_del(struct ttm_resource_manager *man,
	atomic64_sub(usage, &mgr->usage);
	atomic64_sub(vis_usage, &mgr->vis_usage);

	kvfree(mem->mm_node);
	mem->mm_node = NULL;
	kvfree(node);
}

/**