Signed-off-by: Yang Wang <KevinYang.Wang@xxxxxxx>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 6 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 3 +
drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 130
++++++++++++++++++-
drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h | 1 +
4 files changed, 136 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
index 90eb07106609..117c754409b3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
@@ -53,7 +53,7 @@
*
*/
-static void amdgpu_bo_destroy(struct ttm_buffer_object *tbo)
+void amdgpu_bo_destroy(struct ttm_buffer_object *tbo)
{
struct amdgpu_bo *bo = ttm_to_amdgpu_bo(tbo);
@@ -66,7 +66,7 @@ static void amdgpu_bo_destroy(struct
ttm_buffer_object *tbo)
kvfree(bo);
}
-static void amdgpu_bo_user_destroy(struct ttm_buffer_object *tbo)
+void amdgpu_bo_user_destroy(struct ttm_buffer_object *tbo)
{
struct amdgpu_bo *bo = ttm_to_amdgpu_bo(tbo);
struct amdgpu_bo_user *ubo;
@@ -76,7 +76,7 @@ static void amdgpu_bo_user_destroy(struct
ttm_buffer_object *tbo)
amdgpu_bo_destroy(tbo);
}
-static void amdgpu_bo_vm_destroy(struct ttm_buffer_object *tbo)
+void amdgpu_bo_vm_destroy(struct ttm_buffer_object *tbo)
{
struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev);
struct amdgpu_bo *bo = ttm_to_amdgpu_bo(tbo); diff --git
a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
index 147b79c10cbb..3f6a687309a7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
@@ -332,6 +332,9 @@ int amdgpu_bo_restore_shadow(struct amdgpu_bo
*shadow,
struct dma_fence **fence);
uint32_t amdgpu_bo_get_preferred_domain(struct amdgpu_device
*adev,
uint32_t domain);
+void amdgpu_bo_destroy(struct ttm_buffer_object *tbo); void
+amdgpu_bo_user_destroy(struct ttm_buffer_object *tbo); void
+amdgpu_bo_vm_destroy(struct ttm_buffer_object *tbo);
/*
* sub allocation
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
index 27159f1d112e..165f4f1a8141 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
@@ -23,9 +23,11 @@
*/
#include <linux/dma-mapping.h>
+#include <linux/interval_tree_generic.h>
#include <drm/ttm/ttm_range_manager.h>
#include "amdgpu.h"
+#include "amdgpu_object.h"
#include "amdgpu_vm.h"
#include "amdgpu_res_cursor.h"
#include "amdgpu_atomfirmware.h"
@@ -38,6 +40,122 @@ struct amdgpu_vram_reservation {
struct list_head blocks;
};
+struct amdgpu_vram_node {
+ struct rb_node node;
+ u64 start;
+ u64 last;
+ u64 __subtree_last;
+ struct ttm_buffer_object *tbo; };
+
+#define START(node) ((node)->start) #define LAST(node)
+((node)->last)
+
+INTERVAL_TREE_DEFINE(struct amdgpu_vram_node, node, u64,
__subtree_last,
+ START, LAST, static, amdgpu_vram_it)
+
+#undef START
+#undef LAST
+
+#define for_each_vram_mm_node(node, mgr) \
+ for (node = amdgpu_vram_it_iter_first(&(mgr)->root, 0,
U64_MAX); node; \
+ node = amdgpu_vram_it_iter_next(node, 0, U64_MAX))
+
+static void amdgpu_vram_mm_add_block(struct drm_buddy_block *block,
+struct amdgpu_vram_mgr *mgr, struct ttm_buffer_object *tbo) {
+ struct amdgpu_vram_node *node;
+
+ node = kvzalloc(sizeof(*node), GFP_KERNEL);
+ if (!node)
+ return;
+
+ node->start = amdgpu_vram_mgr_block_start(block);
+ node->last = node->start + amdgpu_vram_mgr_block_size(block) -
+1;
+ node->tbo = tbo;
+
+ amdgpu_vram_it_insert(node, &mgr->root); }
+
+static void amdgpu_vram_mm_remove_block(struct drm_buddy_block
+*block, struct amdgpu_vram_mgr *mgr) {
+ struct amdgpu_vram_node *node;
+ u64 start, last;
+
+ start = amdgpu_vram_mgr_block_start(block);
+ last = start + amdgpu_vram_mgr_block_size(block) - 1;
+
+ node = amdgpu_vram_it_iter_first(&mgr->root, start, last);
+ if (node) {
+ amdgpu_vram_it_remove(node, &mgr->root);
+ kvfree(node);
+ }
+}
+
+static inline const char* ttm_bo_type2str(enum ttm_bo_type type) {
+ switch (type) {
+ case ttm_bo_type_kernel:
+ return "kernel";
+ case ttm_bo_type_device:
+ return "device";
+ case ttm_bo_type_sg:
+ return "sg";
+ default:
+ return "unknow";
+ }
+}
+
+static inline const char* amdgpu_vram_domain_str(u32 domain, char
+*tmp) {
+ int index = 0;
+
+ tmp[index++] = domain & AMDGPU_GEM_DOMAIN_CPU ? 'C' : '-';
+ tmp[index++] = domain & AMDGPU_GEM_DOMAIN_GTT ? 'G' : '-';
+ tmp[index++] = domain & AMDGPU_GEM_DOMAIN_VRAM ? 'V' : '-';
+ tmp[index++] = domain & (AMDGPU_GEM_DOMAIN_GDS |
AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA) ?
+ 'P' : '-';
+ tmp[index++] = '\0';
+
+ return tmp;
+}
+
+static inline const char* amdgpu_vram_bo_usage(struct
+ttm_buffer_object *tbo) {
+ if (tbo->destroy == &amdgpu_bo_destroy)
+ return "normal";
+ else if (tbo->destroy == &amdgpu_bo_user_destroy)
+ return "user";
+ else if (tbo->destroy == &amdgpu_bo_vm_destroy)
+ return "vm";
+ else
+ return "unknow";
+}
+
+static void amdgpu_vram_mm_debug(struct amdgpu_vram_mgr *mgr,
+struct drm_printer *p) {
+ struct amdgpu_vram_node *node;
+ struct ttm_buffer_object *tbo;
+ struct amdgpu_bo *abo;
+ char tmp[5];
+
+ for_each_vram_mm_node(node, mgr) {
+ tbo = node->tbo;
+ abo = ttm_to_amdgpu_bo(tbo);
+ drm_printf(p, "%#018llx-%#018llx:", node->start,
node->last);
+ if (abo)
+ drm_printf(p, " (type:%-5s usage:%-8s
domain:%s %s) @%p",
+ ttm_bo_type2str(tbo->type),
+ amdgpu_vram_bo_usage(tbo),
+amdgpu_vram_domain_str(abo->preferred_domains, tmp),
+amdgpu_vram_domain_str(abo->allowed_domains, tmp),
+ abo);
+ else
+ drm_printf(p, " (reserved)");
+ drm_printf(p, " %llu bytes\n",
+ node->last - node->start + 1);
+ }
+}
+
static inline struct amdgpu_vram_mgr *
to_vram_mgr(struct ttm_resource_manager *man)
{
@@ -288,6 +406,7 @@ static void amdgpu_vram_mgr_do_reserve(struct
ttm_resource_manager *man)
dev_dbg(adev->dev, "Reservation 0x%llx - %lld,
Succeeded\n",
rsv->start, rsv->size);
+ amdgpu_vram_mm_add_block(block, mgr, NULL);
vis_usage = amdgpu_vram_mgr_vis_size(adev, block);
atomic64_add(vis_usage, &mgr->vis_usage);
spin_lock(&man->bdev->lru_lock); @@ -540,6 +659,8 @@
static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
vres->base.start = max(vres->base.start, start);
vis_usage += amdgpu_vram_mgr_vis_size(adev, block);
+
+ amdgpu_vram_mm_add_block(block, mgr, tbo);
}
if (amdgpu_is_vram_mgr_blocks_contiguous(&vres->blocks))
@@ -583,8 +704,10 @@ static void amdgpu_vram_mgr_del(struct
ttm_resource_manager *man,
uint64_t vis_usage = 0;
mutex_lock(&mgr->lock);
- list_for_each_entry(block, &vres->blocks, link)
+ list_for_each_entry(block, &vres->blocks, link) {
vis_usage += amdgpu_vram_mgr_vis_size(adev, block);
+ amdgpu_vram_mm_remove_block(block, mgr);
+ }
amdgpu_vram_mgr_do_reserve(man);
@@ -747,6 +870,9 @@ static void amdgpu_vram_mgr_debug(struct
ttm_resource_manager *man,
drm_printf(printer, "reserved:\n");
list_for_each_entry(block, &mgr->reserved_pages, link)
drm_buddy_block_print(mm, block, printer);
+ drm_printf(printer, "vram usage:\n");
+ amdgpu_vram_mm_debug(mgr, printer);
+
mutex_unlock(&mgr->lock);
}
@@ -769,6 +895,8 @@ int amdgpu_vram_mgr_init(struct amdgpu_device
*adev)
struct ttm_resource_manager *man = &mgr->manager;
int err;
+ mgr->root = RB_ROOT_CACHED;
+
ttm_resource_manager_init(man, &adev->mman.bdev,
adev->gmc.real_vram_size);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h
index 0e04e42cf809..a14c56e1e407 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h
@@ -28,6 +28,7 @@
struct amdgpu_vram_mgr {
struct ttm_resource_manager manager;
+ struct rb_root_cached root;
struct drm_buddy mm;
/* protects access to buffer objects */
struct mutex lock;