Skip to content

Commit 95a1616

Browse files
arunpravin24ChristianKoenigAMD
authored andcommitted
drm/amdgpu: Reset the clear flag in buddy during resume
- 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. v2: - Add lock before accessing drm_buddy_clear_reset_blocks()(Matthew Auld) - Force merge the two dirty blocks.(Matthew Auld) - Add a new unit test case for this issue.(Matthew Auld) - Having this function being able to flip the state either way would be good. (Matthew Brost) v3(Matthew Auld): - Do merge step first to avoid the use of extra reset flag. Signed-off-by: Arunpravin Paneer Selvam <[email protected]> Suggested-by: Christian König <[email protected]> Acked-by: Christian König <[email protected]> Reviewed-by: Matthew Auld <[email protected]> Cc: [email protected] Fixes: a68c7ea ("drm/amdgpu: Enable clear page functionality") Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3812 Signed-off-by: Christian König <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent cb345f9 commit 95a1616

File tree

5 files changed

+65
-0
lines changed

5 files changed

+65
-0
lines changed

drivers/gpu/drm/amd/amdgpu/amdgpu_device.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5193,6 +5193,8 @@ int amdgpu_device_resume(struct drm_device *dev, bool notify_clients)
51935193
dev->dev->power.disable_depth--;
51945194
#endif
51955195
}
5196+
5197+
amdgpu_vram_mgr_clear_reset_blocks(adev);
51965198
adev->in_suspend = false;
51975199

51985200
if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DEV_D0))

drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ int amdgpu_vram_mgr_reserve_range(struct amdgpu_vram_mgr *mgr,
154154
uint64_t start, uint64_t size);
155155
int amdgpu_vram_mgr_query_page_status(struct amdgpu_vram_mgr *mgr,
156156
uint64_t start);
157+
void amdgpu_vram_mgr_clear_reset_blocks(struct amdgpu_device *adev);
157158

158159
bool amdgpu_res_cpu_visible(struct amdgpu_device *adev,
159160
struct ttm_resource *res);

drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,23 @@ uint64_t amdgpu_vram_mgr_vis_usage(struct amdgpu_vram_mgr *mgr)
782782
return atomic64_read(&mgr->vis_usage);
783783
}
784784

785+
/**
786+
* amdgpu_vram_mgr_clear_reset_blocks - reset clear blocks
787+
*
788+
* @adev: amdgpu device pointer
789+
*
790+
* Reset the cleared drm buddy blocks.
791+
*/
792+
void amdgpu_vram_mgr_clear_reset_blocks(struct amdgpu_device *adev)
793+
{
794+
struct amdgpu_vram_mgr *mgr = &adev->mman.vram_mgr;
795+
struct drm_buddy *mm = &mgr->mm;
796+
797+
mutex_lock(&mgr->lock);
798+
drm_buddy_reset_clear(mm, false);
799+
mutex_unlock(&mgr->lock);
800+
}
801+
785802
/**
786803
* amdgpu_vram_mgr_intersects - test each drm buddy block for intersection
787804
*

drivers/gpu/drm/drm_buddy.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,49 @@ drm_get_buddy(struct drm_buddy_block *block)
404404
}
405405
EXPORT_SYMBOL(drm_get_buddy);
406406

407+
/**
408+
* drm_buddy_reset_clear - reset blocks clear state
409+
*
410+
* @mm: DRM buddy manager
411+
* @is_clear: blocks clear state
412+
*
413+
* Reset the clear state based on @is_clear value for each block
414+
* in the freelist.
415+
*/
416+
void drm_buddy_reset_clear(struct drm_buddy *mm, bool is_clear)
417+
{
418+
u64 root_size, size, start;
419+
unsigned int order;
420+
int i;
421+
422+
size = mm->size;
423+
for (i = 0; i < mm->n_roots; ++i) {
424+
order = ilog2(size) - ilog2(mm->chunk_size);
425+
start = drm_buddy_block_offset(mm->roots[i]);
426+
__force_merge(mm, start, start + size, order);
427+
428+
root_size = mm->chunk_size << order;
429+
size -= root_size;
430+
}
431+
432+
for (i = 0; i <= mm->max_order; ++i) {
433+
struct drm_buddy_block *block;
434+
435+
list_for_each_entry_reverse(block, &mm->free_list[i], link) {
436+
if (is_clear != drm_buddy_block_is_clear(block)) {
437+
if (is_clear) {
438+
mark_cleared(block);
439+
mm->clear_avail += drm_buddy_block_size(mm, block);
440+
} else {
441+
clear_reset(block);
442+
mm->clear_avail -= drm_buddy_block_size(mm, block);
443+
}
444+
}
445+
}
446+
}
447+
}
448+
EXPORT_SYMBOL(drm_buddy_reset_clear);
449+
407450
/**
408451
* drm_buddy_free_block - free a block
409452
*

include/drm/drm_buddy.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ int drm_buddy_block_trim(struct drm_buddy *mm,
160160
u64 new_size,
161161
struct list_head *blocks);
162162

163+
void drm_buddy_reset_clear(struct drm_buddy *mm, bool is_clear);
164+
163165
void drm_buddy_free_block(struct drm_buddy *mm, struct drm_buddy_block *block);
164166

165167
void drm_buddy_free_list(struct drm_buddy *mm,

0 commit comments

Comments
 (0)