mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
drm/xe: Add initial support for separate kernel VRAM region on the tile
So far, kernel and userspace allocations have shared the same VRAM region. However, in some scenarios, it may be necessary to reserve a separate VRAM area exclusively for kernel allocations. Let's add preliminary support for such a configuration. v2: - replaced for_each_bo_flag_vram with the improved for_each_set_bo_vram_flag helper (Matthew) - moved the VRAM flag iteration macro definition into xe_bo.c (Matthew) - drop unused bo_flgas from bo_vram_flags_to_vram_placement (Matthew) - use hweight32 helper in __xe_bo_fixed_placement for readability (Matthew) v3: remove unnecessary VRAM fixup id Signed-off-by: Piotr Piórkowski <piotr.piorkowski@intel.com> Cc: Matthew Auld <matthew.auld@intel.com> Reviewed-by: Matthew Auld <matthew.auld@intel.com> Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com> Link: https://lore.kernel.org/r/20251003162619.1984236-2-piotr.piorkowski@intel.com
This commit is contained in:
committed by
Michal Wajdeczko
parent
bdc2fb17ae
commit
db7dde9904
@@ -34,6 +34,7 @@
|
||||
#include "xe_res_cursor.h"
|
||||
#include "xe_shrinker.h"
|
||||
#include "xe_sriov_vf_ccs.h"
|
||||
#include "xe_tile.h"
|
||||
#include "xe_trace_bo.h"
|
||||
#include "xe_ttm_stolen_mgr.h"
|
||||
#include "xe_vm.h"
|
||||
@@ -81,6 +82,10 @@ static struct ttm_placement tt_placement = {
|
||||
.placement = tt_placement_flags,
|
||||
};
|
||||
|
||||
#define for_each_set_bo_vram_flag(bit__, bo_flags__) \
|
||||
for (unsigned int __bit_tmp = BIT(0); __bit_tmp <= XE_BO_FLAG_VRAM_MASK; __bit_tmp <<= 1) \
|
||||
for_each_if(((bit__) = __bit_tmp) & (bo_flags__) & XE_BO_FLAG_VRAM_MASK)
|
||||
|
||||
bool mem_type_is_vram(u32 mem_type)
|
||||
{
|
||||
return mem_type >= XE_PL_VRAM0 && mem_type != XE_PL_STOLEN;
|
||||
@@ -213,6 +218,27 @@ static bool force_contiguous(u32 bo_flags)
|
||||
bo_flags & XE_BO_FLAG_PINNED;
|
||||
}
|
||||
|
||||
static u8 vram_bo_flag_to_tile_id(struct xe_device *xe, u32 vram_bo_flag)
|
||||
{
|
||||
xe_assert(xe, vram_bo_flag & XE_BO_FLAG_VRAM_MASK);
|
||||
xe_assert(xe, (vram_bo_flag & (vram_bo_flag - 1)) == 0);
|
||||
|
||||
return __ffs(vram_bo_flag >> (__ffs(XE_BO_FLAG_VRAM0) - 1)) - 1;
|
||||
}
|
||||
|
||||
static u32 bo_vram_flags_to_vram_placement(struct xe_device *xe, u32 vram_flag,
|
||||
enum ttm_bo_type type)
|
||||
{
|
||||
u8 tile_id = vram_bo_flag_to_tile_id(xe, vram_flag);
|
||||
|
||||
xe_assert(xe, tile_id < xe->info.tile_count);
|
||||
|
||||
if (type == ttm_bo_type_kernel)
|
||||
return xe->tiles[tile_id].mem.kernel_vram->placement;
|
||||
else
|
||||
return xe->tiles[tile_id].mem.vram->placement;
|
||||
}
|
||||
|
||||
static void add_vram(struct xe_device *xe, struct xe_bo *bo,
|
||||
struct ttm_place *places, u32 bo_flags, u32 mem_type, u32 *c)
|
||||
{
|
||||
@@ -245,12 +271,15 @@ static void add_vram(struct xe_device *xe, struct xe_bo *bo,
|
||||
}
|
||||
|
||||
static void try_add_vram(struct xe_device *xe, struct xe_bo *bo,
|
||||
u32 bo_flags, u32 *c)
|
||||
u32 bo_flags, enum ttm_bo_type type, u32 *c)
|
||||
{
|
||||
if (bo_flags & XE_BO_FLAG_VRAM0)
|
||||
add_vram(xe, bo, bo->placements, bo_flags, XE_PL_VRAM0, c);
|
||||
if (bo_flags & XE_BO_FLAG_VRAM1)
|
||||
add_vram(xe, bo, bo->placements, bo_flags, XE_PL_VRAM1, c);
|
||||
u32 vram_flag;
|
||||
|
||||
for_each_set_bo_vram_flag(vram_flag, bo_flags) {
|
||||
u32 pl = bo_vram_flags_to_vram_placement(xe, vram_flag, type);
|
||||
|
||||
add_vram(xe, bo, bo->placements, bo_flags, pl, c);
|
||||
}
|
||||
}
|
||||
|
||||
static void try_add_stolen(struct xe_device *xe, struct xe_bo *bo,
|
||||
@@ -269,11 +298,11 @@ static void try_add_stolen(struct xe_device *xe, struct xe_bo *bo,
|
||||
}
|
||||
|
||||
static int __xe_bo_placement_for_flags(struct xe_device *xe, struct xe_bo *bo,
|
||||
u32 bo_flags)
|
||||
u32 bo_flags, enum ttm_bo_type type)
|
||||
{
|
||||
u32 c = 0;
|
||||
|
||||
try_add_vram(xe, bo, bo_flags, &c);
|
||||
try_add_vram(xe, bo, bo_flags, type, &c);
|
||||
try_add_system(xe, bo, bo_flags, &c);
|
||||
try_add_stolen(xe, bo, bo_flags, &c);
|
||||
|
||||
@@ -289,10 +318,10 @@ static int __xe_bo_placement_for_flags(struct xe_device *xe, struct xe_bo *bo,
|
||||
}
|
||||
|
||||
int xe_bo_placement_for_flags(struct xe_device *xe, struct xe_bo *bo,
|
||||
u32 bo_flags)
|
||||
u32 bo_flags, enum ttm_bo_type type)
|
||||
{
|
||||
xe_bo_assert_held(bo);
|
||||
return __xe_bo_placement_for_flags(xe, bo, bo_flags);
|
||||
return __xe_bo_placement_for_flags(xe, bo, bo_flags, type);
|
||||
}
|
||||
|
||||
static void xe_evict_flags(struct ttm_buffer_object *tbo,
|
||||
@@ -2164,7 +2193,7 @@ struct xe_bo *xe_bo_init_locked(struct xe_device *xe, struct xe_bo *bo,
|
||||
|
||||
xe_validation_assert_exec(xe, exec, &bo->ttm.base);
|
||||
if (!(flags & XE_BO_FLAG_FIXED_PLACEMENT)) {
|
||||
err = __xe_bo_placement_for_flags(xe, bo, bo->flags);
|
||||
err = __xe_bo_placement_for_flags(xe, bo, bo->flags, type);
|
||||
if (WARN_ON(err)) {
|
||||
xe_ttm_bo_destroy(&bo->ttm);
|
||||
return ERR_PTR(err);
|
||||
@@ -2222,34 +2251,31 @@ struct xe_bo *xe_bo_init_locked(struct xe_device *xe, struct xe_bo *bo,
|
||||
}
|
||||
|
||||
static int __xe_bo_fixed_placement(struct xe_device *xe,
|
||||
struct xe_bo *bo,
|
||||
struct xe_bo *bo, enum ttm_bo_type type,
|
||||
u32 flags,
|
||||
u64 start, u64 end, u64 size)
|
||||
{
|
||||
struct ttm_place *place = bo->placements;
|
||||
u32 vram_flag, vram_stolen_flags;
|
||||
|
||||
if (flags & (XE_BO_FLAG_USER | XE_BO_FLAG_SYSTEM))
|
||||
return -EINVAL;
|
||||
|
||||
vram_flag = flags & XE_BO_FLAG_VRAM_MASK;
|
||||
vram_stolen_flags = (flags & (XE_BO_FLAG_STOLEN)) | vram_flag;
|
||||
|
||||
/* check if more than one VRAM/STOLEN flag is set */
|
||||
if (hweight32(vram_stolen_flags) > 1)
|
||||
return -EINVAL;
|
||||
|
||||
place->flags = TTM_PL_FLAG_CONTIGUOUS;
|
||||
place->fpfn = start >> PAGE_SHIFT;
|
||||
place->lpfn = end >> PAGE_SHIFT;
|
||||
|
||||
switch (flags & (XE_BO_FLAG_STOLEN | XE_BO_FLAG_VRAM_MASK)) {
|
||||
case XE_BO_FLAG_VRAM0:
|
||||
place->mem_type = XE_PL_VRAM0;
|
||||
break;
|
||||
case XE_BO_FLAG_VRAM1:
|
||||
place->mem_type = XE_PL_VRAM1;
|
||||
break;
|
||||
case XE_BO_FLAG_STOLEN:
|
||||
if (flags & XE_BO_FLAG_STOLEN)
|
||||
place->mem_type = XE_PL_STOLEN;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* 0 or multiple of the above set */
|
||||
return -EINVAL;
|
||||
}
|
||||
else
|
||||
place->mem_type = bo_vram_flags_to_vram_placement(xe, vram_flag, type);
|
||||
|
||||
bo->placement = (struct ttm_placement) {
|
||||
.num_placement = 1,
|
||||
@@ -2278,7 +2304,7 @@ __xe_bo_create_locked(struct xe_device *xe,
|
||||
return bo;
|
||||
|
||||
flags |= XE_BO_FLAG_FIXED_PLACEMENT;
|
||||
err = __xe_bo_fixed_placement(xe, bo, flags, start, end, size);
|
||||
err = __xe_bo_fixed_placement(xe, bo, type, flags, start, end, size);
|
||||
if (err) {
|
||||
xe_bo_free(bo);
|
||||
return ERR_PTR(err);
|
||||
|
||||
@@ -122,7 +122,7 @@ struct xe_bo *xe_managed_bo_create_from_data(struct xe_device *xe, struct xe_til
|
||||
int xe_managed_bo_reinit_in_vram(struct xe_device *xe, struct xe_tile *tile, struct xe_bo **src);
|
||||
|
||||
int xe_bo_placement_for_flags(struct xe_device *xe, struct xe_bo *bo,
|
||||
u32 bo_flags);
|
||||
u32 bo_flags, enum ttm_bo_type type);
|
||||
|
||||
static inline struct xe_bo *ttm_to_xe_bo(const struct ttm_buffer_object *bo)
|
||||
{
|
||||
|
||||
@@ -158,7 +158,15 @@ struct xe_tile {
|
||||
/** @mem: memory management info for tile */
|
||||
struct {
|
||||
/**
|
||||
* @mem.vram: VRAM info for tile.
|
||||
* @mem.kernel_vram: kernel-dedicated VRAM info for tile.
|
||||
*
|
||||
* Although VRAM is associated with a specific tile, it can
|
||||
* still be accessed by all tiles' GTs.
|
||||
*/
|
||||
struct xe_vram_region *kernel_vram;
|
||||
|
||||
/**
|
||||
* @mem.vram: general purpose VRAM info for tile.
|
||||
*
|
||||
* Although VRAM is associated with a specific tile, it can
|
||||
* still be accessed by all tiles' GTs.
|
||||
|
||||
@@ -124,6 +124,14 @@ int xe_tile_alloc_vram(struct xe_tile *tile)
|
||||
return -ENOMEM;
|
||||
tile->mem.vram = vram;
|
||||
|
||||
/*
|
||||
* If the kernel_vram is not already allocated,
|
||||
* it means that tile has common VRAM region for
|
||||
* kernel and user space.
|
||||
*/
|
||||
if (!tile->mem.kernel_vram)
|
||||
tile->mem.kernel_vram = tile->mem.vram;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "regs/xe_gt_regs.h"
|
||||
#include "regs/xe_regs.h"
|
||||
#include "xe_assert.h"
|
||||
#include "xe_bo.h"
|
||||
#include "xe_device.h"
|
||||
#include "xe_force_wake.h"
|
||||
#include "xe_gt_mcr.h"
|
||||
@@ -283,8 +284,11 @@ static void vram_fini(void *arg)
|
||||
|
||||
xe->mem.vram->mapping = NULL;
|
||||
|
||||
for_each_tile(tile, xe, id)
|
||||
for_each_tile(tile, xe, id) {
|
||||
tile->mem.vram->mapping = NULL;
|
||||
if (tile->mem.kernel_vram)
|
||||
tile->mem.kernel_vram->mapping = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct xe_vram_region *xe_vram_region_alloc(struct xe_device *xe, u8 id, u32 placement)
|
||||
|
||||
Reference in New Issue
Block a user