File Index
Files and directories
Sign in
FILE

xe_guc_buf.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/xe/xe_guc_buf.c C
  1// SPDX-License-Identifier: MIT
  2/*
  3 * Copyright © 2024 Intel Corporation
  4 */
  5
  6#include <linux/cleanup.h>
  7#include <drm/drm_managed.h>
  8
  9#include "xe_assert.h"
 10#include "xe_bo.h"
 11#include "xe_gt_printk.h"
 12#include "xe_guc.h"
 13#include "xe_guc_buf.h"
 14#include "xe_sa.h"
 15
 16#define XE_GUC_BUF_CACHE_DEFAULT_SIZE SZ_8K
 17
 18static struct xe_guc *cache_to_guc(struct xe_guc_buf_cache *cache)
 19{
 20	return container_of(cache, struct xe_guc, buf);
 21}
 22
 23static struct xe_gt *cache_to_gt(struct xe_guc_buf_cache *cache)
 24{
 25	return guc_to_gt(cache_to_guc(cache));
 26}
 27
 28static int guc_buf_cache_init(struct xe_guc_buf_cache *cache, u32 size)
 29{
 30	struct xe_gt *gt = cache_to_gt(cache);
 31	struct xe_sa_manager *sam;
 32
 33	sam = __xe_sa_bo_manager_init(gt_to_tile(gt), size, 0, sizeof(u32));
 34	if (IS_ERR(sam))
 35		return PTR_ERR(sam);
 36	cache->sam = sam;
 37
 38	xe_gt_dbg(gt, "reusable buffer with %u dwords at %#x for %ps\n",
 39		  xe_guc_buf_cache_dwords(cache), xe_bo_ggtt_addr(sam->bo),
 40		  __builtin_return_address(0));
 41	return 0;
 42}
 43
 44/**
 45 * xe_guc_buf_cache_init() - Initialize the GuC Buffer Cache.
 46 * @cache: the &xe_guc_buf_cache to initialize
 47 *
 48 * The Buffer Cache allows to obtain a reusable buffer that can be used to pass
 49 * data to GuC or read data from GuC without a need to create a ad-hoc allocation.
 50 *
 51 * Return: 0 on success or a negative error code on failure.
 52 */
 53int xe_guc_buf_cache_init(struct xe_guc_buf_cache *cache)
 54{
 55	return guc_buf_cache_init(cache, XE_GUC_BUF_CACHE_DEFAULT_SIZE);
 56}
 57
 58/**
 59 * xe_guc_buf_cache_init_with_size() - Initialize the GuC Buffer Cache.
 60 * @cache: the &xe_guc_buf_cache to initialize
 61 * @size: size in bytes
 62 *
 63 * Like xe_guc_buf_cache_init(), except it allows the caller to make the cache
 64 * buffer larger, allowing to accommodate larger objects.
 65 *
 66 * Return: 0 on success or a negative error code on failure.
 67 */
 68int xe_guc_buf_cache_init_with_size(struct xe_guc_buf_cache *cache, u32 size)
 69{
 70	return guc_buf_cache_init(cache, max(XE_GUC_BUF_CACHE_DEFAULT_SIZE, size));
 71}
 72
 73/**
 74 * xe_guc_buf_cache_dwords() - Number of dwords the GuC Buffer Cache supports.
 75 * @cache: the &xe_guc_buf_cache to query
 76 *
 77 * Return: a size of the largest reusable buffer (in dwords)
 78 */
 79u32 xe_guc_buf_cache_dwords(struct xe_guc_buf_cache *cache)
 80{
 81	return cache->sam ? cache->sam->base.size / sizeof(u32) : 0;
 82}
 83
 84/**
 85 * xe_guc_buf_reserve() - Reserve a new sub-allocation.
 86 * @cache: the &xe_guc_buf_cache where reserve sub-allocation
 87 * @dwords: the requested size of the buffer in dwords
 88 *
 89 * Use xe_guc_buf_is_valid() to check if returned buffer reference is valid.
 90 * Must use xe_guc_buf_release() to release a sub-allocation.
 91 *
 92 * Return: a &xe_guc_buf of new sub-allocation.
 93 */
 94struct xe_guc_buf xe_guc_buf_reserve(struct xe_guc_buf_cache *cache, u32 dwords)
 95{
 96	struct drm_suballoc *sa;
 97
 98	if (cache->sam)
 99		sa = __xe_sa_bo_new(cache->sam, dwords * sizeof(u32), GFP_ATOMIC);
100	else
101		sa = ERR_PTR(-EOPNOTSUPP);
102
103	return (struct xe_guc_buf){ .sa = sa };
104}
105
106/**
107 * xe_guc_buf_from_data() - Reserve a new sub-allocation using data.
108 * @cache: the &xe_guc_buf_cache where reserve sub-allocation
109 * @data: the data to flush the sub-allocation
110 * @size: the size of the data
111 *
112 * Similar to xe_guc_buf_reserve() but flushes @data to the GPU memory.
113 *
114 * Return: a &xe_guc_buf of new sub-allocation.
115 */
116struct xe_guc_buf xe_guc_buf_from_data(struct xe_guc_buf_cache *cache,
117				       const void *data, size_t size)
118{
119	struct drm_suballoc *sa;
120
121	sa = __xe_sa_bo_new(cache->sam, size, GFP_ATOMIC);
122	if (!IS_ERR(sa))
123		memcpy(xe_sa_bo_cpu_addr(sa), data, size);
124
125	return (struct xe_guc_buf){ .sa = sa };
126}
127
128/**
129 * xe_guc_buf_release() - Release a sub-allocation.
130 * @buf: the &xe_guc_buf to release
131 *
132 * Releases a sub-allocation reserved by the xe_guc_buf_reserve().
133 */
134void xe_guc_buf_release(const struct xe_guc_buf buf)
135{
136	if (xe_guc_buf_is_valid(buf))
137		xe_sa_bo_free(buf.sa, NULL);
138}
139
140/**
141 * xe_guc_buf_sync_read() - Copy the data from the GPU memory to the sub-allocation.
142 * @buf: the &xe_guc_buf to sync
143 *
144 * Return: a CPU pointer of the sub-allocation.
145 */
146void *xe_guc_buf_sync_read(const struct xe_guc_buf buf)
147{
148	xe_sa_bo_sync_read(buf.sa);
149
150	return xe_sa_bo_cpu_addr(buf.sa);
151}
152
153/**
154 * xe_guc_buf_flush() - Copy the data from the sub-allocation to the GPU memory.
155 * @buf: the &xe_guc_buf to flush
156 *
157 * Return: a GPU address of the sub-allocation.
158 */
159u64 xe_guc_buf_flush(const struct xe_guc_buf buf)
160{
161	xe_sa_bo_flush_write(buf.sa);
162	return xe_sa_bo_gpu_addr(buf.sa);
163}
164
165/**
166 * xe_guc_buf_cpu_ptr() - Obtain a CPU pointer to the sub-allocation.
167 * @buf: the &xe_guc_buf to query
168 *
169 * Return: a CPU pointer of the sub-allocation.
170 */
171void *xe_guc_buf_cpu_ptr(const struct xe_guc_buf buf)
172{
173	return xe_sa_bo_cpu_addr(buf.sa);
174}
175
176/**
177 * xe_guc_buf_gpu_addr() - Obtain a GPU address of the sub-allocation.
178 * @buf: the &xe_guc_buf to query
179 *
180 * Return: a GPU address of the sub-allocation.
181 */
182u64 xe_guc_buf_gpu_addr(const struct xe_guc_buf buf)
183{
184	return xe_sa_bo_gpu_addr(buf.sa);
185}
186
187/**
188 * xe_guc_cache_gpu_addr_from_ptr() - Lookup a GPU address using the pointer.
189 * @cache: the &xe_guc_buf_cache with sub-allocations
190 * @ptr: the CPU pointer of the sub-allocation
191 * @size: the size of the data
192 *
193 * Return: a GPU address on success or 0 if the pointer was unrelated.
194 */
195u64 xe_guc_cache_gpu_addr_from_ptr(struct xe_guc_buf_cache *cache, const void *ptr, u32 size)
196{
197	ptrdiff_t offset = ptr - cache->sam->cpu_ptr;
198
199	if (offset < 0 || offset + size > cache->sam->base.size)
200		return 0;
201
202	return xe_sa_manager_gpu_addr(cache->sam) + offset;
203}
204
205#if IS_BUILTIN(CONFIG_DRM_XE_KUNIT_TEST)
206#include "tests/xe_guc_buf_kunit.c"
207#endif
~/ Read-only file preview.