Commit 26ffcbbe authored by Matthew Auld's avatar Matthew Auld

drm/i915/buddy: track available visible size

Track the total amount of available visible memory, and also track
per-resource the amount of used visible memory. For now this is useful
for our debug output, and deciding if it is even worth calling into the
buddy allocator. In the future tracking the per-resource visible usage
will be useful for when deciding if we should attempt to evict certain
buffers.

v2:
 - s/place->lpfn/lpfn/, that way we can avoid scanning the list if the
   entire range is already mappable.
 - Move the end declaration inside the if block(Thomas).
 - Make sure to also account for reserved memory.
Signed-off-by: default avatarMatthew Auld <matthew.auld@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: default avatarThomas Hellström <thomas.hellstrom@linux.intel.com>
Acked-by: default avatarNirmoy Das <nirmoy.das@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220225145502.331818-4-matthew.auld@intel.com
parent 30b9d1b3
...@@ -19,6 +19,9 @@ struct i915_ttm_buddy_manager { ...@@ -19,6 +19,9 @@ struct i915_ttm_buddy_manager {
struct drm_buddy mm; struct drm_buddy mm;
struct list_head reserved; struct list_head reserved;
struct mutex lock; struct mutex lock;
unsigned long visible_size;
unsigned long visible_avail;
unsigned long visible_reserved;
u64 default_page_size; u64 default_page_size;
}; };
...@@ -87,6 +90,12 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man, ...@@ -87,6 +90,12 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man,
n_pages = size >> ilog2(mm->chunk_size); n_pages = size >> ilog2(mm->chunk_size);
mutex_lock(&bman->lock); mutex_lock(&bman->lock);
if (lpfn <= bman->visible_size && n_pages > bman->visible_avail) {
mutex_unlock(&bman->lock);
err = -ENOSPC;
goto err_free_res;
}
err = drm_buddy_alloc_blocks(mm, (u64)place->fpfn << PAGE_SHIFT, err = drm_buddy_alloc_blocks(mm, (u64)place->fpfn << PAGE_SHIFT,
(u64)lpfn << PAGE_SHIFT, (u64)lpfn << PAGE_SHIFT,
(u64)n_pages << PAGE_SHIFT, (u64)n_pages << PAGE_SHIFT,
...@@ -107,6 +116,31 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man, ...@@ -107,6 +116,31 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man,
mutex_unlock(&bman->lock); mutex_unlock(&bman->lock);
} }
if (lpfn <= bman->visible_size) {
bman_res->used_visible_size = bman_res->base.num_pages;
} else {
struct drm_buddy_block *block;
list_for_each_entry(block, &bman_res->blocks, link) {
unsigned long start =
drm_buddy_block_offset(block) >> PAGE_SHIFT;
if (start < bman->visible_size) {
unsigned long end = start +
(drm_buddy_block_size(mm, block) >> PAGE_SHIFT);
bman_res->used_visible_size +=
min(end, bman->visible_size) - start;
}
}
}
if (bman_res->used_visible_size) {
mutex_lock(&bman->lock);
bman->visible_avail -= bman_res->used_visible_size;
mutex_unlock(&bman->lock);
}
*res = &bman_res->base; *res = &bman_res->base;
return 0; return 0;
...@@ -128,6 +162,7 @@ static void i915_ttm_buddy_man_free(struct ttm_resource_manager *man, ...@@ -128,6 +162,7 @@ static void i915_ttm_buddy_man_free(struct ttm_resource_manager *man,
mutex_lock(&bman->lock); mutex_lock(&bman->lock);
drm_buddy_free_list(&bman->mm, &bman_res->blocks); drm_buddy_free_list(&bman->mm, &bman_res->blocks);
bman->visible_avail += bman_res->used_visible_size;
mutex_unlock(&bman->lock); mutex_unlock(&bman->lock);
ttm_resource_fini(man, res); ttm_resource_fini(man, res);
...@@ -143,6 +178,12 @@ static void i915_ttm_buddy_man_debug(struct ttm_resource_manager *man, ...@@ -143,6 +178,12 @@ static void i915_ttm_buddy_man_debug(struct ttm_resource_manager *man,
mutex_lock(&bman->lock); mutex_lock(&bman->lock);
drm_printf(printer, "default_page_size: %lluKiB\n", drm_printf(printer, "default_page_size: %lluKiB\n",
bman->default_page_size >> 10); bman->default_page_size >> 10);
drm_printf(printer, "visible_avail: %lluMiB\n",
(u64)bman->visible_avail << PAGE_SHIFT >> 20);
drm_printf(printer, "visible_size: %lluMiB\n",
(u64)bman->visible_size << PAGE_SHIFT >> 20);
drm_printf(printer, "visible_reserved: %lluMiB\n",
(u64)bman->visible_reserved << PAGE_SHIFT >> 20);
drm_buddy_print(&bman->mm, printer); drm_buddy_print(&bman->mm, printer);
...@@ -164,6 +205,7 @@ static const struct ttm_resource_manager_func i915_ttm_buddy_manager_func = { ...@@ -164,6 +205,7 @@ static const struct ttm_resource_manager_func i915_ttm_buddy_manager_func = {
* @type: Memory type we want to manage * @type: Memory type we want to manage
* @use_tt: Set use_tt for the manager * @use_tt: Set use_tt for the manager
* @size: The size in bytes to manage * @size: The size in bytes to manage
* @visible_size: The CPU visible size in bytes to manage
* @default_page_size: The default minimum page size in bytes for allocations, * @default_page_size: The default minimum page size in bytes for allocations,
* this must be at least as large as @chunk_size, and can be overridden by * this must be at least as large as @chunk_size, and can be overridden by
* setting the BO page_alignment, to be larger or smaller as needed. * setting the BO page_alignment, to be larger or smaller as needed.
...@@ -187,7 +229,7 @@ static const struct ttm_resource_manager_func i915_ttm_buddy_manager_func = { ...@@ -187,7 +229,7 @@ static const struct ttm_resource_manager_func i915_ttm_buddy_manager_func = {
*/ */
int i915_ttm_buddy_man_init(struct ttm_device *bdev, int i915_ttm_buddy_man_init(struct ttm_device *bdev,
unsigned int type, bool use_tt, unsigned int type, bool use_tt,
u64 size, u64 default_page_size, u64 size, u64 visible_size, u64 default_page_size,
u64 chunk_size) u64 chunk_size)
{ {
struct ttm_resource_manager *man; struct ttm_resource_manager *man;
...@@ -206,6 +248,8 @@ int i915_ttm_buddy_man_init(struct ttm_device *bdev, ...@@ -206,6 +248,8 @@ int i915_ttm_buddy_man_init(struct ttm_device *bdev,
INIT_LIST_HEAD(&bman->reserved); INIT_LIST_HEAD(&bman->reserved);
GEM_BUG_ON(default_page_size < chunk_size); GEM_BUG_ON(default_page_size < chunk_size);
bman->default_page_size = default_page_size; bman->default_page_size = default_page_size;
bman->visible_size = visible_size >> PAGE_SHIFT;
bman->visible_avail = bman->visible_size;
man = &bman->manager; man = &bman->manager;
man->use_tt = use_tt; man->use_tt = use_tt;
...@@ -250,6 +294,8 @@ int i915_ttm_buddy_man_fini(struct ttm_device *bdev, unsigned int type) ...@@ -250,6 +294,8 @@ int i915_ttm_buddy_man_fini(struct ttm_device *bdev, unsigned int type)
mutex_lock(&bman->lock); mutex_lock(&bman->lock);
drm_buddy_free_list(mm, &bman->reserved); drm_buddy_free_list(mm, &bman->reserved);
drm_buddy_fini(mm); drm_buddy_fini(mm);
bman->visible_avail += bman->visible_reserved;
WARN_ON_ONCE(bman->visible_avail != bman->visible_size);
mutex_unlock(&bman->lock); mutex_unlock(&bman->lock);
ttm_resource_manager_cleanup(man); ttm_resource_manager_cleanup(man);
...@@ -273,6 +319,7 @@ int i915_ttm_buddy_man_reserve(struct ttm_resource_manager *man, ...@@ -273,6 +319,7 @@ int i915_ttm_buddy_man_reserve(struct ttm_resource_manager *man,
{ {
struct i915_ttm_buddy_manager *bman = to_buddy_manager(man); struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
struct drm_buddy *mm = &bman->mm; struct drm_buddy *mm = &bman->mm;
unsigned long fpfn = start >> PAGE_SHIFT;
unsigned long flags = 0; unsigned long flags = 0;
int ret; int ret;
...@@ -284,8 +331,27 @@ int i915_ttm_buddy_man_reserve(struct ttm_resource_manager *man, ...@@ -284,8 +331,27 @@ int i915_ttm_buddy_man_reserve(struct ttm_resource_manager *man,
size, mm->chunk_size, size, mm->chunk_size,
&bman->reserved, &bman->reserved,
flags); flags);
if (fpfn < bman->visible_size) {
unsigned long lpfn = fpfn + (size >> PAGE_SHIFT);
unsigned long visible = min(lpfn, bman->visible_size) - fpfn;
bman->visible_reserved += visible;
bman->visible_avail -= visible;
}
mutex_unlock(&bman->lock); mutex_unlock(&bman->lock);
return ret; return ret;
} }
/**
* i915_ttm_buddy_man_visible_size - Return the size of the CPU visible portion
* in pages.
* @man: The buddy allocator ttm manager
*/
u64 i915_ttm_buddy_man_visible_size(struct ttm_resource_manager *man)
{
struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
return bman->visible_size;
}
...@@ -21,6 +21,8 @@ struct drm_buddy; ...@@ -21,6 +21,8 @@ struct drm_buddy;
* @base: struct ttm_resource base class we extend * @base: struct ttm_resource base class we extend
* @blocks: the list of struct i915_buddy_block for this resource/allocation * @blocks: the list of struct i915_buddy_block for this resource/allocation
* @flags: DRM_BUDDY_*_ALLOCATION flags * @flags: DRM_BUDDY_*_ALLOCATION flags
* @used_visible_size: How much of this resource, if any, uses the CPU visible
* portion, in pages.
* @mm: the struct i915_buddy_mm for this resource * @mm: the struct i915_buddy_mm for this resource
* *
* Extends the struct ttm_resource to manage an address space allocation with * Extends the struct ttm_resource to manage an address space allocation with
...@@ -30,6 +32,7 @@ struct i915_ttm_buddy_resource { ...@@ -30,6 +32,7 @@ struct i915_ttm_buddy_resource {
struct ttm_resource base; struct ttm_resource base;
struct list_head blocks; struct list_head blocks;
unsigned long flags; unsigned long flags;
unsigned long used_visible_size;
struct drm_buddy *mm; struct drm_buddy *mm;
}; };
...@@ -48,11 +51,14 @@ to_ttm_buddy_resource(struct ttm_resource *res) ...@@ -48,11 +51,14 @@ to_ttm_buddy_resource(struct ttm_resource *res)
int i915_ttm_buddy_man_init(struct ttm_device *bdev, int i915_ttm_buddy_man_init(struct ttm_device *bdev,
unsigned type, bool use_tt, unsigned type, bool use_tt,
u64 size, u64 default_page_size, u64 chunk_size); u64 size, u64 visible_size,
u64 default_page_size, u64 chunk_size);
int i915_ttm_buddy_man_fini(struct ttm_device *bdev, int i915_ttm_buddy_man_fini(struct ttm_device *bdev,
unsigned int type); unsigned int type);
int i915_ttm_buddy_man_reserve(struct ttm_resource_manager *man, int i915_ttm_buddy_man_reserve(struct ttm_resource_manager *man,
u64 start, u64 size); u64 start, u64 size);
u64 i915_ttm_buddy_man_visible_size(struct ttm_resource_manager *man);
#endif #endif
...@@ -87,6 +87,7 @@ int intel_region_ttm_init(struct intel_memory_region *mem) ...@@ -87,6 +87,7 @@ int intel_region_ttm_init(struct intel_memory_region *mem)
ret = i915_ttm_buddy_man_init(bdev, mem_type, false, ret = i915_ttm_buddy_man_init(bdev, mem_type, false,
resource_size(&mem->region), resource_size(&mem->region),
mem->io_size,
mem->min_page_size, PAGE_SIZE); mem->min_page_size, PAGE_SIZE);
if (ret) if (ret)
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment