235 lines
5.6 KiB
C
235 lines
5.6 KiB
C
// SPDX-License-Identifier: GPL-2.0 AND MIT
|
|
/*
|
|
* Copyright © 2023 Intel Corporation
|
|
*/
|
|
#include <drm/ttm/ttm_resource.h>
|
|
#include <drm/ttm/ttm_device.h>
|
|
#include <drm/ttm/ttm_placement.h>
|
|
|
|
#include "ttm_mock_manager.h"
|
|
|
|
static inline struct ttm_mock_manager *
|
|
to_mock_mgr(struct ttm_resource_manager *man)
|
|
{
|
|
return container_of(man, struct ttm_mock_manager, man);
|
|
}
|
|
|
|
static inline struct ttm_mock_resource *
|
|
to_mock_mgr_resource(struct ttm_resource *res)
|
|
{
|
|
return container_of(res, struct ttm_mock_resource, base);
|
|
}
|
|
|
|
static int ttm_mock_manager_alloc(struct ttm_resource_manager *man,
|
|
struct ttm_buffer_object *bo,
|
|
const struct ttm_place *place,
|
|
struct ttm_resource **res)
|
|
{
|
|
struct ttm_mock_manager *manager = to_mock_mgr(man);
|
|
struct ttm_mock_resource *mock_res;
|
|
struct drm_buddy *mm = &manager->mm;
|
|
u64 lpfn, fpfn, alloc_size;
|
|
int err;
|
|
|
|
mock_res = kzalloc(sizeof(*mock_res), GFP_KERNEL);
|
|
|
|
if (!mock_res)
|
|
return -ENOMEM;
|
|
|
|
fpfn = 0;
|
|
lpfn = man->size;
|
|
|
|
ttm_resource_init(bo, place, &mock_res->base);
|
|
INIT_LIST_HEAD(&mock_res->blocks);
|
|
|
|
if (place->flags & TTM_PL_FLAG_TOPDOWN)
|
|
mock_res->flags |= DRM_BUDDY_TOPDOWN_ALLOCATION;
|
|
|
|
if (place->flags & TTM_PL_FLAG_CONTIGUOUS)
|
|
mock_res->flags |= DRM_BUDDY_CONTIGUOUS_ALLOCATION;
|
|
|
|
alloc_size = (uint64_t)mock_res->base.size;
|
|
mutex_lock(&manager->lock);
|
|
err = drm_buddy_alloc_blocks(mm, fpfn, lpfn, alloc_size,
|
|
manager->default_page_size,
|
|
&mock_res->blocks,
|
|
mock_res->flags);
|
|
|
|
if (err)
|
|
goto error_free_blocks;
|
|
mutex_unlock(&manager->lock);
|
|
|
|
*res = &mock_res->base;
|
|
return 0;
|
|
|
|
error_free_blocks:
|
|
drm_buddy_free_list(mm, &mock_res->blocks, 0);
|
|
ttm_resource_fini(man, &mock_res->base);
|
|
mutex_unlock(&manager->lock);
|
|
|
|
return err;
|
|
}
|
|
|
|
static void ttm_mock_manager_free(struct ttm_resource_manager *man,
|
|
struct ttm_resource *res)
|
|
{
|
|
struct ttm_mock_manager *manager = to_mock_mgr(man);
|
|
struct ttm_mock_resource *mock_res = to_mock_mgr_resource(res);
|
|
struct drm_buddy *mm = &manager->mm;
|
|
|
|
mutex_lock(&manager->lock);
|
|
drm_buddy_free_list(mm, &mock_res->blocks, 0);
|
|
mutex_unlock(&manager->lock);
|
|
|
|
ttm_resource_fini(man, res);
|
|
kfree(mock_res);
|
|
}
|
|
|
|
static const struct ttm_resource_manager_func ttm_mock_manager_funcs = {
|
|
.alloc = ttm_mock_manager_alloc,
|
|
.free = ttm_mock_manager_free,
|
|
};
|
|
|
|
int ttm_mock_manager_init(struct ttm_device *bdev, u32 mem_type, u32 size)
|
|
{
|
|
struct ttm_mock_manager *manager;
|
|
struct ttm_resource_manager *base;
|
|
int err;
|
|
|
|
manager = kzalloc(sizeof(*manager), GFP_KERNEL);
|
|
if (!manager)
|
|
return -ENOMEM;
|
|
|
|
mutex_init(&manager->lock);
|
|
|
|
err = drm_buddy_init(&manager->mm, size, PAGE_SIZE);
|
|
|
|
if (err) {
|
|
kfree(manager);
|
|
return err;
|
|
}
|
|
|
|
manager->default_page_size = PAGE_SIZE;
|
|
base = &manager->man;
|
|
base->func = &ttm_mock_manager_funcs;
|
|
base->use_tt = true;
|
|
|
|
ttm_resource_manager_init(base, bdev, size);
|
|
ttm_set_driver_manager(bdev, mem_type, base);
|
|
ttm_resource_manager_set_used(base, true);
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(ttm_mock_manager_init);
|
|
|
|
void ttm_mock_manager_fini(struct ttm_device *bdev, u32 mem_type)
|
|
{
|
|
struct ttm_resource_manager *man;
|
|
struct ttm_mock_manager *mock_man;
|
|
int err;
|
|
|
|
man = ttm_manager_type(bdev, mem_type);
|
|
mock_man = to_mock_mgr(man);
|
|
|
|
err = ttm_resource_manager_evict_all(bdev, man);
|
|
if (err)
|
|
return;
|
|
|
|
ttm_resource_manager_set_used(man, false);
|
|
|
|
mutex_lock(&mock_man->lock);
|
|
drm_buddy_fini(&mock_man->mm);
|
|
mutex_unlock(&mock_man->lock);
|
|
|
|
ttm_set_driver_manager(bdev, mem_type, NULL);
|
|
}
|
|
EXPORT_SYMBOL_GPL(ttm_mock_manager_fini);
|
|
|
|
static int ttm_bad_manager_alloc(struct ttm_resource_manager *man,
|
|
struct ttm_buffer_object *bo,
|
|
const struct ttm_place *place,
|
|
struct ttm_resource **res)
|
|
{
|
|
return -ENOSPC;
|
|
}
|
|
|
|
static int ttm_busy_manager_alloc(struct ttm_resource_manager *man,
|
|
struct ttm_buffer_object *bo,
|
|
const struct ttm_place *place,
|
|
struct ttm_resource **res)
|
|
{
|
|
return -EBUSY;
|
|
}
|
|
|
|
static void ttm_bad_manager_free(struct ttm_resource_manager *man,
|
|
struct ttm_resource *res)
|
|
{
|
|
}
|
|
|
|
static bool ttm_bad_manager_compatible(struct ttm_resource_manager *man,
|
|
struct ttm_resource *res,
|
|
const struct ttm_place *place,
|
|
size_t size)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
static const struct ttm_resource_manager_func ttm_bad_manager_funcs = {
|
|
.alloc = ttm_bad_manager_alloc,
|
|
.free = ttm_bad_manager_free,
|
|
.compatible = ttm_bad_manager_compatible
|
|
};
|
|
|
|
static const struct ttm_resource_manager_func ttm_bad_busy_manager_funcs = {
|
|
.alloc = ttm_busy_manager_alloc,
|
|
.free = ttm_bad_manager_free,
|
|
.compatible = ttm_bad_manager_compatible
|
|
};
|
|
|
|
int ttm_bad_manager_init(struct ttm_device *bdev, u32 mem_type, u32 size)
|
|
{
|
|
struct ttm_resource_manager *man;
|
|
|
|
man = kzalloc(sizeof(*man), GFP_KERNEL);
|
|
if (!man)
|
|
return -ENOMEM;
|
|
|
|
man->func = &ttm_bad_manager_funcs;
|
|
|
|
ttm_resource_manager_init(man, bdev, size);
|
|
ttm_set_driver_manager(bdev, mem_type, man);
|
|
ttm_resource_manager_set_used(man, true);
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(ttm_bad_manager_init);
|
|
|
|
int ttm_busy_manager_init(struct ttm_device *bdev, u32 mem_type, u32 size)
|
|
{
|
|
struct ttm_resource_manager *man;
|
|
|
|
ttm_bad_manager_init(bdev, mem_type, size);
|
|
man = ttm_manager_type(bdev, mem_type);
|
|
|
|
man->func = &ttm_bad_busy_manager_funcs;
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(ttm_busy_manager_init);
|
|
|
|
void ttm_bad_manager_fini(struct ttm_device *bdev, uint32_t mem_type)
|
|
{
|
|
struct ttm_resource_manager *man;
|
|
|
|
man = ttm_manager_type(bdev, mem_type);
|
|
|
|
ttm_resource_manager_set_used(man, false);
|
|
ttm_set_driver_manager(bdev, mem_type, NULL);
|
|
|
|
kfree(man);
|
|
}
|
|
EXPORT_SYMBOL_GPL(ttm_bad_manager_fini);
|
|
|
|
MODULE_DESCRIPTION("KUnit tests for ttm with mock resource managers");
|
|
MODULE_LICENSE("GPL and additional rights");
|