- Added a handler in DRM buddy manager to reset the cleared
  flag for the blocks in the freelist.

- This is necessary because, upon resuming, the VRAM becomes
  cluttered with BIOS data, yet the VRAM backend manager
  believes that everything has been cleared.

Signed-off-by: Arunpravin Paneer Selvam <arunpravin.paneersel...@amd.com>
Suggested-by: Christian König <christian.koe...@amd.com>
Cc: sta...@vger.kernel.org
Fixes: a68c7eaa7a8f ("drm/amdgpu: Enable clear page functionality")
Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3812
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c   |  2 ++
 drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h |  5 ++++
 drivers/gpu/drm/drm_buddy.c                  | 24 ++++++++++++++++++++
 include/drm/drm_buddy.h                      |  2 ++
 4 files changed, 33 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index a59f194e3360..eb67d6c97392 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -5193,6 +5193,8 @@ int amdgpu_device_resume(struct drm_device *dev, bool 
notify_clients)
                dev->dev->power.disable_depth--;
 #endif
        }
+
+       amdgpu_vram_mgr_clear_reset_blocks(&adev->mman.vram_mgr.mm);
        adev->in_suspend = false;
 
        if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DEV_D0))
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h
index 1019c5806ec7..e9e2928fa4d1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h
@@ -58,6 +58,11 @@ static inline bool amdgpu_vram_mgr_is_cleared(struct 
drm_buddy_block *block)
        return drm_buddy_block_is_clear(block);
 }
 
+static inline void amdgpu_vram_mgr_clear_reset_blocks(struct drm_buddy *mm)
+{
+       drm_buddy_clear_reset_blocks(mm);
+}
+
 static inline struct amdgpu_vram_mgr_resource *
 to_amdgpu_vram_mgr_resource(struct ttm_resource *res)
 {
diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c
index a1e652b7631d..b5e44867adf2 100644
--- a/drivers/gpu/drm/drm_buddy.c
+++ b/drivers/gpu/drm/drm_buddy.c
@@ -405,6 +405,30 @@ drm_get_buddy(struct drm_buddy_block *block)
 }
 EXPORT_SYMBOL(drm_get_buddy);
 
+/**
+ * drm_buddy_clear_reset_blocks - reset cleared blocks
+ *
+ * @mm: DRM buddy manager
+ *
+ * Reset all the cleared blocks in the freelist.
+ */
+void drm_buddy_clear_reset_blocks(struct drm_buddy *mm)
+{
+       unsigned int i;
+
+       for (i = 0; i <= mm->max_order; ++i) {
+               struct drm_buddy_block *block;
+
+               list_for_each_entry_reverse(block, &mm->free_list[i], link) {
+                       if (drm_buddy_block_is_clear(block)) {
+                               clear_reset(block);
+                               mm->clear_avail -= drm_buddy_block_size(mm, 
block);
+                       }
+               }
+       }
+}
+EXPORT_SYMBOL(drm_buddy_clear_reset_blocks);
+
 /**
  * drm_buddy_free_block - free a block
  *
diff --git a/include/drm/drm_buddy.h b/include/drm/drm_buddy.h
index 9689a7c5dd36..da569dea16b7 100644
--- a/include/drm/drm_buddy.h
+++ b/include/drm/drm_buddy.h
@@ -160,6 +160,8 @@ int drm_buddy_block_trim(struct drm_buddy *mm,
                         u64 new_size,
                         struct list_head *blocks);
 
+void drm_buddy_clear_reset_blocks(struct drm_buddy *mm);
+
 void drm_buddy_free_block(struct drm_buddy *mm, struct drm_buddy_block *block);
 
 void drm_buddy_free_list(struct drm_buddy *mm,
-- 
2.43.0

Reply via email to