Re: [Intel-gfx] [PATCH 1/6] drm/i915/ttm: add ttm_buddy_man

2021-06-08 Thread Thomas Hellström


On 6/8/21 10:11 AM, Matthew Auld wrote:

On 08/06/2021 08:11, Thomas Hellström wrote:

On Mon, 2021-06-07 at 19:22 +0100, Matthew Auld wrote:

Add back our standalone i915_buddy allocator and integrate it into a
ttm_resource_manager. This will plug into our ttm backend for
managing
device local-memory in the next couple of patches.

Signed-off-by: Matthew Auld 
Cc: Thomas Hellström 
---



Since the buddy + selftests have been part of the driver before, I
didn't review them separately, but for the TTM interface, some minor
comments below. With those fixed,

Acked-by: Thomas Hellström 



diff --git a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
new file mode 100644
index ..d7bf37be1932
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
@@ -0,0 +1,246 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#include 
+
+#include 
+#include 
+
+#include "i915_ttm_buddy_manager.h"
+
+#include "i915_buddy.h"
+#include "i915_gem.h"
+
+struct i915_ttm_buddy_manager {
+   struct ttm_resource_manager manager;
+   struct i915_buddy_mm mm;
+   struct list_head reserved;
+   struct mutex lock;
+};
+
+static inline struct i915_ttm_buddy_manager *


"inline" shouldn't be needed here.


+to_buddy_manager(struct ttm_resource_manager *man)
+{
+   return container_of(man, struct i915_ttm_buddy_manager,
manager);
+}
+
+static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager
*man,
+   struct ttm_buffer_object *bo,
+   const struct ttm_place *place,
+   struct ttm_resource **res)
+{
+   struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
+   struct i915_ttm_buddy_resource *bman_res;
+   struct i915_buddy_mm *mm = >mm;
+   unsigned long n_pages;
+   unsigned int min_order;
+   u64 size;
+   int err;
+
+   GEM_BUG_ON(place->fpfn || place->lpfn);
+   GEM_BUG_ON(bo->page_alignment < mm->chunk_size);
+
+   bman_res = kzalloc(sizeof(*bman_res), GFP_KERNEL);
+   if (!bman_res)
+   return -ENOMEM;
+
+   ttm_resource_init(bo, place, _res->base);
+   INIT_LIST_HEAD(_res->blocks);
+   bman_res->mm = mm;
+
+   GEM_BUG_ON(!bman_res->base.num_pages);
+   size = bman_res->base.num_pages << PAGE_SHIFT;
+
+   min_order = ilog2(bo->page_alignment) - ilog2(mm-

chunk_size);

+   if (place->flags & TTM_PL_FLAG_CONTIGUOUS) {
+   size = roundup_pow_of_two(size);
+   min_order = ilog2(size) - ilog2(mm->chunk_size);
+   }
+
+   if (size > mm->size) {
+   err = -E2BIG;
+   goto err_free_res;
+   }
+
+   n_pages = size >> ilog2(mm->chunk_size);
+
+   do {
+   struct i915_buddy_block *block;
+   unsigned int order;
+
+   order = fls(n_pages) - 1;
+   GEM_BUG_ON(order > mm->max_order);
+   GEM_BUG_ON(order < min_order);
+
+   do {
+   mutex_lock(>lock);
+   block = i915_buddy_alloc(mm, order);
+   mutex_unlock(>lock);
+   if (!IS_ERR(block))
+   break;
+
+   if (order-- == min_order) {
+   err = -ENXIO;


IIRC, TTM relies on -ENOSPC to retry with evictions.


Ah, right. We convert that back to -ENXIO in the upper levels somewhere?

Yes, that's done in the ttm bo backend after ttm_bo_validate() and bo 
initialization.


/Thomas


___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 1/6] drm/i915/ttm: add ttm_buddy_man

2021-06-08 Thread Matthew Auld

On 08/06/2021 08:11, Thomas Hellström wrote:

On Mon, 2021-06-07 at 19:22 +0100, Matthew Auld wrote:

Add back our standalone i915_buddy allocator and integrate it into a
ttm_resource_manager. This will plug into our ttm backend for
managing
device local-memory in the next couple of patches.

Signed-off-by: Matthew Auld 
Cc: Thomas Hellström 
---



Since the buddy + selftests have been part of the driver before, I
didn't review them separately, but for the TTM interface, some minor
comments below. With those fixed,

Acked-by: Thomas Hellström 



diff --git a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
new file mode 100644
index ..d7bf37be1932
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
@@ -0,0 +1,246 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#include 
+
+#include 
+#include 
+
+#include "i915_ttm_buddy_manager.h"
+
+#include "i915_buddy.h"
+#include "i915_gem.h"
+
+struct i915_ttm_buddy_manager {
+   struct ttm_resource_manager manager;
+   struct i915_buddy_mm mm;
+   struct list_head reserved;
+   struct mutex lock;
+};
+
+static inline struct i915_ttm_buddy_manager *


"inline" shouldn't be needed here.


+to_buddy_manager(struct ttm_resource_manager *man)
+{
+   return container_of(man, struct i915_ttm_buddy_manager,
manager);
+}
+
+static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager
*man,
+   struct ttm_buffer_object *bo,
+   const struct ttm_place *place,
+   struct ttm_resource **res)
+{
+   struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
+   struct i915_ttm_buddy_resource *bman_res;
+   struct i915_buddy_mm *mm = >mm;
+   unsigned long n_pages;
+   unsigned int min_order;
+   u64 size;
+   int err;
+
+   GEM_BUG_ON(place->fpfn || place->lpfn);
+   GEM_BUG_ON(bo->page_alignment < mm->chunk_size);
+
+   bman_res = kzalloc(sizeof(*bman_res), GFP_KERNEL);
+   if (!bman_res)
+   return -ENOMEM;
+
+   ttm_resource_init(bo, place, _res->base);
+   INIT_LIST_HEAD(_res->blocks);
+   bman_res->mm = mm;
+
+   GEM_BUG_ON(!bman_res->base.num_pages);
+   size = bman_res->base.num_pages << PAGE_SHIFT;
+
+   min_order = ilog2(bo->page_alignment) - ilog2(mm-

chunk_size);

+   if (place->flags & TTM_PL_FLAG_CONTIGUOUS) {
+   size = roundup_pow_of_two(size);
+   min_order = ilog2(size) - ilog2(mm->chunk_size);
+   }
+
+   if (size > mm->size) {
+   err = -E2BIG;
+   goto err_free_res;
+   }
+
+   n_pages = size >> ilog2(mm->chunk_size);
+
+   do {
+   struct i915_buddy_block *block;
+   unsigned int order;
+
+   order = fls(n_pages) - 1;
+   GEM_BUG_ON(order > mm->max_order);
+   GEM_BUG_ON(order < min_order);
+
+   do {
+   mutex_lock(>lock);
+   block = i915_buddy_alloc(mm, order);
+   mutex_unlock(>lock);
+   if (!IS_ERR(block))
+   break;
+
+   if (order-- == min_order) {
+   err = -ENXIO;


IIRC, TTM relies on -ENOSPC to retry with evictions.


Ah, right. We convert that back to -ENXIO in the upper levels somewhere?




+   goto err_free_blocks;
+   }
+   } while (1);
+
+   n_pages -= BIT(order);
+
+   list_add_tail(>link, _res->blocks);
+
+   if (!n_pages)
+   break;
+   } while (1);
+
+   *res = _res->base;
+   return 0;
+
+err_free_blocks:
+   mutex_lock(>lock);
+   i915_buddy_free_list(mm, _res->blocks);
+   mutex_unlock(>lock);
+err_free_res:
+   kfree(bman_res);
+   return err;
+}
+


/Thomas



___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 1/6] drm/i915/ttm: add ttm_buddy_man

2021-06-08 Thread Thomas Hellström
On Mon, 2021-06-07 at 19:22 +0100, Matthew Auld wrote:
> Add back our standalone i915_buddy allocator and integrate it into a
> ttm_resource_manager. This will plug into our ttm backend for
> managing
> device local-memory in the next couple of patches.
> 
> Signed-off-by: Matthew Auld 
> Cc: Thomas Hellström 
> ---
> 

Since the buddy + selftests have been part of the driver before, I
didn't review them separately, but for the TTM interface, some minor
comments below. With those fixed,

Acked-by: Thomas Hellström 


> diff --git a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
> b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
> new file mode 100644
> index ..d7bf37be1932
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
> @@ -0,0 +1,246 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2021 Intel Corporation
> + */
> +
> +#include 
> +
> +#include 
> +#include 
> +
> +#include "i915_ttm_buddy_manager.h"
> +
> +#include "i915_buddy.h"
> +#include "i915_gem.h"
> +
> +struct i915_ttm_buddy_manager {
> +   struct ttm_resource_manager manager;
> +   struct i915_buddy_mm mm;
> +   struct list_head reserved;
> +   struct mutex lock;
> +};
> +
> +static inline struct i915_ttm_buddy_manager *

"inline" shouldn't be needed here.

> +to_buddy_manager(struct ttm_resource_manager *man)
> +{
> +   return container_of(man, struct i915_ttm_buddy_manager,
> manager);
> +}
> +
> +static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager
> *man,
> +   struct ttm_buffer_object *bo,
> +   const struct ttm_place *place,
> +   struct ttm_resource **res)
> +{
> +   struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
> +   struct i915_ttm_buddy_resource *bman_res;
> +   struct i915_buddy_mm *mm = >mm;
> +   unsigned long n_pages;
> +   unsigned int min_order;
> +   u64 size;
> +   int err;
> +
> +   GEM_BUG_ON(place->fpfn || place->lpfn);
> +   GEM_BUG_ON(bo->page_alignment < mm->chunk_size);
> +
> +   bman_res = kzalloc(sizeof(*bman_res), GFP_KERNEL);
> +   if (!bman_res)
> +   return -ENOMEM;
> +
> +   ttm_resource_init(bo, place, _res->base);
> +   INIT_LIST_HEAD(_res->blocks);
> +   bman_res->mm = mm;
> +
> +   GEM_BUG_ON(!bman_res->base.num_pages);
> +   size = bman_res->base.num_pages << PAGE_SHIFT;
> +
> +   min_order = ilog2(bo->page_alignment) - ilog2(mm-
> >chunk_size);
> +   if (place->flags & TTM_PL_FLAG_CONTIGUOUS) {
> +   size = roundup_pow_of_two(size);
> +   min_order = ilog2(size) - ilog2(mm->chunk_size);
> +   }
> +
> +   if (size > mm->size) {
> +   err = -E2BIG;
> +   goto err_free_res;
> +   }
> +
> +   n_pages = size >> ilog2(mm->chunk_size);
> +
> +   do {
> +   struct i915_buddy_block *block;
> +   unsigned int order;
> +
> +   order = fls(n_pages) - 1;
> +   GEM_BUG_ON(order > mm->max_order);
> +   GEM_BUG_ON(order < min_order);
> +
> +   do {
> +   mutex_lock(>lock);
> +   block = i915_buddy_alloc(mm, order);
> +   mutex_unlock(>lock);
> +   if (!IS_ERR(block))
> +   break;
> +
> +   if (order-- == min_order) {
> +   err = -ENXIO;

IIRC, TTM relies on -ENOSPC to retry with evictions.

> +   goto err_free_blocks;
> +   }
> +   } while (1);
> +
> +   n_pages -= BIT(order);
> +
> +   list_add_tail(>link, _res->blocks);
> +
> +   if (!n_pages)
> +   break;
> +   } while (1);
> +
> +   *res = _res->base;
> +   return 0;
> +
> +err_free_blocks:
> +   mutex_lock(>lock);
> +   i915_buddy_free_list(mm, _res->blocks);
> +   mutex_unlock(>lock);
> +err_free_res:
> +   kfree(bman_res);
> +   return err;
> +}
> +

/Thomas


___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 1/6] drm/i915/ttm: add ttm_buddy_man

2021-06-07 Thread Matthew Auld
Add back our standalone i915_buddy allocator and integrate it into a
ttm_resource_manager. This will plug into our ttm backend for managing
device local-memory in the next couple of patches.

Signed-off-by: Matthew Auld 
Cc: Thomas Hellström 
---
 drivers/gpu/drm/i915/Makefile |   2 +
 drivers/gpu/drm/i915/i915_buddy.c | 412 +
 drivers/gpu/drm/i915/i915_buddy.h | 133 +++
 drivers/gpu/drm/i915/i915_ttm_buddy_manager.c | 246 ++
 drivers/gpu/drm/i915/i915_ttm_buddy_manager.h |  56 ++
 drivers/gpu/drm/i915/selftests/i915_buddy.c   | 789 ++
 6 files changed, 1638 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/i915_buddy.c
 create mode 100644 drivers/gpu/drm/i915/i915_buddy.h
 create mode 100644 drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
 create mode 100644 drivers/gpu/drm/i915/i915_ttm_buddy_manager.h
 create mode 100644 drivers/gpu/drm/i915/selftests/i915_buddy.c

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index f57dfc74d6ce..6c84e96ab26a 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -162,6 +162,7 @@ gem-y += \
 i915-y += \
  $(gem-y) \
  i915_active.o \
+ i915_buddy.o \
  i915_cmd_parser.o \
  i915_gem_evict.o \
  i915_gem_gtt.o \
@@ -171,6 +172,7 @@ i915-y += \
  i915_request.o \
  i915_scheduler.o \
  i915_trace_points.o \
+ i915_ttm_buddy_manager.o \
  i915_vma.o \
  intel_wopcm.o
 
diff --git a/drivers/gpu/drm/i915/i915_buddy.c 
b/drivers/gpu/drm/i915/i915_buddy.c
new file mode 100644
index ..29dd7d0310c1
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_buddy.c
@@ -0,0 +1,412 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#include 
+
+#include "i915_buddy.h"
+
+#include "i915_gem.h"
+#include "i915_utils.h"
+
+static struct i915_buddy_block *i915_block_alloc(struct i915_buddy_mm *mm,
+struct i915_buddy_block 
*parent,
+unsigned int order,
+u64 offset)
+{
+   struct i915_buddy_block *block;
+
+   GEM_BUG_ON(order > I915_BUDDY_MAX_ORDER);
+
+   block = kmem_cache_zalloc(mm->slab_blocks, GFP_KERNEL);
+   if (!block)
+   return NULL;
+
+   block->header = offset;
+   block->header |= order;
+   block->parent = parent;
+
+   GEM_BUG_ON(block->header & I915_BUDDY_HEADER_UNUSED);
+   return block;
+}
+
+static void i915_block_free(struct i915_buddy_mm *mm,
+   struct i915_buddy_block *block)
+{
+   kmem_cache_free(mm->slab_blocks, block);
+}
+
+static void mark_allocated(struct i915_buddy_block *block)
+{
+   block->header &= ~I915_BUDDY_HEADER_STATE;
+   block->header |= I915_BUDDY_ALLOCATED;
+
+   list_del(>link);
+}
+
+static void mark_free(struct i915_buddy_mm *mm,
+ struct i915_buddy_block *block)
+{
+   block->header &= ~I915_BUDDY_HEADER_STATE;
+   block->header |= I915_BUDDY_FREE;
+
+   list_add(>link,
+>free_list[i915_buddy_block_order(block)]);
+}
+
+static void mark_split(struct i915_buddy_block *block)
+{
+   block->header &= ~I915_BUDDY_HEADER_STATE;
+   block->header |= I915_BUDDY_SPLIT;
+
+   list_del(>link);
+}
+
+int i915_buddy_init(struct i915_buddy_mm *mm, u64 size, u64 chunk_size)
+{
+   unsigned int i;
+   u64 offset;
+
+   if (size < chunk_size)
+   return -EINVAL;
+
+   if (chunk_size < PAGE_SIZE)
+   return -EINVAL;
+
+   if (!is_power_of_2(chunk_size))
+   return -EINVAL;
+
+   size = round_down(size, chunk_size);
+
+   mm->size = size;
+   mm->chunk_size = chunk_size;
+   mm->max_order = ilog2(size) - ilog2(chunk_size);
+
+   GEM_BUG_ON(mm->max_order > I915_BUDDY_MAX_ORDER);
+
+   mm->slab_blocks = KMEM_CACHE(i915_buddy_block, SLAB_HWCACHE_ALIGN);
+   if (!mm->slab_blocks)
+   return -ENOMEM;
+
+   mm->free_list = kmalloc_array(mm->max_order + 1,
+ sizeof(struct list_head),
+ GFP_KERNEL);
+   if (!mm->free_list)
+   goto out_destroy_slab;
+
+   for (i = 0; i <= mm->max_order; ++i)
+   INIT_LIST_HEAD(>free_list[i]);
+
+   mm->n_roots = hweight64(size);
+
+   mm->roots = kmalloc_array(mm->n_roots,
+ sizeof(struct i915_buddy_block *),
+ GFP_KERNEL);
+   if (!mm->roots)
+   goto out_free_list;
+
+   offset = 0;
+   i = 0;
+
+   /*
+* Split into power-of-two blocks, in case we are given a size that is
+* not itself a power-of-two.
+*/
+   do {
+   struct i915_buddy_block *root;
+