// SPDX-License-Identifier: MIT
/*
* Copyright © 2024 Intel Corporation
*/
#include <linux/cleanup.h>
#include <drm/drm_managed.h>
#include "xe_assert.h"
#include "xe_bo.h"
#include "xe_gt_printk.h"
#include "xe_guc.h"
#include "xe_guc_buf.h"
#include "xe_sa.h"
static struct xe_guc *cache_to_guc(struct xe_guc_buf_cache *cache)
{
return container_of(cache, struct xe_guc, buf);
}
static struct xe_gt *cache_to_gt(struct xe_guc_buf_cache *cache)
{
return guc_to_gt(cache_to_guc(cache));
}
/**
* xe_guc_buf_cache_init ( ) - Initialize the GuC Buffer Cache .
* @ cache : the & xe_guc_buf_cache to initialize
*
* The Buffer Cache allows to obtain a reusable buffer that can be used to pass
* indirect H2G data to GuC without a need to create a ad - hoc allocation .
*
* Return : 0 on success or a negative error code on failure .
*/
int xe_guc_buf_cache_init(struct xe_guc_buf_cache *cache)
{
struct xe_gt *gt = cache_to_gt(cache);
struct xe_sa_manager *sam;
sam = __xe_sa_bo_manager_init(gt_to_tile(gt), SZ_8K, 0 , sizeof (u32));
if (IS_ERR(sam))
return PTR_ERR(sam);
cache->sam = sam;
xe_gt_dbg(gt, "reusable buffer with %u dwords at %#x for %ps\n" ,
xe_guc_buf_cache_dwords(cache), xe_bo_ggtt_addr(sam->bo),
__builtin_return_address(0 ));
return 0 ;
}
/**
* xe_guc_buf_cache_dwords ( ) - Number of dwords the GuC Buffer Cache supports .
* @ cache : the & xe_guc_buf_cache to query
*
* Return : a size of the largest reusable buffer ( in dwords )
*/
u32 xe_guc_buf_cache_dwords(struct xe_guc_buf_cache *cache)
{
return cache->sam ? cache->sam->base.size / sizeof (u32) : 0 ;
}
/**
* xe_guc_buf_reserve ( ) - Reserve a new sub - allocation .
* @ cache : the & xe_guc_buf_cache where reserve sub - allocation
* @ dwords : the requested size of the buffer in dwords
*
* Use xe_guc_buf_is_valid ( ) to check if returned buffer reference is valid .
* Must use xe_guc_buf_release ( ) to release a sub - allocation .
*
* Return : a & xe_guc_buf of new sub - allocation .
*/
struct xe_guc_buf xe_guc_buf_reserve(struct xe_guc_buf_cache *cache, u32 dwords)
{
struct drm_suballoc *sa;
if (cache->sam)
sa = __xe_sa_bo_new(cache->sam, dwords * sizeof (u32), GFP_ATOMIC);
else
sa = ERR_PTR(-EOPNOTSUPP);
return (struct xe_guc_buf){ .sa = sa };
}
/**
* xe_guc_buf_from_data ( ) - Reserve a new sub - allocation using data .
* @ cache : the & xe_guc_buf_cache where reserve sub - allocation
* @ data : the data to flush the sub - allocation
* @ size : the size of the data
*
* Similar to xe_guc_buf_reserve ( ) but flushes @ data to the GPU memory .
*
* Return : a & xe_guc_buf of new sub - allocation .
*/
struct xe_guc_buf xe_guc_buf_from_data(struct xe_guc_buf_cache *cache,
const void *data, size_t size)
{
struct drm_suballoc *sa;
sa = __xe_sa_bo_new(cache->sam, size, GFP_ATOMIC);
if (!IS_ERR(sa))
memcpy(xe_sa_bo_cpu_addr(sa), data, size);
return (struct xe_guc_buf){ .sa = sa };
}
/**
* xe_guc_buf_release ( ) - Release a sub - allocation .
* @ buf : the & xe_guc_buf to release
*
* Releases a sub - allocation reserved by the xe_guc_buf_reserve ( ) .
*/
void xe_guc_buf_release(const struct xe_guc_buf buf)
{
if (xe_guc_buf_is_valid(buf))
xe_sa_bo_free(buf.sa, NULL);
}
/**
* xe_guc_buf_flush ( ) - Copy the data from the sub - allocation to the GPU memory .
* @ buf : the & xe_guc_buf to flush
*
* Return : a GPU address of the sub - allocation .
*/
u64 xe_guc_buf_flush(const struct xe_guc_buf buf)
{
xe_sa_bo_flush_write(buf.sa);
return xe_sa_bo_gpu_addr(buf.sa);
}
/**
* xe_guc_buf_cpu_ptr ( ) - Obtain a CPU pointer to the sub - allocation .
* @ buf : the & xe_guc_buf to query
*
* Return : a CPU pointer of the sub - allocation .
*/
void *xe_guc_buf_cpu_ptr(const struct xe_guc_buf buf)
{
return xe_sa_bo_cpu_addr(buf.sa);
}
/**
* xe_guc_buf_gpu_addr ( ) - Obtain a GPU address of the sub - allocation .
* @ buf : the & xe_guc_buf to query
*
* Return : a GPU address of the sub - allocation .
*/
u64 xe_guc_buf_gpu_addr(const struct xe_guc_buf buf)
{
return xe_sa_bo_gpu_addr(buf.sa);
}
/**
* xe_guc_cache_gpu_addr_from_ptr ( ) - Lookup a GPU address using the pointer .
* @ cache : the & xe_guc_buf_cache with sub - allocations
* @ ptr : the CPU pointer of the sub - allocation
* @ size : the size of the data
*
* Return : a GPU address on success or 0 if the pointer was unrelated .
*/
u64 xe_guc_cache_gpu_addr_from_ptr(struct xe_guc_buf_cache *cache, const void *ptr, u32 size)
{
ptrdiff_t offset = ptr - cache->sam->cpu_ptr;
if (offset < 0 || offset + size > cache->sam->base.size)
return 0 ;
return cache->sam->gpu_addr + offset;
}
#if IS_BUILTIN(CONFIG_DRM_XE_KUNIT_TEST)
#include "tests/xe_guc_buf_kunit.c"
#endif
Messung V0.5 in Prozent C=94 H=100 G=96
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-10-02)
¤
*© Formatika GbR, Deutschland