summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2020-11-10 17:48:47 +1000
committerDave Airlie <airlied@redhat.com>2020-11-10 17:48:47 +1000
commit5b8c596976d4338942dd889b66cd06dc766424e1 (patch)
tree0fdcc1cc3c51daaf39400f72caf4f10d99d43541 /drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
parentc0f98d2f8b076bf3e3183aa547395f919c943a14 (diff)
parent514ad1b6bb6e2fa205b5511bd3d50e33457f6180 (diff)
Merge tag 'amd-drm-next-5.11-2020-11-05' of git://people.freedesktop.org/~agd5f/linux into drm-next
amd-drm-next-5.11-2020-11-05: amdgpu: - Add initial support for Vangogh - Add support for Green Sardine - Add initial support for Dimgrey Cavefish - Scatter/Gather display support for Renoir - Updates for Sienna Cichlid - Updates for Navy Flounder - SMU7 power improvements - Modifier support for gfx9+ - CI BACO fixes - Arcturus SMU fixes - Lots of code cleanups - DC fixes - Kernel doc fixes - Add more GPU HW client information to page fault error logging - MPO clock tuning for RV - FP fixes for DCN3 on ARM and PPC radeon: - Expose voltage via hwmon on Sumo APUs amdkfd: - Fix unique id handling - Misc fixes From: Alex Deucher <alexdeucher@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/20201105222749.201798-1-alexander.deucher@amd.com
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c115
1 files changed, 110 insertions, 5 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
index 7747be644dd0..c99c2180785f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
@@ -168,8 +168,7 @@ static const struct ttm_resource_manager_func amdgpu_vram_mgr_func;
/**
* amdgpu_vram_mgr_init - init VRAM manager and DRM MM
*
- * @man: TTM memory type manager
- * @p_size: maximum size of VRAM
+ * @adev: amdgpu_device pointer
*
* Allocate and initialize the VRAM manager.
*/
@@ -185,6 +184,8 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev)
drm_mm_init(&mgr->mm, 0, man->size);
spin_lock_init(&mgr->lock);
+ INIT_LIST_HEAD(&mgr->reservations_pending);
+ INIT_LIST_HEAD(&mgr->reserved_pages);
/* Add the two VRAM-related sysfs files */
ret = sysfs_create_files(&adev->dev->kobj, amdgpu_vram_mgr_attributes);
@@ -199,7 +200,7 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev)
/**
* amdgpu_vram_mgr_fini - free and destroy VRAM manager
*
- * @man: TTM memory type manager
+ * @adev: amdgpu_device pointer
*
* Destroy and free the VRAM manager, returns -EBUSY if ranges are still
* allocated inside it.
@@ -209,6 +210,7 @@ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev)
struct amdgpu_vram_mgr *mgr = &adev->mman.vram_mgr;
struct ttm_resource_manager *man = &mgr->manager;
int ret;
+ struct amdgpu_vram_reservation *rsv, *temp;
ttm_resource_manager_set_used(man, false);
@@ -217,6 +219,13 @@ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev)
return;
spin_lock(&mgr->lock);
+ list_for_each_entry_safe(rsv, temp, &mgr->reservations_pending, node)
+ kfree(rsv);
+
+ list_for_each_entry_safe(rsv, temp, &mgr->reserved_pages, node) {
+ drm_mm_remove_node(&rsv->mm_node);
+ kfree(rsv);
+ }
drm_mm_takedown(&mgr->mm);
spin_unlock(&mgr->lock);
@@ -229,7 +238,7 @@ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev)
/**
* amdgpu_vram_mgr_vis_size - Calculate visible node size
*
- * @adev: amdgpu device structure
+ * @adev: amdgpu_device pointer
* @node: MM node structure
*
* Calculate how many bytes of the MM node are inside visible VRAM
@@ -275,6 +284,101 @@ u64 amdgpu_vram_mgr_bo_visible_size(struct amdgpu_bo *bo)
return usage;
}
+static void amdgpu_vram_mgr_do_reserve(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 *mm = &mgr->mm;
+ struct amdgpu_vram_reservation *rsv, *temp;
+ uint64_t vis_usage;
+
+ list_for_each_entry_safe(rsv, temp, &mgr->reservations_pending, node) {
+ if (drm_mm_reserve_node(mm, &rsv->mm_node))
+ continue;
+
+ dev_dbg(adev->dev, "Reservation 0x%llx - %lld, Succeeded\n",
+ rsv->mm_node.start, rsv->mm_node.size);
+
+ vis_usage = amdgpu_vram_mgr_vis_size(adev, &rsv->mm_node);
+ atomic64_add(vis_usage, &mgr->vis_usage);
+ atomic64_add(rsv->mm_node.size << PAGE_SHIFT, &mgr->usage);
+ list_move(&rsv->node, &mgr->reserved_pages);
+ }
+}
+
+/**
+ * amdgpu_vram_mgr_reserve_range - Reserve a range from VRAM
+ *
+ * @man: TTM memory type manager
+ * @start: start address of the range in VRAM
+ * @size: size of the range
+ *
+ * Reserve memory from start addess with the specified size in VRAM
+ */
+int amdgpu_vram_mgr_reserve_range(struct ttm_resource_manager *man,
+ uint64_t start, uint64_t size)
+{
+ struct amdgpu_vram_mgr *mgr = to_vram_mgr(man);
+ struct amdgpu_vram_reservation *rsv;
+
+ rsv = kzalloc(sizeof(*rsv), GFP_KERNEL);
+ if (!rsv)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&rsv->node);
+ rsv->mm_node.start = start >> PAGE_SHIFT;
+ rsv->mm_node.size = size >> PAGE_SHIFT;
+
+ spin_lock(&mgr->lock);
+ list_add_tail(&mgr->reservations_pending, &rsv->node);
+ amdgpu_vram_mgr_do_reserve(man);
+ spin_unlock(&mgr->lock);
+
+ return 0;
+}
+
+/**
+ * amdgpu_vram_mgr_query_page_status - query the reservation status
+ *
+ * @man: TTM memory type manager
+ * @start: start address of a page in VRAM
+ *
+ * Returns:
+ * -EBUSY: the page is still hold and in pending list
+ * 0: the page has been reserved
+ * -ENOENT: the input page is not a reservation
+ */
+int amdgpu_vram_mgr_query_page_status(struct ttm_resource_manager *man,
+ uint64_t start)
+{
+ struct amdgpu_vram_mgr *mgr = to_vram_mgr(man);
+ struct amdgpu_vram_reservation *rsv;
+ int ret;
+
+ spin_lock(&mgr->lock);
+
+ list_for_each_entry(rsv, &mgr->reservations_pending, node) {
+ if ((rsv->mm_node.start <= start) &&
+ (start < (rsv->mm_node.start + rsv->mm_node.size))) {
+ ret = -EBUSY;
+ goto out;
+ }
+ }
+
+ list_for_each_entry(rsv, &mgr->reserved_pages, node) {
+ if ((rsv->mm_node.start <= start) &&
+ (start < (rsv->mm_node.start + rsv->mm_node.size))) {
+ ret = 0;
+ goto out;
+ }
+ }
+
+ ret = -ENOENT;
+out:
+ spin_unlock(&mgr->lock);
+ return ret;
+}
+
/**
* amdgpu_vram_mgr_virt_start - update virtual start address
*
@@ -445,6 +549,7 @@ static void amdgpu_vram_mgr_del(struct ttm_resource_manager *man,
vis_usage += amdgpu_vram_mgr_vis_size(adev, nodes);
++nodes;
}
+ amdgpu_vram_mgr_do_reserve(man);
spin_unlock(&mgr->lock);
atomic64_sub(usage, &mgr->usage);
@@ -529,7 +634,7 @@ error_free:
}
/**
- * amdgpu_vram_mgr_alloc_sgt - allocate and fill a sg table
+ * amdgpu_vram_mgr_free_sgt - allocate and fill a sg table
*
* @adev: amdgpu device pointer
* @sgt: sg table to free