All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alex Deucher <alexdeucher@gmail.com>
To: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
Cc: Maling list - DRI developers <dri-devel@lists.freedesktop.org>,
	 Intel Graphics Development <intel-gfx@lists.freedesktop.org>,
	 amd-gfx list <amd-gfx@lists.freedesktop.org>,
	Christian Koenig <christian.koenig@amd.com>,
	 Matthew Auld <matthew.auld@intel.com>,
	Daniel Vetter <daniel@ffwll.ch>,
	 "Deucher, Alexander" <alexander.deucher@amd.com>
Subject: Re: [PATCH 2/2] Add drm buddy manager support to amdgpu driver
Date: Mon, 20 Sep 2021 15:30:46 -0400	[thread overview]
Message-ID: <CADnq5_NshcMm2ZztfNJn0BcNHxUfs-tBpTCpocpZA3xj0v+CSg@mail.gmail.com> (raw)
In-Reply-To: <20210920192110.221153-1-Arunpravin.PaneerSelvam@amd.com>

On Mon, Sep 20, 2021 at 3:21 PM Arunpravin
<Arunpravin.PaneerSelvam@amd.com> wrote:
>
> Replace drm_mm with drm buddy manager for
> VRAM memory management

Would be good to document why we are doing this and what advantages it
brings over the old drm_mm code.

Alex


>
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
> ---
>  .../gpu/drm/amd/amdgpu/amdgpu_res_cursor.h    |  78 +++++--
>  drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h       |   3 +-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c  | 216 ++++++++++--------
>  3 files changed, 189 insertions(+), 108 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h
> index acfa207cf970..ba24052e9062 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h
> @@ -30,12 +30,25 @@
>  #include <drm/ttm/ttm_resource.h>
>  #include <drm/ttm/ttm_range_manager.h>
>
> +struct amdgpu_vram_mgr_node {
> +       struct ttm_range_mgr_node tnode;
> +       struct list_head blocks;
> +};
> +
> +static inline struct amdgpu_vram_mgr_node *
> +to_amdgpu_vram_mgr_node(struct ttm_resource *res)
> +{
> +       return container_of(container_of(res, struct ttm_range_mgr_node, base),
> +                       struct amdgpu_vram_mgr_node, tnode);
> +}
> +
>  /* state back for walking over vram_mgr and gtt_mgr allocations */
>  struct amdgpu_res_cursor {
>         uint64_t                start;
>         uint64_t                size;
>         uint64_t                remaining;
> -       struct drm_mm_node      *node;
> +       void                    *node;
> +       uint32_t                mem_type;
>  };
>
>  /**
> @@ -52,8 +65,6 @@ static inline void amdgpu_res_first(struct ttm_resource *res,
>                                     uint64_t start, uint64_t size,
>                                     struct amdgpu_res_cursor *cur)
>  {
> -       struct drm_mm_node *node;
> -
>         if (!res || res->mem_type == TTM_PL_SYSTEM) {
>                 cur->start = start;
>                 cur->size = size;
> @@ -65,14 +76,39 @@ static inline void amdgpu_res_first(struct ttm_resource *res,
>
>         BUG_ON(start + size > res->num_pages << PAGE_SHIFT);
>
> -       node = to_ttm_range_mgr_node(res)->mm_nodes;
> -       while (start >= node->size << PAGE_SHIFT)
> -               start -= node++->size << PAGE_SHIFT;
> +       cur->mem_type = res->mem_type;
> +
> +       if (cur->mem_type == TTM_PL_VRAM) {
> +               struct drm_buddy_block *block;
> +               struct list_head *head, *next;
> +
> +               head = &to_amdgpu_vram_mgr_node(res)->blocks;
> +
> +               block = list_first_entry_or_null(head, struct drm_buddy_block, link);
> +               while (start >= block->size << PAGE_SHIFT) {
> +                       start -= block->size << PAGE_SHIFT;
> +
> +                       next = block->link.next;
> +                       if (next != head)
> +                               block = list_entry(next, struct drm_buddy_block, link);
> +               }
>
> -       cur->start = (node->start << PAGE_SHIFT) + start;
> -       cur->size = min((node->size << PAGE_SHIFT) - start, size);
> -       cur->remaining = size;
> -       cur->node = node;
> +               cur->start = (block->start << PAGE_SHIFT) + start;
> +               cur->size = min((block->size << PAGE_SHIFT) - start, size);
> +               cur->remaining = size;
> +               cur->node = block;
> +       } else if (cur->mem_type == TTM_PL_TT) {
> +               struct drm_mm_node *node;
> +
> +               node = to_ttm_range_mgr_node(res)->mm_nodes;
> +               while (start >= node->size << PAGE_SHIFT)
> +                       start -= node++->size << PAGE_SHIFT;
> +
> +               cur->start = (node->start << PAGE_SHIFT) + start;
> +               cur->size = min((node->size << PAGE_SHIFT) - start, size);
> +               cur->remaining = size;
> +               cur->node = node;
> +       }
>  }
>
>  /**
> @@ -85,8 +121,6 @@ static inline void amdgpu_res_first(struct ttm_resource *res,
>   */
>  static inline void amdgpu_res_next(struct amdgpu_res_cursor *cur, uint64_t size)
>  {
> -       struct drm_mm_node *node = cur->node;
> -
>         BUG_ON(size > cur->remaining);
>
>         cur->remaining -= size;
> @@ -99,9 +133,23 @@ static inline void amdgpu_res_next(struct amdgpu_res_cursor *cur, uint64_t size)
>                 return;
>         }
>
> -       cur->node = ++node;
> -       cur->start = node->start << PAGE_SHIFT;
> -       cur->size = min(node->size << PAGE_SHIFT, cur->remaining);
> +       if (cur->mem_type == TTM_PL_VRAM) {
> +               struct drm_buddy_block *block = cur->node;
> +               struct list_head *next;
> +
> +               next = block->link.next;
> +               block = list_entry(next, struct drm_buddy_block, link);
> +
> +               cur->node = block;
> +               cur->start = block->start << PAGE_SHIFT;
> +               cur->size = min(block->size << PAGE_SHIFT, cur->remaining);
> +       } else if (cur->mem_type == TTM_PL_TT) {
> +               struct drm_mm_node *node = cur->node;
> +
> +               cur->node = ++node;
> +               cur->start = node->start << PAGE_SHIFT;
> +               cur->size = min(node->size << PAGE_SHIFT, cur->remaining);
> +       }
>  }
>
>  #endif
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
> index e69f3e8e06e5..96c8e8aaa0ee 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
> @@ -26,6 +26,7 @@
>
>  #include <linux/dma-direction.h>
>  #include <drm/gpu_scheduler.h>
> +#include <drm/drm_buddy.h>
>  #include "amdgpu.h"
>
>  #define AMDGPU_PL_GDS          (TTM_PL_PRIV + 0)
> @@ -40,7 +41,7 @@
>
>  struct amdgpu_vram_mgr {
>         struct ttm_resource_manager manager;
> -       struct drm_mm mm;
> +       struct drm_buddy_mm mm;
>         spinlock_t lock;
>         struct list_head reservations_pending;
>         struct list_head reserved_pages;
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
> index 7b2b0980ec41..de0c5f4cabaf 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
> @@ -23,7 +23,9 @@
>   */
>
>  #include <linux/dma-mapping.h>
> +#include <linux/list_sort.h>
>  #include <drm/ttm/ttm_range_manager.h>
> +#include <drm/drm_buddy.h>
>
>  #include "amdgpu.h"
>  #include "amdgpu_vm.h"
> @@ -33,7 +35,7 @@
>
>  struct amdgpu_vram_reservation {
>         struct list_head node;
> -       struct drm_mm_node mm_node;
> +       struct drm_buddy_block mm_node;
>  };
>
>  static inline struct amdgpu_vram_mgr *
> @@ -196,10 +198,10 @@ const struct attribute_group amdgpu_vram_mgr_attr_group = {
>   * Calculate how many bytes of the MM node are inside visible VRAM
>   */
>  static u64 amdgpu_vram_mgr_vis_size(struct amdgpu_device *adev,
> -                                   struct drm_mm_node *node)
> +                                   struct drm_buddy_block *block)
>  {
> -       uint64_t start = node->start << PAGE_SHIFT;
> -       uint64_t end = (node->size + node->start) << PAGE_SHIFT;
> +       uint64_t start = block->start << PAGE_SHIFT;
> +       uint64_t end = (block->size + block->start) << PAGE_SHIFT;
>
>         if (start >= adev->gmc.visible_vram_size)
>                 return 0;
> @@ -220,8 +222,8 @@ u64 amdgpu_vram_mgr_bo_visible_size(struct amdgpu_bo *bo)
>  {
>         struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
>         struct ttm_resource *res = bo->tbo.resource;
> -       unsigned pages = res->num_pages;
> -       struct drm_mm_node *mm;
> +       struct amdgpu_vram_mgr_node *vnode = to_amdgpu_vram_mgr_node(res);
> +       struct drm_buddy_block *block;
>         u64 usage;
>
>         if (amdgpu_gmc_vram_full_visible(&adev->gmc))
> @@ -230,9 +232,8 @@ u64 amdgpu_vram_mgr_bo_visible_size(struct amdgpu_bo *bo)
>         if (res->start >= adev->gmc.visible_vram_size >> PAGE_SHIFT)
>                 return 0;
>
> -       mm = &container_of(res, struct ttm_range_mgr_node, base)->mm_nodes[0];
> -       for (usage = 0; pages; pages -= mm->size, mm++)
> -               usage += amdgpu_vram_mgr_vis_size(adev, mm);
> +       list_for_each_entry(block, &vnode->blocks, link)
> +               usage += amdgpu_vram_mgr_vis_size(adev, block);
>
>         return usage;
>  }
> @@ -242,12 +243,15 @@ static void amdgpu_vram_mgr_do_reserve(struct ttm_resource_manager *man)
>  {
>         struct amdgpu_vram_mgr *mgr = to_vram_mgr(man);
>         struct amdgpu_device *adev = to_amdgpu_device(mgr);
> -       struct drm_mm *mm = &mgr->mm;
> +       struct drm_buddy_mm *mm = &mgr->mm;
>         struct amdgpu_vram_reservation *rsv, *temp;
>         uint64_t vis_usage;
> +       int r = 0;
>
>         list_for_each_entry_safe(rsv, temp, &mgr->reservations_pending, node) {
> -               if (drm_mm_reserve_node(mm, &rsv->mm_node))
> +               r = drm_buddy_alloc_range(mm, &rsv->node, rsv->mm_node.start, rsv->mm_node.size);
> +
> +               if (unlikely(r))
>                         continue;
>
>                 dev_dbg(adev->dev, "Reservation 0x%llx - %lld, Succeeded\n",
> @@ -333,26 +337,16 @@ int amdgpu_vram_mgr_query_page_status(struct ttm_resource_manager *man,
>         return ret;
>  }
>
> -/**
> - * amdgpu_vram_mgr_virt_start - update virtual start address
> - *
> - * @mem: ttm_resource to update
> - * @node: just allocated node
> - *
> - * Calculate a virtual BO start address to easily check if everything is CPU
> - * accessible.
> - */
> -static void amdgpu_vram_mgr_virt_start(struct ttm_resource *mem,
> -                                      struct drm_mm_node *node)
> +static int sort_blocks(void *priv, const struct list_head *A,
> +                                       const struct list_head *B)
>  {
> -       unsigned long start;
> +       struct drm_buddy_block *a = list_entry(A, typeof(*a), link);
> +       struct drm_buddy_block *b = list_entry(B, typeof(*b), link);
>
> -       start = node->start + node->size;
> -       if (start > mem->num_pages)
> -               start -= mem->num_pages;
> +       if (a->start < b->start)
> +               return -1;
>         else
> -               start = 0;
> -       mem->start = max(mem->start, start);
> +               return 1;
>  }
>
>  /**
> @@ -370,15 +364,20 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
>                                const struct ttm_place *place,
>                                struct ttm_resource **res)
>  {
> -       unsigned long lpfn, num_nodes, pages_per_node, pages_left, pages;
> +       unsigned long lpfn, pages_per_node, pages_left, pages;
>         struct amdgpu_vram_mgr *mgr = to_vram_mgr(man);
>         struct amdgpu_device *adev = to_amdgpu_device(mgr);
>         uint64_t vis_usage = 0, mem_bytes, max_bytes;
> +       struct amdgpu_vram_mgr_node *vnode;
> +       struct drm_buddy_mm *mm = &mgr->mm;
>         struct ttm_range_mgr_node *node;
> -       struct drm_mm *mm = &mgr->mm;
> -       enum drm_mm_insert_mode mode;
> +       enum drm_buddy_alloc_mode mode;
> +       struct drm_buddy_block *block;
> +       unsigned int visible_pfn;
> +       bool bar_limit_enabled;
> +       unsigned long n_pages;
>         unsigned i;
> -       int r;
> +       int r = 0;
>
>         lpfn = place->lpfn;
>         if (!lpfn)
> @@ -395,10 +394,9 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
>                 goto error_sub;
>         }
>
> -       if (place->flags & TTM_PL_FLAG_CONTIGUOUS) {
> +       if (place->flags & TTM_PL_FLAG_CONTIGUOUS)
>                 pages_per_node = ~0ul;
> -               num_nodes = 1;
> -       } else {
> +       else {
>  #ifdef CONFIG_TRANSPARENT_HUGEPAGE
>                 pages_per_node = HPAGE_PMD_NR;
>  #else
> @@ -407,57 +405,97 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
>  #endif
>                 pages_per_node = max_t(uint32_t, pages_per_node,
>                                        tbo->page_alignment);
> -               num_nodes = DIV_ROUND_UP_ULL(PFN_UP(mem_bytes), pages_per_node);
>         }
>
> -       node = kvmalloc(struct_size(node, mm_nodes, num_nodes),
> -                       GFP_KERNEL | __GFP_ZERO);
> -       if (!node) {
> +       vnode = kzalloc(sizeof(*vnode), GFP_KERNEL);
> +
> +       if (!vnode) {
>                 r = -ENOMEM;
>                 goto error_sub;
>         }
>
> +       node = &vnode->tnode;
> +
>         ttm_resource_init(tbo, place, &node->base);
>
> -       mode = DRM_MM_INSERT_BEST;
> -       if (place->flags & TTM_PL_FLAG_TOPDOWN)
> -               mode = DRM_MM_INSERT_HIGH;
> +       bar_limit_enabled = !(amdgpu_gmc_vram_full_visible(&adev->gmc));
> +
> +       visible_pfn = adev->gmc.visible_vram_size >> PAGE_SHIFT;
> +
> +       mode = DRM_BUDDY_BOTTOM_UP;
> +       if (!place->fpfn && lpfn == man->size &&
> +                                       (place->flags & TTM_PL_FLAG_TOPDOWN))
> +               /* Allocate blocks from CPU non-mappable (TOP-DOWN) region */
> +               mode = DRM_BUDDY_TOP_DOWN;
> +       else if (place->fpfn || (lpfn != man->size && lpfn != visible_pfn))
> +               /* Allocate blocks in desired range */
> +               mode = DRM_BUDDY_ALLOC_RANGE;
>
>         pages_left = node->base.num_pages;
>
>         /* Limit maximum size to 2GB due to SG table limitations */
>         pages = min(pages_left, 2UL << (30 - PAGE_SHIFT));
>
> +       INIT_LIST_HEAD(&vnode->blocks);
> +
>         i = 0;
> -       spin_lock(&mgr->lock);
> -       while (pages_left) {
> -               uint32_t alignment = tbo->page_alignment;
> -
> -               if (pages >= pages_per_node)
> -                       alignment = pages_per_node;
> -
> -               r = drm_mm_insert_node_in_range(mm, &node->mm_nodes[i], pages,
> -                                               alignment, 0, place->fpfn,
> -                                               lpfn, mode);
> -               if (unlikely(r)) {
> -                       if (pages > pages_per_node) {
> -                               if (is_power_of_2(pages))
> -                                       pages = pages / 2;
> -                               else
> -                                       pages = rounddown_pow_of_two(pages);
> -                               continue;
> -                       }
> -                       goto error_free;
> -               }
> +       if (mode == DRM_BUDDY_ALLOC_RANGE) {
> +               r = drm_buddy_alloc_range(mm, &vnode->blocks,
> +                               (uint64_t)place->fpfn << PAGE_SHIFT, pages << PAGE_SHIFT);
> +
> +               if (unlikely(r))
> +                       goto error_free_res;
> +       } else {
> +               while (pages_left) {
> +                       if (pages >= pages_per_node)
> +                               pages = pages_per_node;
> +
> +                       n_pages = pages;
> +
> +                       if (place->flags & TTM_PL_FLAG_CONTIGUOUS)
> +                               n_pages = roundup_pow_of_two(n_pages);
> +
> +                       do {
> +                               unsigned int order;
> +
> +                               order = fls(n_pages) - 1;
> +                               BUG_ON(order > mm->max_order);
> +
> +                               spin_lock(&mgr->lock);
> +                               block = drm_buddy_alloc(mm, order, bar_limit_enabled,
> +                                                                       visible_pfn, mode);
> +                               spin_unlock(&mgr->lock);
>
> -               vis_usage += amdgpu_vram_mgr_vis_size(adev, &node->mm_nodes[i]);
> -               amdgpu_vram_mgr_virt_start(&node->base, &node->mm_nodes[i]);
> -               pages_left -= pages;
> -               ++i;
> +                               if (IS_ERR(block)) {
> +                                       r = -ENOSPC;
> +                                       goto error_free_blocks;
> +                               }
>
> -               if (pages > pages_left)
> -                       pages = pages_left;
> +                               n_pages -= BIT(order);
> +
> +                               list_add_tail(&block->link, &vnode->blocks);
> +
> +                               if (!n_pages)
> +                                       break;
> +                       } while (1);
> +
> +                       pages_left -= pages;
> +                       ++i;
> +
> +                       if (pages > pages_left)
> +                               pages = pages_left;
> +               }
>         }
> +
> +       spin_lock(&mgr->lock);
> +       list_sort(NULL, &vnode->blocks, sort_blocks);
> +
> +       list_for_each_entry(block, &vnode->blocks, link)
> +               vis_usage += amdgpu_vram_mgr_vis_size(adev, block);
> +
> +       block = list_first_entry_or_null(&vnode->blocks,
> +                       struct drm_buddy_block, link);
> +       node->base.start = block->start;
>         spin_unlock(&mgr->lock);
>
>         if (i == 1)
> @@ -472,12 +510,12 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
>         *res = &node->base;
>         return 0;
>
> -error_free:
> -       while (i--)
> -               drm_mm_remove_node(&node->mm_nodes[i]);
> +error_free_blocks:
> +       spin_lock(&mgr->lock);
> +       drm_buddy_free_list(mm, &vnode->blocks);
>         spin_unlock(&mgr->lock);
> -       kvfree(node);
> -
> +error_free_res:
> +       kfree(vnode);
>  error_sub:
>         atomic64_sub(mem_bytes, &mgr->usage);
>         return r;
> @@ -494,28 +532,28 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
>  static void amdgpu_vram_mgr_del(struct ttm_resource_manager *man,
>                                 struct ttm_resource *res)
>  {
> -       struct ttm_range_mgr_node *node = to_ttm_range_mgr_node(res);
> +       struct amdgpu_vram_mgr_node *vnode = to_amdgpu_vram_mgr_node(res);
>         struct amdgpu_vram_mgr *mgr = to_vram_mgr(man);
>         struct amdgpu_device *adev = to_amdgpu_device(mgr);
> +       struct drm_buddy_mm *mm = &mgr->mm;
> +       struct drm_buddy_block *block;
>         uint64_t usage = 0, vis_usage = 0;
> -       unsigned i, pages;
>
>         spin_lock(&mgr->lock);
> -       for (i = 0, pages = res->num_pages; pages;
> -            pages -= node->mm_nodes[i].size, ++i) {
> -               struct drm_mm_node *mm = &node->mm_nodes[i];
> -
> -               drm_mm_remove_node(mm);
> -               usage += mm->size << PAGE_SHIFT;
> -               vis_usage += amdgpu_vram_mgr_vis_size(adev, mm);
> +       list_for_each_entry(block, &vnode->blocks, link) {
> +               usage += block->size << PAGE_SHIFT;
> +               vis_usage += amdgpu_vram_mgr_vis_size(adev, block);
>         }
> +
>         amdgpu_vram_mgr_do_reserve(man);
> +
> +       drm_buddy_free_list(mm, &vnode->blocks);
>         spin_unlock(&mgr->lock);
>
>         atomic64_sub(usage, &mgr->usage);
>         atomic64_sub(vis_usage, &mgr->vis_usage);
>
> -       kvfree(node);
> +       kfree(vnode);
>  }
>
>  /**
> @@ -668,12 +706,6 @@ uint64_t amdgpu_vram_mgr_vis_usage(struct ttm_resource_manager *man)
>  static void amdgpu_vram_mgr_debug(struct ttm_resource_manager *man,
>                                   struct drm_printer *printer)
>  {
> -       struct amdgpu_vram_mgr *mgr = to_vram_mgr(man);
> -
> -       spin_lock(&mgr->lock);
> -       drm_mm_print(&mgr->mm, printer);
> -       spin_unlock(&mgr->lock);
> -
>         drm_printf(printer, "man size:%llu pages, ram usage:%lluMB, vis usage:%lluMB\n",
>                    man->size, amdgpu_vram_mgr_usage(man) >> 20,
>                    amdgpu_vram_mgr_vis_usage(man) >> 20);
> @@ -701,7 +733,7 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev)
>
>         man->func = &amdgpu_vram_mgr_func;
>
> -       drm_mm_init(&mgr->mm, 0, man->size);
> +       drm_buddy_init(&mgr->mm, man->size << PAGE_SHIFT, PAGE_SIZE);
>         spin_lock_init(&mgr->lock);
>         INIT_LIST_HEAD(&mgr->reservations_pending);
>         INIT_LIST_HEAD(&mgr->reserved_pages);
> @@ -737,10 +769,10 @@ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev)
>                 kfree(rsv);
>
>         list_for_each_entry_safe(rsv, temp, &mgr->reserved_pages, node) {
> -               drm_mm_remove_node(&rsv->mm_node);
> +               drm_buddy_free(&mgr->mm, &rsv->mm_node);
>                 kfree(rsv);
>         }
> -       drm_mm_takedown(&mgr->mm);
> +       drm_buddy_fini(&mgr->mm);
>         spin_unlock(&mgr->lock);
>
>         ttm_resource_manager_cleanup(man);
> --
> 2.25.1
>

WARNING: multiple messages have this Message-ID (diff)
From: Alex Deucher <alexdeucher@gmail.com>
To: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
Cc: Maling list - DRI developers <dri-devel@lists.freedesktop.org>,
	 Intel Graphics Development <intel-gfx@lists.freedesktop.org>,
	 amd-gfx list <amd-gfx@lists.freedesktop.org>,
	Christian Koenig <christian.koenig@amd.com>,
	 Matthew Auld <matthew.auld@intel.com>,
	Daniel Vetter <daniel@ffwll.ch>,
	 "Deucher, Alexander" <alexander.deucher@amd.com>
Subject: Re: [Intel-gfx] [PATCH 2/2] Add drm buddy manager support to amdgpu driver
Date: Mon, 20 Sep 2021 15:30:46 -0400	[thread overview]
Message-ID: <CADnq5_NshcMm2ZztfNJn0BcNHxUfs-tBpTCpocpZA3xj0v+CSg@mail.gmail.com> (raw)
In-Reply-To: <20210920192110.221153-1-Arunpravin.PaneerSelvam@amd.com>

On Mon, Sep 20, 2021 at 3:21 PM Arunpravin
<Arunpravin.PaneerSelvam@amd.com> wrote:
>
> Replace drm_mm with drm buddy manager for
> VRAM memory management

Would be good to document why we are doing this and what advantages it
brings over the old drm_mm code.

Alex


>
> Signed-off-by: Arunpravin <Arunpravin.PaneerSelvam@amd.com>
> ---
>  .../gpu/drm/amd/amdgpu/amdgpu_res_cursor.h    |  78 +++++--
>  drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h       |   3 +-
>  drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c  | 216 ++++++++++--------
>  3 files changed, 189 insertions(+), 108 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h
> index acfa207cf970..ba24052e9062 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h
> @@ -30,12 +30,25 @@
>  #include <drm/ttm/ttm_resource.h>
>  #include <drm/ttm/ttm_range_manager.h>
>
> +struct amdgpu_vram_mgr_node {
> +       struct ttm_range_mgr_node tnode;
> +       struct list_head blocks;
> +};
> +
> +static inline struct amdgpu_vram_mgr_node *
> +to_amdgpu_vram_mgr_node(struct ttm_resource *res)
> +{
> +       return container_of(container_of(res, struct ttm_range_mgr_node, base),
> +                       struct amdgpu_vram_mgr_node, tnode);
> +}
> +
>  /* state back for walking over vram_mgr and gtt_mgr allocations */
>  struct amdgpu_res_cursor {
>         uint64_t                start;
>         uint64_t                size;
>         uint64_t                remaining;
> -       struct drm_mm_node      *node;
> +       void                    *node;
> +       uint32_t                mem_type;
>  };
>
>  /**
> @@ -52,8 +65,6 @@ static inline void amdgpu_res_first(struct ttm_resource *res,
>                                     uint64_t start, uint64_t size,
>                                     struct amdgpu_res_cursor *cur)
>  {
> -       struct drm_mm_node *node;
> -
>         if (!res || res->mem_type == TTM_PL_SYSTEM) {
>                 cur->start = start;
>                 cur->size = size;
> @@ -65,14 +76,39 @@ static inline void amdgpu_res_first(struct ttm_resource *res,
>
>         BUG_ON(start + size > res->num_pages << PAGE_SHIFT);
>
> -       node = to_ttm_range_mgr_node(res)->mm_nodes;
> -       while (start >= node->size << PAGE_SHIFT)
> -               start -= node++->size << PAGE_SHIFT;
> +       cur->mem_type = res->mem_type;
> +
> +       if (cur->mem_type == TTM_PL_VRAM) {
> +               struct drm_buddy_block *block;
> +               struct list_head *head, *next;
> +
> +               head = &to_amdgpu_vram_mgr_node(res)->blocks;
> +
> +               block = list_first_entry_or_null(head, struct drm_buddy_block, link);
> +               while (start >= block->size << PAGE_SHIFT) {
> +                       start -= block->size << PAGE_SHIFT;
> +
> +                       next = block->link.next;
> +                       if (next != head)
> +                               block = list_entry(next, struct drm_buddy_block, link);
> +               }
>
> -       cur->start = (node->start << PAGE_SHIFT) + start;
> -       cur->size = min((node->size << PAGE_SHIFT) - start, size);
> -       cur->remaining = size;
> -       cur->node = node;
> +               cur->start = (block->start << PAGE_SHIFT) + start;
> +               cur->size = min((block->size << PAGE_SHIFT) - start, size);
> +               cur->remaining = size;
> +               cur->node = block;
> +       } else if (cur->mem_type == TTM_PL_TT) {
> +               struct drm_mm_node *node;
> +
> +               node = to_ttm_range_mgr_node(res)->mm_nodes;
> +               while (start >= node->size << PAGE_SHIFT)
> +                       start -= node++->size << PAGE_SHIFT;
> +
> +               cur->start = (node->start << PAGE_SHIFT) + start;
> +               cur->size = min((node->size << PAGE_SHIFT) - start, size);
> +               cur->remaining = size;
> +               cur->node = node;
> +       }
>  }
>
>  /**
> @@ -85,8 +121,6 @@ static inline void amdgpu_res_first(struct ttm_resource *res,
>   */
>  static inline void amdgpu_res_next(struct amdgpu_res_cursor *cur, uint64_t size)
>  {
> -       struct drm_mm_node *node = cur->node;
> -
>         BUG_ON(size > cur->remaining);
>
>         cur->remaining -= size;
> @@ -99,9 +133,23 @@ static inline void amdgpu_res_next(struct amdgpu_res_cursor *cur, uint64_t size)
>                 return;
>         }
>
> -       cur->node = ++node;
> -       cur->start = node->start << PAGE_SHIFT;
> -       cur->size = min(node->size << PAGE_SHIFT, cur->remaining);
> +       if (cur->mem_type == TTM_PL_VRAM) {
> +               struct drm_buddy_block *block = cur->node;
> +               struct list_head *next;
> +
> +               next = block->link.next;
> +               block = list_entry(next, struct drm_buddy_block, link);
> +
> +               cur->node = block;
> +               cur->start = block->start << PAGE_SHIFT;
> +               cur->size = min(block->size << PAGE_SHIFT, cur->remaining);
> +       } else if (cur->mem_type == TTM_PL_TT) {
> +               struct drm_mm_node *node = cur->node;
> +
> +               cur->node = ++node;
> +               cur->start = node->start << PAGE_SHIFT;
> +               cur->size = min(node->size << PAGE_SHIFT, cur->remaining);
> +       }
>  }
>
>  #endif
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
> index e69f3e8e06e5..96c8e8aaa0ee 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
> @@ -26,6 +26,7 @@
>
>  #include <linux/dma-direction.h>
>  #include <drm/gpu_scheduler.h>
> +#include <drm/drm_buddy.h>
>  #include "amdgpu.h"
>
>  #define AMDGPU_PL_GDS          (TTM_PL_PRIV + 0)
> @@ -40,7 +41,7 @@
>
>  struct amdgpu_vram_mgr {
>         struct ttm_resource_manager manager;
> -       struct drm_mm mm;
> +       struct drm_buddy_mm mm;
>         spinlock_t lock;
>         struct list_head reservations_pending;
>         struct list_head reserved_pages;
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
> index 7b2b0980ec41..de0c5f4cabaf 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
> @@ -23,7 +23,9 @@
>   */
>
>  #include <linux/dma-mapping.h>
> +#include <linux/list_sort.h>
>  #include <drm/ttm/ttm_range_manager.h>
> +#include <drm/drm_buddy.h>
>
>  #include "amdgpu.h"
>  #include "amdgpu_vm.h"
> @@ -33,7 +35,7 @@
>
>  struct amdgpu_vram_reservation {
>         struct list_head node;
> -       struct drm_mm_node mm_node;
> +       struct drm_buddy_block mm_node;
>  };
>
>  static inline struct amdgpu_vram_mgr *
> @@ -196,10 +198,10 @@ const struct attribute_group amdgpu_vram_mgr_attr_group = {
>   * Calculate how many bytes of the MM node are inside visible VRAM
>   */
>  static u64 amdgpu_vram_mgr_vis_size(struct amdgpu_device *adev,
> -                                   struct drm_mm_node *node)
> +                                   struct drm_buddy_block *block)
>  {
> -       uint64_t start = node->start << PAGE_SHIFT;
> -       uint64_t end = (node->size + node->start) << PAGE_SHIFT;
> +       uint64_t start = block->start << PAGE_SHIFT;
> +       uint64_t end = (block->size + block->start) << PAGE_SHIFT;
>
>         if (start >= adev->gmc.visible_vram_size)
>                 return 0;
> @@ -220,8 +222,8 @@ u64 amdgpu_vram_mgr_bo_visible_size(struct amdgpu_bo *bo)
>  {
>         struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
>         struct ttm_resource *res = bo->tbo.resource;
> -       unsigned pages = res->num_pages;
> -       struct drm_mm_node *mm;
> +       struct amdgpu_vram_mgr_node *vnode = to_amdgpu_vram_mgr_node(res);
> +       struct drm_buddy_block *block;
>         u64 usage;
>
>         if (amdgpu_gmc_vram_full_visible(&adev->gmc))
> @@ -230,9 +232,8 @@ u64 amdgpu_vram_mgr_bo_visible_size(struct amdgpu_bo *bo)
>         if (res->start >= adev->gmc.visible_vram_size >> PAGE_SHIFT)
>                 return 0;
>
> -       mm = &container_of(res, struct ttm_range_mgr_node, base)->mm_nodes[0];
> -       for (usage = 0; pages; pages -= mm->size, mm++)
> -               usage += amdgpu_vram_mgr_vis_size(adev, mm);
> +       list_for_each_entry(block, &vnode->blocks, link)
> +               usage += amdgpu_vram_mgr_vis_size(adev, block);
>
>         return usage;
>  }
> @@ -242,12 +243,15 @@ static void amdgpu_vram_mgr_do_reserve(struct ttm_resource_manager *man)
>  {
>         struct amdgpu_vram_mgr *mgr = to_vram_mgr(man);
>         struct amdgpu_device *adev = to_amdgpu_device(mgr);
> -       struct drm_mm *mm = &mgr->mm;
> +       struct drm_buddy_mm *mm = &mgr->mm;
>         struct amdgpu_vram_reservation *rsv, *temp;
>         uint64_t vis_usage;
> +       int r = 0;
>
>         list_for_each_entry_safe(rsv, temp, &mgr->reservations_pending, node) {
> -               if (drm_mm_reserve_node(mm, &rsv->mm_node))
> +               r = drm_buddy_alloc_range(mm, &rsv->node, rsv->mm_node.start, rsv->mm_node.size);
> +
> +               if (unlikely(r))
>                         continue;
>
>                 dev_dbg(adev->dev, "Reservation 0x%llx - %lld, Succeeded\n",
> @@ -333,26 +337,16 @@ int amdgpu_vram_mgr_query_page_status(struct ttm_resource_manager *man,
>         return ret;
>  }
>
> -/**
> - * amdgpu_vram_mgr_virt_start - update virtual start address
> - *
> - * @mem: ttm_resource to update
> - * @node: just allocated node
> - *
> - * Calculate a virtual BO start address to easily check if everything is CPU
> - * accessible.
> - */
> -static void amdgpu_vram_mgr_virt_start(struct ttm_resource *mem,
> -                                      struct drm_mm_node *node)
> +static int sort_blocks(void *priv, const struct list_head *A,
> +                                       const struct list_head *B)
>  {
> -       unsigned long start;
> +       struct drm_buddy_block *a = list_entry(A, typeof(*a), link);
> +       struct drm_buddy_block *b = list_entry(B, typeof(*b), link);
>
> -       start = node->start + node->size;
> -       if (start > mem->num_pages)
> -               start -= mem->num_pages;
> +       if (a->start < b->start)
> +               return -1;
>         else
> -               start = 0;
> -       mem->start = max(mem->start, start);
> +               return 1;
>  }
>
>  /**
> @@ -370,15 +364,20 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
>                                const struct ttm_place *place,
>                                struct ttm_resource **res)
>  {
> -       unsigned long lpfn, num_nodes, pages_per_node, pages_left, pages;
> +       unsigned long lpfn, pages_per_node, pages_left, pages;
>         struct amdgpu_vram_mgr *mgr = to_vram_mgr(man);
>         struct amdgpu_device *adev = to_amdgpu_device(mgr);
>         uint64_t vis_usage = 0, mem_bytes, max_bytes;
> +       struct amdgpu_vram_mgr_node *vnode;
> +       struct drm_buddy_mm *mm = &mgr->mm;
>         struct ttm_range_mgr_node *node;
> -       struct drm_mm *mm = &mgr->mm;
> -       enum drm_mm_insert_mode mode;
> +       enum drm_buddy_alloc_mode mode;
> +       struct drm_buddy_block *block;
> +       unsigned int visible_pfn;
> +       bool bar_limit_enabled;
> +       unsigned long n_pages;
>         unsigned i;
> -       int r;
> +       int r = 0;
>
>         lpfn = place->lpfn;
>         if (!lpfn)
> @@ -395,10 +394,9 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
>                 goto error_sub;
>         }
>
> -       if (place->flags & TTM_PL_FLAG_CONTIGUOUS) {
> +       if (place->flags & TTM_PL_FLAG_CONTIGUOUS)
>                 pages_per_node = ~0ul;
> -               num_nodes = 1;
> -       } else {
> +       else {
>  #ifdef CONFIG_TRANSPARENT_HUGEPAGE
>                 pages_per_node = HPAGE_PMD_NR;
>  #else
> @@ -407,57 +405,97 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
>  #endif
>                 pages_per_node = max_t(uint32_t, pages_per_node,
>                                        tbo->page_alignment);
> -               num_nodes = DIV_ROUND_UP_ULL(PFN_UP(mem_bytes), pages_per_node);
>         }
>
> -       node = kvmalloc(struct_size(node, mm_nodes, num_nodes),
> -                       GFP_KERNEL | __GFP_ZERO);
> -       if (!node) {
> +       vnode = kzalloc(sizeof(*vnode), GFP_KERNEL);
> +
> +       if (!vnode) {
>                 r = -ENOMEM;
>                 goto error_sub;
>         }
>
> +       node = &vnode->tnode;
> +
>         ttm_resource_init(tbo, place, &node->base);
>
> -       mode = DRM_MM_INSERT_BEST;
> -       if (place->flags & TTM_PL_FLAG_TOPDOWN)
> -               mode = DRM_MM_INSERT_HIGH;
> +       bar_limit_enabled = !(amdgpu_gmc_vram_full_visible(&adev->gmc));
> +
> +       visible_pfn = adev->gmc.visible_vram_size >> PAGE_SHIFT;
> +
> +       mode = DRM_BUDDY_BOTTOM_UP;
> +       if (!place->fpfn && lpfn == man->size &&
> +                                       (place->flags & TTM_PL_FLAG_TOPDOWN))
> +               /* Allocate blocks from CPU non-mappable (TOP-DOWN) region */
> +               mode = DRM_BUDDY_TOP_DOWN;
> +       else if (place->fpfn || (lpfn != man->size && lpfn != visible_pfn))
> +               /* Allocate blocks in desired range */
> +               mode = DRM_BUDDY_ALLOC_RANGE;
>
>         pages_left = node->base.num_pages;
>
>         /* Limit maximum size to 2GB due to SG table limitations */
>         pages = min(pages_left, 2UL << (30 - PAGE_SHIFT));
>
> +       INIT_LIST_HEAD(&vnode->blocks);
> +
>         i = 0;
> -       spin_lock(&mgr->lock);
> -       while (pages_left) {
> -               uint32_t alignment = tbo->page_alignment;
> -
> -               if (pages >= pages_per_node)
> -                       alignment = pages_per_node;
> -
> -               r = drm_mm_insert_node_in_range(mm, &node->mm_nodes[i], pages,
> -                                               alignment, 0, place->fpfn,
> -                                               lpfn, mode);
> -               if (unlikely(r)) {
> -                       if (pages > pages_per_node) {
> -                               if (is_power_of_2(pages))
> -                                       pages = pages / 2;
> -                               else
> -                                       pages = rounddown_pow_of_two(pages);
> -                               continue;
> -                       }
> -                       goto error_free;
> -               }
> +       if (mode == DRM_BUDDY_ALLOC_RANGE) {
> +               r = drm_buddy_alloc_range(mm, &vnode->blocks,
> +                               (uint64_t)place->fpfn << PAGE_SHIFT, pages << PAGE_SHIFT);
> +
> +               if (unlikely(r))
> +                       goto error_free_res;
> +       } else {
> +               while (pages_left) {
> +                       if (pages >= pages_per_node)
> +                               pages = pages_per_node;
> +
> +                       n_pages = pages;
> +
> +                       if (place->flags & TTM_PL_FLAG_CONTIGUOUS)
> +                               n_pages = roundup_pow_of_two(n_pages);
> +
> +                       do {
> +                               unsigned int order;
> +
> +                               order = fls(n_pages) - 1;
> +                               BUG_ON(order > mm->max_order);
> +
> +                               spin_lock(&mgr->lock);
> +                               block = drm_buddy_alloc(mm, order, bar_limit_enabled,
> +                                                                       visible_pfn, mode);
> +                               spin_unlock(&mgr->lock);
>
> -               vis_usage += amdgpu_vram_mgr_vis_size(adev, &node->mm_nodes[i]);
> -               amdgpu_vram_mgr_virt_start(&node->base, &node->mm_nodes[i]);
> -               pages_left -= pages;
> -               ++i;
> +                               if (IS_ERR(block)) {
> +                                       r = -ENOSPC;
> +                                       goto error_free_blocks;
> +                               }
>
> -               if (pages > pages_left)
> -                       pages = pages_left;
> +                               n_pages -= BIT(order);
> +
> +                               list_add_tail(&block->link, &vnode->blocks);
> +
> +                               if (!n_pages)
> +                                       break;
> +                       } while (1);
> +
> +                       pages_left -= pages;
> +                       ++i;
> +
> +                       if (pages > pages_left)
> +                               pages = pages_left;
> +               }
>         }
> +
> +       spin_lock(&mgr->lock);
> +       list_sort(NULL, &vnode->blocks, sort_blocks);
> +
> +       list_for_each_entry(block, &vnode->blocks, link)
> +               vis_usage += amdgpu_vram_mgr_vis_size(adev, block);
> +
> +       block = list_first_entry_or_null(&vnode->blocks,
> +                       struct drm_buddy_block, link);
> +       node->base.start = block->start;
>         spin_unlock(&mgr->lock);
>
>         if (i == 1)
> @@ -472,12 +510,12 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
>         *res = &node->base;
>         return 0;
>
> -error_free:
> -       while (i--)
> -               drm_mm_remove_node(&node->mm_nodes[i]);
> +error_free_blocks:
> +       spin_lock(&mgr->lock);
> +       drm_buddy_free_list(mm, &vnode->blocks);
>         spin_unlock(&mgr->lock);
> -       kvfree(node);
> -
> +error_free_res:
> +       kfree(vnode);
>  error_sub:
>         atomic64_sub(mem_bytes, &mgr->usage);
>         return r;
> @@ -494,28 +532,28 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
>  static void amdgpu_vram_mgr_del(struct ttm_resource_manager *man,
>                                 struct ttm_resource *res)
>  {
> -       struct ttm_range_mgr_node *node = to_ttm_range_mgr_node(res);
> +       struct amdgpu_vram_mgr_node *vnode = to_amdgpu_vram_mgr_node(res);
>         struct amdgpu_vram_mgr *mgr = to_vram_mgr(man);
>         struct amdgpu_device *adev = to_amdgpu_device(mgr);
> +       struct drm_buddy_mm *mm = &mgr->mm;
> +       struct drm_buddy_block *block;
>         uint64_t usage = 0, vis_usage = 0;
> -       unsigned i, pages;
>
>         spin_lock(&mgr->lock);
> -       for (i = 0, pages = res->num_pages; pages;
> -            pages -= node->mm_nodes[i].size, ++i) {
> -               struct drm_mm_node *mm = &node->mm_nodes[i];
> -
> -               drm_mm_remove_node(mm);
> -               usage += mm->size << PAGE_SHIFT;
> -               vis_usage += amdgpu_vram_mgr_vis_size(adev, mm);
> +       list_for_each_entry(block, &vnode->blocks, link) {
> +               usage += block->size << PAGE_SHIFT;
> +               vis_usage += amdgpu_vram_mgr_vis_size(adev, block);
>         }
> +
>         amdgpu_vram_mgr_do_reserve(man);
> +
> +       drm_buddy_free_list(mm, &vnode->blocks);
>         spin_unlock(&mgr->lock);
>
>         atomic64_sub(usage, &mgr->usage);
>         atomic64_sub(vis_usage, &mgr->vis_usage);
>
> -       kvfree(node);
> +       kfree(vnode);
>  }
>
>  /**
> @@ -668,12 +706,6 @@ uint64_t amdgpu_vram_mgr_vis_usage(struct ttm_resource_manager *man)
>  static void amdgpu_vram_mgr_debug(struct ttm_resource_manager *man,
>                                   struct drm_printer *printer)
>  {
> -       struct amdgpu_vram_mgr *mgr = to_vram_mgr(man);
> -
> -       spin_lock(&mgr->lock);
> -       drm_mm_print(&mgr->mm, printer);
> -       spin_unlock(&mgr->lock);
> -
>         drm_printf(printer, "man size:%llu pages, ram usage:%lluMB, vis usage:%lluMB\n",
>                    man->size, amdgpu_vram_mgr_usage(man) >> 20,
>                    amdgpu_vram_mgr_vis_usage(man) >> 20);
> @@ -701,7 +733,7 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev)
>
>         man->func = &amdgpu_vram_mgr_func;
>
> -       drm_mm_init(&mgr->mm, 0, man->size);
> +       drm_buddy_init(&mgr->mm, man->size << PAGE_SHIFT, PAGE_SIZE);
>         spin_lock_init(&mgr->lock);
>         INIT_LIST_HEAD(&mgr->reservations_pending);
>         INIT_LIST_HEAD(&mgr->reserved_pages);
> @@ -737,10 +769,10 @@ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev)
>                 kfree(rsv);
>
>         list_for_each_entry_safe(rsv, temp, &mgr->reserved_pages, node) {
> -               drm_mm_remove_node(&rsv->mm_node);
> +               drm_buddy_free(&mgr->mm, &rsv->mm_node);
>                 kfree(rsv);
>         }
> -       drm_mm_takedown(&mgr->mm);
> +       drm_buddy_fini(&mgr->mm);
>         spin_unlock(&mgr->lock);
>
>         ttm_resource_manager_cleanup(man);
> --
> 2.25.1
>

  reply	other threads:[~2021-09-20 19:31 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-20 19:21 [PATCH 2/2] Add drm buddy manager support to amdgpu driver Arunpravin
2021-09-20 19:21 ` [Intel-gfx] " Arunpravin
2021-09-20 19:30 ` Alex Deucher [this message]
2021-09-20 19:30   ` Alex Deucher
2021-09-21  9:04 ` Christian König
2021-09-21  9:04   ` [Intel-gfx] " Christian König
2021-09-21 15:51   ` Paneer Selvam, Arunpravin
2021-09-21 15:51     ` [Intel-gfx] " Paneer Selvam, Arunpravin
2021-09-22  6:48     ` Christian König
2021-09-22  6:48       ` [Intel-gfx] " Christian König
2021-09-23  5:53       ` Paneer Selvam, Arunpravin
2021-09-23  5:53         ` [Intel-gfx] " Paneer Selvam, Arunpravin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CADnq5_NshcMm2ZztfNJn0BcNHxUfs-tBpTCpocpZA3xj0v+CSg@mail.gmail.com \
    --to=alexdeucher@gmail.com \
    --cc=Arunpravin.PaneerSelvam@amd.com \
    --cc=alexander.deucher@amd.com \
    --cc=amd-gfx@lists.freedesktop.org \
    --cc=christian.koenig@amd.com \
    --cc=daniel@ffwll.ch \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=matthew.auld@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.