Commit 6387a3c4 authored by Arunpravin's avatar Arunpravin Committed by Christian König

drm: move the buddy allocator from i915 into common drm

Move the base i915 buddy allocator code into drm
- Move i915_buddy.h to include/drm
- Move i915_buddy.c to drm root folder
- Rename "i915" string with "drm" string wherever applicable
- Rename "I915" string with "DRM" string wherever applicable
- Fix header file dependencies
- Fix alignment issues
- add Makefile support for drm buddy
- export functions and write kerneldoc description
- Remove i915 selftest config check condition as buddy selftest
  will be moved to drm selftest folder

cleanup i915 buddy references in i915 driver module
and replace with drm buddy

v2:
  - include header file in alphabetical order(Thomas)
  - merged changes listed in the body section into a single patch
    to keep the build intact(Christian, Jani)

v3:
  - make drm buddy a separate module(Thomas, Christian)

v4:
  - Fix build error reported by kernel test robot <lkp@intel.com>
  - removed i915 buddy selftest from i915_mock_selftests.h to
    avoid build error
  - removed selftests/i915_buddy.c file as we create a new set of
    buddy test cases in drm/selftests folder

v5:
  - Fix merge conflict issue

v6:
  - replace drm_buddy_mm structure name as drm_buddy(Thomas, Christian)
  - replace drm_buddy_alloc() function name as drm_buddy_alloc_blocks()
    (Thomas)
  - replace drm_buddy_free() function name as drm_buddy_free_block()
    (Thomas)
  - export drm_buddy_free_block() function
  - fix multiple instances of KMEM_CACHE() entry

v7:
  - fix warnings reported by kernel test robot <lkp@intel.com>
  - modify the license(Christian)

v8:
  - fix warnings reported by kernel test robot <lkp@intel.com>
Signed-off-by: default avatarArunpravin <Arunpravin.PaneerSelvam@amd.com>
Acked-by: default avatarChristian König <christian.koenig@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220118104504.2349-1-Arunpravin.PaneerSelvam@amd.comSigned-off-by: default avatarChristian König <christian.koenig@amd.com>
parent 6b79f96f
......@@ -204,6 +204,12 @@ config DRM_TTM
GPU memory types. Will be enabled automatically if a device driver
uses it.
config DRM_BUDDY
tristate
depends on DRM
help
A page based buddy allocator
config DRM_VRAM_HELPER
tristate
depends on DRM
......
......@@ -40,6 +40,8 @@ obj-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_cma_helper.o
drm_shmem_helper-y := drm_gem_shmem_helper.o
obj-$(CONFIG_DRM_GEM_SHMEM_HELPER) += drm_shmem_helper.o
obj-$(CONFIG_DRM_BUDDY) += drm_buddy.o
drm_vram_helper-y := drm_gem_vram_helper.o
obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o
......
......@@ -28,6 +28,7 @@ config DRM_I915
select CEC_CORE if CEC_NOTIFIER
select VMAP_PFN
select DRM_TTM
select DRM_BUDDY
help
Choose this option if you have a system that has "Intel Graphics
Media Accelerator" or "HD Graphics" integrated graphics,
......
......@@ -161,7 +161,6 @@ gem-y += \
i915-y += \
$(gem-y) \
i915_active.o \
i915_buddy.o \
i915_cmd_parser.o \
i915_gem_evict.o \
i915_gem_gtt.o \
......
......@@ -9,7 +9,6 @@
#include "gem/i915_gem_context.h"
#include "gem/i915_gem_object.h"
#include "i915_active.h"
#include "i915_buddy.h"
#include "i915_params.h"
#include "i915_pci.h"
#include "i915_perf.h"
......@@ -50,8 +49,6 @@ static const struct {
{ .init = i915_check_nomodeset },
{ .init = i915_active_module_init,
.exit = i915_active_module_exit },
{ .init = i915_buddy_module_init,
.exit = i915_buddy_module_exit },
{ .init = i915_context_module_init,
.exit = i915_context_module_exit },
{ .init = i915_gem_context_module_init,
......
......@@ -5,10 +5,9 @@
*/
#include "i915_scatterlist.h"
#include "i915_buddy.h"
#include "i915_ttm_buddy_manager.h"
#include <drm/drm_buddy.h>
#include <drm/drm_mm.h>
#include <linux/slab.h>
......@@ -153,9 +152,9 @@ struct i915_refct_sgt *i915_rsgt_from_buddy_resource(struct ttm_resource *res,
struct i915_ttm_buddy_resource *bman_res = to_ttm_buddy_resource(res);
const u64 size = res->num_pages << PAGE_SHIFT;
const u64 max_segment = rounddown(UINT_MAX, PAGE_SIZE);
struct i915_buddy_mm *mm = bman_res->mm;
struct drm_buddy *mm = bman_res->mm;
struct list_head *blocks = &bman_res->blocks;
struct i915_buddy_block *block;
struct drm_buddy_block *block;
struct i915_refct_sgt *rsgt;
struct scatterlist *sg;
struct sg_table *st;
......@@ -181,8 +180,8 @@ struct i915_refct_sgt *i915_rsgt_from_buddy_resource(struct ttm_resource *res,
list_for_each_entry(block, blocks, link) {
u64 block_size, offset;
block_size = min_t(u64, size, i915_buddy_block_size(mm, block));
offset = i915_buddy_block_offset(block);
block_size = min_t(u64, size, drm_buddy_block_size(mm, block));
offset = drm_buddy_block_offset(block);
while (block_size) {
u64 len;
......
......@@ -8,14 +8,15 @@
#include <drm/ttm/ttm_bo_driver.h>
#include <drm/ttm/ttm_placement.h>
#include <drm/drm_buddy.h>
#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 drm_buddy mm;
struct list_head reserved;
struct mutex lock;
u64 default_page_size;
......@@ -34,7 +35,7 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man,
{
struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
struct i915_ttm_buddy_resource *bman_res;
struct i915_buddy_mm *mm = &bman->mm;
struct drm_buddy *mm = &bman->mm;
unsigned long n_pages;
unsigned int min_order;
u64 min_page_size;
......@@ -73,7 +74,7 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man,
n_pages = size >> ilog2(mm->chunk_size);
do {
struct i915_buddy_block *block;
struct drm_buddy_block *block;
unsigned int order;
order = fls(n_pages) - 1;
......@@ -82,7 +83,7 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man,
do {
mutex_lock(&bman->lock);
block = i915_buddy_alloc(mm, order);
block = drm_buddy_alloc_blocks(mm, order);
mutex_unlock(&bman->lock);
if (!IS_ERR(block))
break;
......@@ -106,7 +107,7 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man,
err_free_blocks:
mutex_lock(&bman->lock);
i915_buddy_free_list(mm, &bman_res->blocks);
drm_buddy_free_list(mm, &bman_res->blocks);
mutex_unlock(&bman->lock);
err_free_res:
kfree(bman_res);
......@@ -120,7 +121,7 @@ static void i915_ttm_buddy_man_free(struct ttm_resource_manager *man,
struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
mutex_lock(&bman->lock);
i915_buddy_free_list(&bman->mm, &bman_res->blocks);
drm_buddy_free_list(&bman->mm, &bman_res->blocks);
mutex_unlock(&bman->lock);
kfree(bman_res);
......@@ -130,17 +131,17 @@ 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;
struct drm_buddy_block *block;
mutex_lock(&bman->lock);
drm_printf(printer, "default_page_size: %lluKiB\n",
bman->default_page_size >> 10);
i915_buddy_print(&bman->mm, printer);
drm_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);
drm_buddy_block_print(&bman->mm, block, printer);
mutex_unlock(&bman->lock);
}
......@@ -190,7 +191,7 @@ int i915_ttm_buddy_man_init(struct ttm_device *bdev,
if (!bman)
return -ENOMEM;
err = i915_buddy_init(&bman->mm, size, chunk_size);
err = drm_buddy_init(&bman->mm, size, chunk_size);
if (err)
goto err_free_bman;
......@@ -228,7 +229,7 @@ int i915_ttm_buddy_man_fini(struct ttm_device *bdev, unsigned int type)
{
struct ttm_resource_manager *man = ttm_manager_type(bdev, type);
struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
struct i915_buddy_mm *mm = &bman->mm;
struct drm_buddy *mm = &bman->mm;
int ret;
ttm_resource_manager_set_used(man, false);
......@@ -240,8 +241,8 @@ int i915_ttm_buddy_man_fini(struct ttm_device *bdev, unsigned int type)
ttm_set_driver_manager(bdev, type, NULL);
mutex_lock(&bman->lock);
i915_buddy_free_list(mm, &bman->reserved);
i915_buddy_fini(mm);
drm_buddy_free_list(mm, &bman->reserved);
drm_buddy_fini(mm);
mutex_unlock(&bman->lock);
ttm_resource_manager_cleanup(man);
......@@ -264,11 +265,11 @@ int i915_ttm_buddy_man_reserve(struct ttm_resource_manager *man,
u64 start, u64 size)
{
struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
struct i915_buddy_mm *mm = &bman->mm;
struct drm_buddy *mm = &bman->mm;
int ret;
mutex_lock(&bman->lock);
ret = i915_buddy_alloc_range(mm, &bman->reserved, start, size);
ret = drm_buddy_alloc_range(mm, &bman->reserved, start, size);
mutex_unlock(&bman->lock);
return ret;
......
......@@ -13,7 +13,7 @@
struct ttm_device;
struct ttm_resource_manager;
struct i915_buddy_mm;
struct drm_buddy;
/**
* struct i915_ttm_buddy_resource
......@@ -28,7 +28,7 @@ struct i915_buddy_mm;
struct i915_ttm_buddy_resource {
struct ttm_resource base;
struct list_head blocks;
struct i915_buddy_mm *mm;
struct drm_buddy *mm;
};
/**
......
This diff is collapsed.
......@@ -33,4 +33,3 @@ selftest(evict, i915_gem_evict_mock_selftests)
selftest(gtt, i915_gem_gtt_mock_selftests)
selftest(hugepages, i915_gem_huge_page_mock_selftests)
selftest(memory_region, intel_memory_region_mock_selftests)
selftest(buddy, i915_buddy_mock_selftests)
......@@ -6,6 +6,8 @@
#include <linux/prime_numbers.h>
#include <linux/sort.h>
#include <drm/drm_buddy.h>
#include "../i915_selftest.h"
#include "mock_drm.h"
......@@ -20,7 +22,6 @@
#include "gt/intel_engine_pm.h"
#include "gt/intel_engine_user.h"
#include "gt/intel_gt.h"
#include "i915_buddy.h"
#include "gt/intel_migrate.h"
#include "i915_memcpy.h"
#include "i915_ttm_buddy_manager.h"
......@@ -369,7 +370,7 @@ static int igt_mock_splintered_region(void *arg)
struct drm_i915_private *i915 = mem->i915;
struct i915_ttm_buddy_resource *res;
struct drm_i915_gem_object *obj;
struct i915_buddy_mm *mm;
struct drm_buddy *mm;
unsigned int expected_order;
LIST_HEAD(objects);
u64 size;
......@@ -454,8 +455,8 @@ static int igt_mock_max_segment(void *arg)
struct drm_i915_private *i915 = mem->i915;
struct i915_ttm_buddy_resource *res;
struct drm_i915_gem_object *obj;
struct i915_buddy_block *block;
struct i915_buddy_mm *mm;
struct drm_buddy_block *block;
struct drm_buddy *mm;
struct list_head *blocks;
struct scatterlist *sg;
LIST_HEAD(objects);
......@@ -485,8 +486,8 @@ static int igt_mock_max_segment(void *arg)
mm = res->mm;
size = 0;
list_for_each_entry(block, blocks, link) {
if (i915_buddy_block_size(mm, block) > size)
size = i915_buddy_block_size(mm, block);
if (drm_buddy_block_size(mm, block) > size)
size = drm_buddy_block_size(mm, block);
}
if (size < max_segment) {
pr_err("%s: Failed to create a huge contiguous block [> %u], largest block %lld\n",
......
......@@ -3,52 +3,62 @@
* Copyright © 2021 Intel Corporation
*/
#ifndef __I915_BUDDY_H__
#define __I915_BUDDY_H__
#ifndef __DRM_BUDDY_H__
#define __DRM_BUDDY_H__
#include <linux/bitops.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/sched.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)
#define I915_BUDDY_ALLOCATED (1 << 10)
#define I915_BUDDY_FREE (2 << 10)
#define I915_BUDDY_SPLIT (3 << 10)
#define range_overflows(start, size, max) ({ \
typeof(start) start__ = (start); \
typeof(size) size__ = (size); \
typeof(max) max__ = (max); \
(void)(&start__ == &size__); \
(void)(&start__ == &max__); \
start__ >= max__ || size__ > max__ - start__; \
})
struct drm_buddy_block {
#define DRM_BUDDY_HEADER_OFFSET GENMASK_ULL(63, 12)
#define DRM_BUDDY_HEADER_STATE GENMASK_ULL(11, 10)
#define DRM_BUDDY_ALLOCATED (1 << 10)
#define DRM_BUDDY_FREE (2 << 10)
#define DRM_BUDDY_SPLIT (3 << 10)
/* Free to be used, if needed in the future */
#define I915_BUDDY_HEADER_UNUSED GENMASK_ULL(9, 6)
#define I915_BUDDY_HEADER_ORDER GENMASK_ULL(5, 0)
#define DRM_BUDDY_HEADER_UNUSED GENMASK_ULL(9, 6)
#define DRM_BUDDY_HEADER_ORDER GENMASK_ULL(5, 0)
u64 header;
struct i915_buddy_block *left;
struct i915_buddy_block *right;
struct i915_buddy_block *parent;
struct drm_buddy_block *left;
struct drm_buddy_block *right;
struct drm_buddy_block *parent;
void *private; /* owned by creator */
/*
* While the block is allocated by the user through i915_buddy_alloc*,
* While the block is allocated by the user through drm_buddy_alloc*,
* the user has ownership of the link, for example to maintain within
* a list, if so desired. As soon as the block is freed with
* i915_buddy_free* ownership is given back to the mm.
* drm_buddy_free* ownership is given back to the mm.
*/
struct list_head link;
struct list_head tmp_link;
};
/* Order-zero must be at least PAGE_SIZE */
#define I915_BUDDY_MAX_ORDER (63 - PAGE_SHIFT)
#define DRM_BUDDY_MAX_ORDER (63 - PAGE_SHIFT)
/*
* Binary Buddy System.
*
* Locking should be handled by the user, a simple mutex around
* i915_buddy_alloc* and i915_buddy_free* should suffice.
* drm_buddy_alloc* and drm_buddy_free* should suffice.
*/
struct i915_buddy_mm {
struct drm_buddy {
/* Maintain a free list for each order. */
struct list_head *free_list;
......@@ -59,7 +69,7 @@ struct i915_buddy_mm {
* block. Nodes are either allocated or free, in which case they will
* also exist on the respective free list.
*/
struct i915_buddy_block **roots;
struct drm_buddy_block **roots;
/*
* Anything from here is public, and remains static for the lifetime of
......@@ -75,69 +85,66 @@ struct i915_buddy_mm {
};
static inline u64
i915_buddy_block_offset(struct i915_buddy_block *block)
drm_buddy_block_offset(struct drm_buddy_block *block)
{
return block->header & I915_BUDDY_HEADER_OFFSET;
return block->header & DRM_BUDDY_HEADER_OFFSET;
}
static inline unsigned int
i915_buddy_block_order(struct i915_buddy_block *block)
drm_buddy_block_order(struct drm_buddy_block *block)
{
return block->header & I915_BUDDY_HEADER_ORDER;
return block->header & DRM_BUDDY_HEADER_ORDER;
}
static inline unsigned int
i915_buddy_block_state(struct i915_buddy_block *block)
drm_buddy_block_state(struct drm_buddy_block *block)
{
return block->header & I915_BUDDY_HEADER_STATE;
return block->header & DRM_BUDDY_HEADER_STATE;
}
static inline bool
i915_buddy_block_is_allocated(struct i915_buddy_block *block)
drm_buddy_block_is_allocated(struct drm_buddy_block *block)
{
return i915_buddy_block_state(block) == I915_BUDDY_ALLOCATED;
return drm_buddy_block_state(block) == DRM_BUDDY_ALLOCATED;
}
static inline bool
i915_buddy_block_is_free(struct i915_buddy_block *block)
drm_buddy_block_is_free(struct drm_buddy_block *block)
{
return i915_buddy_block_state(block) == I915_BUDDY_FREE;
return drm_buddy_block_state(block) == DRM_BUDDY_FREE;
}
static inline bool
i915_buddy_block_is_split(struct i915_buddy_block *block)
drm_buddy_block_is_split(struct drm_buddy_block *block)
{
return i915_buddy_block_state(block) == I915_BUDDY_SPLIT;
return drm_buddy_block_state(block) == DRM_BUDDY_SPLIT;
}
static inline u64
i915_buddy_block_size(struct i915_buddy_mm *mm,
struct i915_buddy_block *block)
drm_buddy_block_size(struct drm_buddy *mm,
struct drm_buddy_block *block)
{
return mm->chunk_size << i915_buddy_block_order(block);
return mm->chunk_size << drm_buddy_block_order(block);
}
int i915_buddy_init(struct i915_buddy_mm *mm, u64 size, u64 chunk_size);
int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 chunk_size);
void i915_buddy_fini(struct i915_buddy_mm *mm);
void drm_buddy_fini(struct drm_buddy *mm);
struct i915_buddy_block *
i915_buddy_alloc(struct i915_buddy_mm *mm, unsigned int order);
struct drm_buddy_block *
drm_buddy_alloc_blocks(struct drm_buddy *mm, unsigned int order);
int i915_buddy_alloc_range(struct i915_buddy_mm *mm,
int drm_buddy_alloc_range(struct drm_buddy *mm,
struct list_head *blocks,
u64 start, u64 size);
void i915_buddy_free(struct i915_buddy_mm *mm, struct i915_buddy_block *block);
void drm_buddy_free_block(struct drm_buddy *mm, struct drm_buddy_block *block);
void i915_buddy_free_list(struct i915_buddy_mm *mm, struct list_head *objects);
void drm_buddy_free_list(struct drm_buddy *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,
void drm_buddy_print(struct drm_buddy *mm, struct drm_printer *p);
void drm_buddy_block_print(struct drm_buddy *mm,
struct drm_buddy_block *block,
struct drm_printer *p);
void i915_buddy_module_exit(void);
int i915_buddy_module_init(void);
#endif
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