[PATCH 1/2] drm/i915/buddy: add some pretty printing

Thomas Hellström thomas.hellstrom at linux.intel.com
Thu Aug 19 07:15:04 UTC 2021


On Wed, 2021-08-18 at 15:58 +0100, Matthew Auld wrote:
> Implement the debug hook for the buddy resource manager. For this we
> want to print out the status of the memory manager, including how much
> memory is still allocatable, what page sizes we have etc. This will be
> triggered when TTM is unable to fulfil an allocation request for device
> local-memory.
> 
> Signed-off-by: Matthew Auld <matthew.auld at intel.com>
> Cc: Thomas Hellström <thomas.hellstrom at linux.intel.com>
> ---
>  drivers/gpu/drm/i915/i915_buddy.c             | 45 +++++++++++++++++++
>  drivers/gpu/drm/i915/i915_buddy.h             |  8 ++++
>  drivers/gpu/drm/i915/i915_ttm_buddy_manager.c | 20 ++++++++-
>  3 files changed, 72 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_buddy.c
> b/drivers/gpu/drm/i915/i915_buddy.c
> index 7b274c51cac0..240e881d9eb0 100644
> --- a/drivers/gpu/drm/i915/i915_buddy.c
> +++ b/drivers/gpu/drm/i915/i915_buddy.c
> @@ -4,6 +4,7 @@
>   */
>  
>  #include <linux/kmemleak.h>
> +#include <linux/sizes.h>
>  
>  #include "i915_buddy.h"
>  
> @@ -82,6 +83,7 @@ int i915_buddy_init(struct i915_buddy_mm *mm, u64
> size, u64 chunk_size)
>         size = round_down(size, chunk_size);
>  
>         mm->size = size;
> +       mm->avail = size;
>         mm->chunk_size = chunk_size;
>         mm->max_order = ilog2(size) - ilog2(chunk_size);
>  
> @@ -155,6 +157,8 @@ void i915_buddy_fini(struct i915_buddy_mm *mm)
>                 i915_block_free(mm, mm->roots[i]);
>         }
>  
> +       GEM_WARN_ON(mm->avail != mm->size);
> +
>         kfree(mm->roots);
>         kfree(mm->free_list);
>  }
> @@ -230,6 +234,7 @@ void i915_buddy_free(struct i915_buddy_mm *mm,
>                      struct i915_buddy_block *block)
>  {
>         GEM_BUG_ON(!i915_buddy_block_is_allocated(block));
> +       mm->avail += i915_buddy_block_size(mm, block);
>         __i915_buddy_free(mm, block);
>  }
>  
> @@ -283,6 +288,7 @@ i915_buddy_alloc(struct i915_buddy_mm *mm, unsigned
> int order)
>         }
>  
>         mark_allocated(block);
> +       mm->avail -= i915_buddy_block_size(mm, block);
>         kmemleak_update_trace(block);
>         return block;
>  
> @@ -368,6 +374,7 @@ int i915_buddy_alloc_range(struct i915_buddy_mm
> *mm,
>                         }
>  
>                         mark_allocated(block);
> +                       mm->avail -= i915_buddy_block_size(mm, block);
>                         list_add_tail(&block->link, &allocated);
>                         continue;
>                 }
> @@ -402,6 +409,44 @@ int i915_buddy_alloc_range(struct i915_buddy_mm
> *mm,
>         return err;
>  }
>  
> +void i915_buddy_block_print(struct i915_buddy_mm *mm,
> +                           struct i915_buddy_block *block,
> +                           struct drm_printer *p)
> +{
> +       u64 start = i915_buddy_block_offset(block);
> +       u64 size = i915_buddy_block_size(mm, block);
> +
> +       drm_printf(p, "%#018llx-%#018llx: %llu\n", start, start + size,
> size);
> +}
> +
> +void i915_buddy_print(struct i915_buddy_mm *mm, struct drm_printer *p)
> +{
> +       int order;
> +
> +       drm_printf(p, "chunk_size: %lluKB, total: %lluMB, free:
> %lluMB\n",
> +                  mm->chunk_size >> 10, mm->size >> 20, mm->avail >>
> 20);
> +
> +       for (order = mm->max_order; order >= 0; order--) {
> +               struct i915_buddy_block *block;
> +               u64 count = 0, free;
> +
> +               list_for_each_entry(block, &mm->free_list[order], link)
> {
> +                       GEM_BUG_ON(!i915_buddy_block_is_free(block));
> +                       count++;
> +               }
> +
> +               drm_printf(p, "order-%d ", order);
> +
> +               free = count * (mm->chunk_size << order);
> +               if (free < SZ_1M)
> +                       drm_printf(p, "free: %lluKB", free >> 10);
> +               else
> +                       drm_printf(p, "free: %lluMB", free >> 20);

Use KiB and MiB instead of KB and MB? Also below.


> +
> +               drm_printf(p, ", pages: %llu\n", count);
> +       }
> +}
> +
>  #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
>  #include "selftests/i915_buddy.c"
>  #endif
> diff --git a/drivers/gpu/drm/i915/i915_buddy.h
> b/drivers/gpu/drm/i915/i915_buddy.h
> index 3940d632f208..7077742112ac 100644
> --- a/drivers/gpu/drm/i915/i915_buddy.h
> +++ b/drivers/gpu/drm/i915/i915_buddy.h
> @@ -10,6 +10,8 @@
>  #include <linux/list.h>
>  #include <linux/slab.h>
>  
> +#include <drm/drm_print.h>
> +
>  struct i915_buddy_block {
>  #define I915_BUDDY_HEADER_OFFSET GENMASK_ULL(63, 12)
>  #define I915_BUDDY_HEADER_STATE  GENMASK_ULL(11, 10)
> @@ -69,6 +71,7 @@ struct i915_buddy_mm {
>         /* Must be at least PAGE_SIZE */
>         u64 chunk_size;
>         u64 size;
> +       u64 avail;
>  };
>  
>  static inline u64
> @@ -129,6 +132,11 @@ void i915_buddy_free(struct i915_buddy_mm *mm,
> struct i915_buddy_block *block);
>  
>  void i915_buddy_free_list(struct i915_buddy_mm *mm, struct list_head
> *objects);
>  
> +void i915_buddy_print(struct i915_buddy_mm *mm, struct drm_printer
> *p);
> +void i915_buddy_block_print(struct i915_buddy_mm *mm,
> +                           struct i915_buddy_block *block,
> +                           struct drm_printer *p);
> +
>  void i915_buddy_module_exit(void);
>  int i915_buddy_module_init(void);
>  
> diff --git a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
> b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
> index 6877362f6b85..95ab786a1fe4 100644
> --- a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
> +++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
> @@ -126,12 +126,30 @@ static void i915_ttm_buddy_man_free(struct
> ttm_resource_manager *man,
>         kfree(bman_res);
>  }
>  
> +static void i915_ttm_buddy_man_debug(struct ttm_resource_manager *man,
> +                                    struct drm_printer *printer)
> +{
> +       struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
> +       struct i915_buddy_block *block;
> +
> +       mutex_lock(&bman->lock);
> +       drm_printf(printer, "default_page_size: %lluKB\n",
> +                  bman->default_page_size >> 10);
> +
> +       i915_buddy_print(&bman->mm, printer);
> +
> +       drm_printf(printer, "reserved:\n");
> +       list_for_each_entry(block, &bman->reserved, link)
> +               i915_buddy_block_print(&bman->mm, block, printer);
> +       mutex_unlock(&bman->lock);
> +}
> +
>  static const struct ttm_resource_manager_func
> i915_ttm_buddy_manager_func = {
>         .alloc = i915_ttm_buddy_man_alloc,
>         .free = i915_ttm_buddy_man_free,
> +       .debug = i915_ttm_buddy_man_debug,
>  };
>  
> -
>  /**
>   * i915_ttm_buddy_man_init - Setup buddy allocator based ttm manager
>   * @bdev: The ttm device

Otherwise LGTM,
Reviewed-by: Thomas Hellström <thomas.hellstrom at linux.intel.com>





More information about the dri-devel mailing list