From: Michal Wajdeczko <michal.wajdeczko@intel.com>
To: intel-xe@lists.freedesktop.org
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>,
Matthew Brost <matthew.brost@intel.com>,
Rodrigo Vivi <rodrigo.vivi@intel.com>
Subject: [PATCH 10/13] drm/xe/guc: Introduce the GuC Buffer Cache
Date: Thu, 12 Dec 2024 02:01:38 +0100 [thread overview]
Message-ID: <20241212010141.389-11-michal.wajdeczko@intel.com> (raw)
In-Reply-To: <20241212010141.389-1-michal.wajdeczko@intel.com>
The purpose of the GuC Buffer Cache is to maintain a set ofreusable
buffers that could be used while sending some of the CTB H2G actions
that require separate buffer with indirect data. Currently only few
PF actions need this so initialize it only when running as a PF.
Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
---
v2: base it on xe_sa_manager instead (Matt, Rodrigo)
---
drivers/gpu/drm/xe/Makefile | 1 +
drivers/gpu/drm/xe/xe_guc.c | 5 +
drivers/gpu/drm/xe/xe_guc_buf.c | 172 ++++++++++++++++++++++++++
drivers/gpu/drm/xe/xe_guc_buf.h | 47 +++++++
drivers/gpu/drm/xe/xe_guc_buf_types.h | 28 +++++
drivers/gpu/drm/xe/xe_guc_types.h | 3 +
6 files changed, 256 insertions(+)
create mode 100644 drivers/gpu/drm/xe/xe_guc_buf.c
create mode 100644 drivers/gpu/drm/xe/xe_guc_buf.h
create mode 100644 drivers/gpu/drm/xe/xe_guc_buf_types.h
diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index 7730e0596299..2e50a697f549 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -56,6 +56,7 @@ xe-y += xe_bb.o \
xe_gt_topology.o \
xe_guc.o \
xe_guc_ads.o \
+ xe_guc_buf.o \
xe_guc_capture.o \
xe_guc_ct.o \
xe_guc_db_mgr.o \
diff --git a/drivers/gpu/drm/xe/xe_guc.c b/drivers/gpu/drm/xe/xe_guc.c
index 4e2868efb620..af62586f3528 100644
--- a/drivers/gpu/drm/xe/xe_guc.c
+++ b/drivers/gpu/drm/xe/xe_guc.c
@@ -23,6 +23,7 @@
#include "xe_gt_sriov_vf.h"
#include "xe_gt_throttle.h"
#include "xe_guc_ads.h"
+#include "xe_guc_buf.h"
#include "xe_guc_capture.h"
#include "xe_guc_ct.h"
#include "xe_guc_db_mgr.h"
@@ -654,6 +655,10 @@ int xe_guc_init(struct xe_guc *guc)
if (ret)
goto out;
+ ret = xe_guc_buf_cache_init(&guc->buf);
+ if (ret)
+ goto out;
+
xe_uc_fw_change_status(&guc->fw, XE_UC_FIRMWARE_LOADABLE);
ret = devm_add_action_or_reset(xe->drm.dev, guc_fini_hw, guc);
diff --git a/drivers/gpu/drm/xe/xe_guc_buf.c b/drivers/gpu/drm/xe/xe_guc_buf.c
new file mode 100644
index 000000000000..261c7c74417f
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_guc_buf.c
@@ -0,0 +1,172 @@
+// 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;
+
+ /* XXX: currently it's useful only for the PF actions */
+ if (!IS_SRIOV_PF(gt_to_xe(gt)))
+ return 0;
+
+ 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(32), 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;
+}
diff --git a/drivers/gpu/drm/xe/xe_guc_buf.h b/drivers/gpu/drm/xe/xe_guc_buf.h
new file mode 100644
index 000000000000..0d67604d96bd
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_guc_buf.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2024 Intel Corporation
+ */
+
+#ifndef _XE_GUC_BUF_H_
+#define _XE_GUC_BUF_H_
+
+#include <linux/cleanup.h>
+#include <linux/err.h>
+
+#include "xe_guc_buf_types.h"
+
+int xe_guc_buf_cache_init(struct xe_guc_buf_cache *cache);
+u32 xe_guc_buf_cache_dwords(struct xe_guc_buf_cache *cache);
+struct xe_guc_buf xe_guc_buf_reserve(struct xe_guc_buf_cache *cache, u32 dwords);
+struct xe_guc_buf xe_guc_buf_from_data(struct xe_guc_buf_cache *cache,
+ const void *data, size_t size);
+void xe_guc_buf_release(const struct xe_guc_buf buf);
+
+/**
+ * xe_guc_buf_is_valid() - Check if a buffer reference is valid.
+ * @buf: the &xe_guc_buf reference to check
+ *
+ * Return: true if @ref represents a valid sub-allication.
+ */
+static inline bool xe_guc_buf_is_valid(const struct xe_guc_buf buf)
+{
+ return !IS_ERR_OR_NULL(buf.sa);
+}
+
+void *xe_guc_buf_cpu_ptr(const struct xe_guc_buf buf);
+u64 xe_guc_buf_flush(const struct xe_guc_buf buf);
+u64 xe_guc_buf_gpu_addr(const struct xe_guc_buf buf);
+u64 xe_guc_cache_gpu_addr_from_ptr(struct xe_guc_buf_cache *cache, const void *ptr, u32 size);
+
+DEFINE_CLASS(xe_guc_buf, struct xe_guc_buf,
+ xe_guc_buf_release(_T),
+ xe_guc_buf_reserve(cache, num),
+ struct xe_guc_buf_cache *cache, u32 num);
+
+DEFINE_CLASS(xe_guc_buf_from_data, struct xe_guc_buf,
+ xe_guc_buf_release(_T),
+ xe_guc_buf_from_data(cache, data, size),
+ struct xe_guc_buf_cache *cache, const void *data, size_t size);
+
+#endif
diff --git a/drivers/gpu/drm/xe/xe_guc_buf_types.h b/drivers/gpu/drm/xe/xe_guc_buf_types.h
new file mode 100644
index 000000000000..9e123d71c064
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_guc_buf_types.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2024 Intel Corporation
+ */
+
+#ifndef _XE_GUC_BUF_TYPES_H_
+#define _XE_GUC_BUF_TYPES_H_
+
+struct drm_suballoc;
+struct xe_sa_manager;
+
+/**
+ * struct xe_guc_buf_cache - GuC Data Buffer Cache.
+ */
+struct xe_guc_buf_cache {
+ /* private: internal sub-allocation manager */
+ struct xe_sa_manager *sam;
+};
+
+/**
+ * struct xe_guc_buf - GuC Data Buffer Reference.
+ */
+struct xe_guc_buf {
+ /* private: internal sub-allocation reference */
+ struct drm_suballoc *sa;
+};
+
+#endif
diff --git a/drivers/gpu/drm/xe/xe_guc_types.h b/drivers/gpu/drm/xe/xe_guc_types.h
index 83a41ebcdc91..573aa6308380 100644
--- a/drivers/gpu/drm/xe/xe_guc_types.h
+++ b/drivers/gpu/drm/xe/xe_guc_types.h
@@ -11,6 +11,7 @@
#include "regs/xe_reg_defs.h"
#include "xe_guc_ads_types.h"
+#include "xe_guc_buf_types.h"
#include "xe_guc_ct_types.h"
#include "xe_guc_fwif.h"
#include "xe_guc_log_types.h"
@@ -58,6 +59,8 @@ struct xe_guc {
struct xe_guc_ads ads;
/** @ct: GuC ct */
struct xe_guc_ct ct;
+ /** @buf: GuC Buffer Cache manager */
+ struct xe_guc_buf_cache buf;
/** @capture: the error-state-capture module's data and objects */
struct xe_guc_state_capture *capture;
/** @pc: GuC Power Conservation */
--
2.47.1
next prev parent reply other threads:[~2024-12-12 1:02 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-12-12 1:01 [PATCH 00/13] The xe_sa_manager based GuC Buffer Cache Michal Wajdeczko
2024-12-12 1:01 ` [PATCH 01/13] drm/xe/sa: Always call drm_suballoc_manager_fini() Michal Wajdeczko
2024-12-12 3:03 ` Matthew Brost
2024-12-12 1:01 ` [PATCH 02/13] drm/xe/sa: Drop redundant NULL assignments Michal Wajdeczko
2024-12-12 3:03 ` Matthew Brost
2024-12-12 1:01 ` [PATCH 03/13] drm/xe/sa: Cleanup internal BO data at device removal Michal Wajdeczko
2024-12-12 3:07 ` Matthew Brost
2024-12-12 1:01 ` [PATCH 04/13] drm/xe/sa: Drop useless is_iomem member Michal Wajdeczko
2024-12-12 3:09 ` Matthew Brost
2024-12-18 20:53 ` Michal Wajdeczko
2024-12-12 1:01 ` [PATCH 05/13] drm/xe/sa: Improve error message on init failure Michal Wajdeczko
2024-12-12 3:10 ` Matthew Brost
2024-12-12 1:01 ` [PATCH 06/13] drm/xe/sa: Tidy up coding style in init() Michal Wajdeczko
2024-12-12 3:11 ` Matthew Brost
2024-12-12 1:01 ` [PATCH 07/13] drm/xe/sa: Allow making suballocations using custom gfp flags Michal Wajdeczko
2024-12-12 3:12 ` Matthew Brost
2024-12-12 1:01 ` [PATCH 08/13] drm/xe/sa: Allow creating suballocator with custom guard size Michal Wajdeczko
2024-12-12 3:23 ` Matthew Brost
2024-12-12 21:57 ` Michal Wajdeczko
2024-12-12 22:48 ` Matthew Brost
2024-12-12 1:01 ` [PATCH 09/13] drm/xe/sa: Minor header cleanups Michal Wajdeczko
2024-12-12 3:14 ` Matthew Brost
2024-12-12 1:01 ` Michal Wajdeczko [this message]
2024-12-12 3:30 ` [PATCH 10/13] drm/xe/guc: Introduce the GuC Buffer Cache Matthew Brost
2024-12-12 21:48 ` Michal Wajdeczko
2024-12-13 18:38 ` Matthew Brost
2024-12-13 20:13 ` Rodrigo Vivi
2024-12-18 21:03 ` Michal Wajdeczko
2024-12-19 20:28 ` Rodrigo Vivi
2024-12-12 1:01 ` [PATCH 11/13] drm/xe/pf: Use GuC Buffer Cache during VFs provisioning Michal Wajdeczko
2024-12-12 3:34 ` Matthew Brost
2024-12-12 22:02 ` Michal Wajdeczko
2024-12-12 1:01 ` [PATCH 12/13] drm/xe/kunit: Allow to replace xe_managed_bo_create_pin_map() Michal Wajdeczko
2024-12-12 1:01 ` [PATCH 13/13] drm/xe/kunit: Add KUnit tests for GuC Buffer Cache Michal Wajdeczko
2024-12-12 3:36 ` Matthew Brost
2024-12-18 21:06 ` Michal Wajdeczko
2024-12-12 2:20 ` ✓ CI.Patch_applied: success for The xe_sa_manager based " Patchwork
2024-12-12 2:20 ` ✗ CI.checkpatch: warning " Patchwork
2024-12-12 2:21 ` ✓ CI.KUnit: success " Patchwork
2024-12-12 2:41 ` ✓ CI.Build: " Patchwork
2024-12-12 2:45 ` ✓ CI.Hooks: " Patchwork
2024-12-12 2:48 ` ✓ CI.checksparse: " Patchwork
2024-12-12 3:14 ` ✗ Xe.CI.BAT: failure " Patchwork
2024-12-12 8:50 ` ✗ Xe.CI.Full: " Patchwork
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20241212010141.389-11-michal.wajdeczko@intel.com \
--to=michal.wajdeczko@intel.com \
--cc=intel-xe@lists.freedesktop.org \
--cc=matthew.brost@intel.com \
--cc=rodrigo.vivi@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox