From f89b881c81d9a6481fc17b46b351ca38f5dd6f3a Mon Sep 17 00:00:00 2001 From: Dennis Li Date: Mon, 22 Feb 2021 18:22:57 +0800 Subject: drm/amdgpu: reserve backup pages for bad page retirment To ensure user has a constant of VRAM accessible in run-time, driver reserves limit backup pages when init, and return ones when bad pages retired, to keep no change of unused memory size. v2: refine codes to calculate badpags threshold Reviewed-by: Hawking Zhang Signed-off-by: Dennis Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 96 +++++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index c89b66bb70e2..de7db14de8ef 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -28,6 +28,9 @@ #include "amdgpu_atomfirmware.h" #include "atom.h" +static int amdgpu_vram_mgr_free_backup_pages(struct amdgpu_vram_mgr *mgr, + uint32_t num_pages); + static inline struct amdgpu_vram_mgr *to_vram_mgr(struct ttm_resource_manager *man) { return container_of(man, struct amdgpu_vram_mgr, manager); @@ -186,6 +189,7 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev) spin_lock_init(&mgr->lock); INIT_LIST_HEAD(&mgr->reservations_pending); INIT_LIST_HEAD(&mgr->reserved_pages); + INIT_LIST_HEAD(&mgr->backup_pages); /* Add the two VRAM-related sysfs files */ ret = sysfs_create_files(&adev->dev->kobj, amdgpu_vram_mgr_attributes); @@ -226,6 +230,11 @@ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev) drm_mm_remove_node(&rsv->mm_node); kfree(rsv); } + + list_for_each_entry_safe(rsv, temp, &mgr->backup_pages, node) { + drm_mm_remove_node(&rsv->mm_node); + kfree(rsv); + } drm_mm_takedown(&mgr->mm); spin_unlock(&mgr->lock); @@ -297,12 +306,14 @@ static void amdgpu_vram_mgr_do_reserve(struct ttm_resource_manager *man) continue; dev_dbg(adev->dev, "Reservation 0x%llx - %lld, Succeeded\n", - rsv->mm_node.start, rsv->mm_node.size); + rsv->mm_node.start << PAGE_SHIFT, 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_free_backup_pages(mgr, rsv->mm_node.size); } } @@ -319,6 +330,7 @@ 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_device *adev = to_amdgpu_device(mgr); struct amdgpu_vram_reservation *rsv; rsv = kzalloc(sizeof(*rsv), GFP_KERNEL); @@ -329,14 +341,94 @@ int amdgpu_vram_mgr_reserve_range(struct ttm_resource_manager *man, rsv->mm_node.start = start >> PAGE_SHIFT; rsv->mm_node.size = size >> PAGE_SHIFT; + dev_dbg(adev->dev, "Pending Reservation: 0x%llx\n", start); + spin_lock(&mgr->lock); - list_add_tail(&mgr->reservations_pending, &rsv->node); + list_add_tail(&rsv->node, &mgr->reservations_pending); amdgpu_vram_mgr_do_reserve(man); spin_unlock(&mgr->lock); return 0; } +static int amdgpu_vram_mgr_free_backup_pages(struct amdgpu_vram_mgr *mgr, + uint32_t num_pages) +{ + struct amdgpu_device *adev = to_amdgpu_device(mgr); + struct amdgpu_vram_reservation *rsv; + uint32_t i; + uint64_t vis_usage = 0, total_usage = 0; + + if (num_pages > mgr->num_backup_pages) { + dev_warn(adev->dev, "No enough backup pages\n"); + return -EINVAL; + } + + for (i = 0; i < num_pages; i++) { + rsv = list_first_entry(&mgr->backup_pages, + struct amdgpu_vram_reservation, node); + vis_usage += amdgpu_vram_mgr_vis_size(adev, &rsv->mm_node); + total_usage += (rsv->mm_node.size << PAGE_SHIFT); + drm_mm_remove_node(&rsv->mm_node); + list_del(&rsv->node); + kfree(rsv); + mgr->num_backup_pages--; + } + + atomic64_sub(total_usage, &mgr->usage); + atomic64_sub(vis_usage, &mgr->vis_usage); + + return 0; +} + +int amdgpu_vram_mgr_reserve_backup_pages(struct ttm_resource_manager *man, + uint32_t num_pages) +{ + struct amdgpu_vram_mgr *mgr = to_vram_mgr(man); + struct amdgpu_device *adev = to_amdgpu_device(mgr); + struct amdgpu_vram_reservation *rsv; + struct drm_mm *mm = &mgr->mm; + uint32_t i; + int ret = 0; + uint64_t vis_usage, total_usage; + + for (i = 0; i < num_pages; i++) { + rsv = kzalloc(sizeof(*rsv), GFP_KERNEL); + if (!rsv) { + ret = -ENOMEM; + goto pro_end; + } + + INIT_LIST_HEAD(&rsv->node); + + ret = drm_mm_insert_node(mm, &rsv->mm_node, 1); + if (ret) { + dev_err(adev->dev, "failed to reserve backup page %d, ret 0x%x\n", i, ret); + kfree(rsv); + goto pro_end; + } + + vis_usage = amdgpu_vram_mgr_vis_size(adev, &rsv->mm_node); + total_usage = (rsv->mm_node.size << PAGE_SHIFT); + + spin_lock(&mgr->lock); + atomic64_add(vis_usage, &mgr->vis_usage); + atomic64_add(total_usage, &mgr->usage); + list_add_tail(&rsv->node, &mgr->backup_pages); + mgr->num_backup_pages++; + spin_unlock(&mgr->lock); + } + +pro_end: + if (ret) { + spin_lock(&mgr->lock); + amdgpu_vram_mgr_free_backup_pages(mgr, mgr->num_backup_pages); + spin_unlock(&mgr->lock); + } + + return ret; +} + /** * amdgpu_vram_mgr_query_page_status - query the reservation status * -- cgit v1.2.3 From 5392b2af97dc5802991f953eb2687e538da4688c Mon Sep 17 00:00:00 2001 From: Ramesh Errabolu Date: Wed, 24 Feb 2021 20:48:06 -0600 Subject: drm/amdgpu: Remove amdgpu_device arg from free_sgt api (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently callers have to provide handle of amdgpu_device, which is not used by the implementation. It is unlikely this parameter will become useful in future, thus removing it v2: squash in unused variable fix Reviewed-by: Christian König Signed-off-by: Ramesh Errabolu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index de7db14de8ef..96fa1833cd92 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -731,15 +731,13 @@ error_free: /** * amdgpu_vram_mgr_free_sgt - allocate and fill a sg table * - * @adev: amdgpu device pointer * @dev: device pointer * @dir: data direction of resource to unmap * @sgt: sg table to free * * Free a previously allocate sg table. */ -void amdgpu_vram_mgr_free_sgt(struct amdgpu_device *adev, - struct device *dev, +void amdgpu_vram_mgr_free_sgt(struct device *dev, enum dma_data_direction dir, struct sg_table *sgt) { -- cgit v1.2.3 From e5c04edfcde373b093d2a07322873b3ce1c5b88e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 18 Mar 2021 14:04:06 +0100 Subject: drm/amdgpu: revert "reserve backup pages for bad page retirment" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As noted during the review this approach doesn't make sense at all. We should not apply any limitation on the VRAM applications can use inside the kernel. If an application or end user wants to reserve a certain amount of VRAM for bad pages handling we should do this in the upper layer. This reverts commit f89b881c81d9a6481fc17b46b351ca38f5dd6f3a. Signed-off-by: Christian König Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 96 +--------------------------- 1 file changed, 2 insertions(+), 94 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 96fa1833cd92..b2fc475ce6f7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -28,9 +28,6 @@ #include "amdgpu_atomfirmware.h" #include "atom.h" -static int amdgpu_vram_mgr_free_backup_pages(struct amdgpu_vram_mgr *mgr, - uint32_t num_pages); - static inline struct amdgpu_vram_mgr *to_vram_mgr(struct ttm_resource_manager *man) { return container_of(man, struct amdgpu_vram_mgr, manager); @@ -189,7 +186,6 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev) spin_lock_init(&mgr->lock); INIT_LIST_HEAD(&mgr->reservations_pending); INIT_LIST_HEAD(&mgr->reserved_pages); - INIT_LIST_HEAD(&mgr->backup_pages); /* Add the two VRAM-related sysfs files */ ret = sysfs_create_files(&adev->dev->kobj, amdgpu_vram_mgr_attributes); @@ -230,11 +226,6 @@ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev) drm_mm_remove_node(&rsv->mm_node); kfree(rsv); } - - list_for_each_entry_safe(rsv, temp, &mgr->backup_pages, node) { - drm_mm_remove_node(&rsv->mm_node); - kfree(rsv); - } drm_mm_takedown(&mgr->mm); spin_unlock(&mgr->lock); @@ -306,14 +297,12 @@ static void amdgpu_vram_mgr_do_reserve(struct ttm_resource_manager *man) continue; dev_dbg(adev->dev, "Reservation 0x%llx - %lld, Succeeded\n", - rsv->mm_node.start << PAGE_SHIFT, rsv->mm_node.size); + 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_free_backup_pages(mgr, rsv->mm_node.size); } } @@ -330,7 +319,6 @@ 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_device *adev = to_amdgpu_device(mgr); struct amdgpu_vram_reservation *rsv; rsv = kzalloc(sizeof(*rsv), GFP_KERNEL); @@ -341,94 +329,14 @@ int amdgpu_vram_mgr_reserve_range(struct ttm_resource_manager *man, rsv->mm_node.start = start >> PAGE_SHIFT; rsv->mm_node.size = size >> PAGE_SHIFT; - dev_dbg(adev->dev, "Pending Reservation: 0x%llx\n", start); - spin_lock(&mgr->lock); - list_add_tail(&rsv->node, &mgr->reservations_pending); + list_add_tail(&mgr->reservations_pending, &rsv->node); amdgpu_vram_mgr_do_reserve(man); spin_unlock(&mgr->lock); return 0; } -static int amdgpu_vram_mgr_free_backup_pages(struct amdgpu_vram_mgr *mgr, - uint32_t num_pages) -{ - struct amdgpu_device *adev = to_amdgpu_device(mgr); - struct amdgpu_vram_reservation *rsv; - uint32_t i; - uint64_t vis_usage = 0, total_usage = 0; - - if (num_pages > mgr->num_backup_pages) { - dev_warn(adev->dev, "No enough backup pages\n"); - return -EINVAL; - } - - for (i = 0; i < num_pages; i++) { - rsv = list_first_entry(&mgr->backup_pages, - struct amdgpu_vram_reservation, node); - vis_usage += amdgpu_vram_mgr_vis_size(adev, &rsv->mm_node); - total_usage += (rsv->mm_node.size << PAGE_SHIFT); - drm_mm_remove_node(&rsv->mm_node); - list_del(&rsv->node); - kfree(rsv); - mgr->num_backup_pages--; - } - - atomic64_sub(total_usage, &mgr->usage); - atomic64_sub(vis_usage, &mgr->vis_usage); - - return 0; -} - -int amdgpu_vram_mgr_reserve_backup_pages(struct ttm_resource_manager *man, - uint32_t num_pages) -{ - struct amdgpu_vram_mgr *mgr = to_vram_mgr(man); - struct amdgpu_device *adev = to_amdgpu_device(mgr); - struct amdgpu_vram_reservation *rsv; - struct drm_mm *mm = &mgr->mm; - uint32_t i; - int ret = 0; - uint64_t vis_usage, total_usage; - - for (i = 0; i < num_pages; i++) { - rsv = kzalloc(sizeof(*rsv), GFP_KERNEL); - if (!rsv) { - ret = -ENOMEM; - goto pro_end; - } - - INIT_LIST_HEAD(&rsv->node); - - ret = drm_mm_insert_node(mm, &rsv->mm_node, 1); - if (ret) { - dev_err(adev->dev, "failed to reserve backup page %d, ret 0x%x\n", i, ret); - kfree(rsv); - goto pro_end; - } - - vis_usage = amdgpu_vram_mgr_vis_size(adev, &rsv->mm_node); - total_usage = (rsv->mm_node.size << PAGE_SHIFT); - - spin_lock(&mgr->lock); - atomic64_add(vis_usage, &mgr->vis_usage); - atomic64_add(total_usage, &mgr->usage); - list_add_tail(&rsv->node, &mgr->backup_pages); - mgr->num_backup_pages++; - spin_unlock(&mgr->lock); - } - -pro_end: - if (ret) { - spin_lock(&mgr->lock); - amdgpu_vram_mgr_free_backup_pages(mgr, mgr->num_backup_pages); - spin_unlock(&mgr->lock); - } - - return ret; -} - /** * amdgpu_vram_mgr_query_page_status - query the reservation status * -- cgit v1.2.3 From 36000c7a51080840902d79e1558851076ecb7a96 Mon Sep 17 00:00:00 2001 From: Tian Tao Date: Wed, 24 Mar 2021 17:17:40 +0800 Subject: drm/amdgpu: Convert sysfs sprintf/snprintf family to sysfs_emit Fix the following coccicheck warning: drivers/gpu//drm/amd/amdgpu/amdgpu_ras.c:434:9-17: WARNING: use scnprintf or sprintf drivers/gpu//drm/amd/amdgpu/amdgpu_xgmi.c:220:8-16: WARNING: use scnprintf or sprintf drivers/gpu//drm/amd/amdgpu/amdgpu_xgmi.c:249:8-16: WARNING: use scnprintf or sprintf drivers/gpu//drm/amd/amdgpu/df_v3_6.c:208:8-16: WARNING: use scnprintf or sprintf drivers/gpu//drm/amd/amdgpu/amdgpu_psp.c:2973:8-16: WARNING: use scnprintf or sprintf drivers/gpu//drm/amd/amdgpu/amdgpu_vram_mgr.c:75:8-16: WARNING: use scnprintf or sprintf drivers/gpu//drm/amd/amdgpu/amdgpu_vram_mgr.c:112:8-16: WARNING: use scnprintf or sprintf drivers/gpu//drm/amd/amdgpu/amdgpu_vram_mgr.c:58:8-16: WARNING: use scnprintf or sprintf drivers/gpu//drm/amd/amdgpu/amdgpu_vram_mgr.c:93:8-16: WARNING: use scnprintf or sprintf drivers/gpu//drm/amd/amdgpu/amdgpu_vram_mgr.c:125:9-17: WARNING: use scnprintf or sprintf drivers/gpu//drm/amd/amdgpu/amdgpu_gtt_mgr.c:52:8-16: WARNING: use scnprintf or sprintf drivers/gpu//drm/amd/amdgpu/amdgpu_gtt_mgr.c:71:8-16: WARNING: use scnprintf or sprintf drivers/gpu//drm/amd/amdgpu/amdgpu_device.c:140:8-16: WARNING: use scnprintf or sprintf drivers/gpu//drm/amd/amdgpu/amdgpu_device.c:164:8-16: WARNING: use scnprintf or sprintf drivers/gpu//drm/amd/amdgpu/amdgpu_device.c:186:8-16: WARNING: use scnprintf or sprintf drivers/gpu//drm/amd/amdgpu/amdgpu_device.c:208:8-16: WARNING: use scnprintf or sprintf drivers/gpu//drm/amd/amdgpu/amdgpu_atombios.c:1916:8-16: WARNING: use scnprintf or sprintf Signed-off-by: Tian Tao Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 32 +++++++++++++--------------- 1 file changed, 15 insertions(+), 17 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index b2fc475ce6f7..592a2dd16493 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -52,7 +52,7 @@ static ssize_t amdgpu_mem_info_vram_total_show(struct device *dev, struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = drm_to_adev(ddev); - return snprintf(buf, PAGE_SIZE, "%llu\n", adev->gmc.real_vram_size); + return sysfs_emit(buf, "%llu\n", adev->gmc.real_vram_size); } /** @@ -69,7 +69,7 @@ static ssize_t amdgpu_mem_info_vis_vram_total_show(struct device *dev, struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = drm_to_adev(ddev); - return snprintf(buf, PAGE_SIZE, "%llu\n", adev->gmc.visible_vram_size); + return sysfs_emit(buf, "%llu\n", adev->gmc.visible_vram_size); } /** @@ -87,8 +87,7 @@ static ssize_t amdgpu_mem_info_vram_used_show(struct device *dev, struct amdgpu_device *adev = drm_to_adev(ddev); struct ttm_resource_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); - return snprintf(buf, PAGE_SIZE, "%llu\n", - amdgpu_vram_mgr_usage(man)); + return sysfs_emit(buf, "%llu\n", amdgpu_vram_mgr_usage(man)); } /** @@ -106,8 +105,7 @@ static ssize_t amdgpu_mem_info_vis_vram_used_show(struct device *dev, struct amdgpu_device *adev = drm_to_adev(ddev); struct ttm_resource_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); - return snprintf(buf, PAGE_SIZE, "%llu\n", - amdgpu_vram_mgr_vis_usage(man)); + return sysfs_emit(buf, "%llu\n", amdgpu_vram_mgr_vis_usage(man)); } static ssize_t amdgpu_mem_info_vram_vendor(struct device *dev, @@ -119,27 +117,27 @@ static ssize_t amdgpu_mem_info_vram_vendor(struct device *dev, switch (adev->gmc.vram_vendor) { case SAMSUNG: - return snprintf(buf, PAGE_SIZE, "samsung\n"); + return sysfs_emit(buf, "samsung\n"); case INFINEON: - return snprintf(buf, PAGE_SIZE, "infineon\n"); + return sysfs_emit(buf, "infineon\n"); case ELPIDA: - return snprintf(buf, PAGE_SIZE, "elpida\n"); + return sysfs_emit(buf, "elpida\n"); case ETRON: - return snprintf(buf, PAGE_SIZE, "etron\n"); + return sysfs_emit(buf, "etron\n"); case NANYA: - return snprintf(buf, PAGE_SIZE, "nanya\n"); + return sysfs_emit(buf, "nanya\n"); case HYNIX: - return snprintf(buf, PAGE_SIZE, "hynix\n"); + return sysfs_emit(buf, "hynix\n"); case MOSEL: - return snprintf(buf, PAGE_SIZE, "mosel\n"); + return sysfs_emit(buf, "mosel\n"); case WINBOND: - return snprintf(buf, PAGE_SIZE, "winbond\n"); + return sysfs_emit(buf, "winbond\n"); case ESMT: - return snprintf(buf, PAGE_SIZE, "esmt\n"); + return sysfs_emit(buf, "esmt\n"); case MICRON: - return snprintf(buf, PAGE_SIZE, "micron\n"); + return sysfs_emit(buf, "micron\n"); default: - return snprintf(buf, PAGE_SIZE, "unknown\n"); + return sysfs_emit(buf, "unknown\n"); } } -- cgit v1.2.3