Igt-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Jesse Zhang <Jesse.Zhang@amd.com>
To: <igt-dev@lists.freedesktop.org>
Cc: Vitaly Prosyak <vitaly.prosyak@amd.com>,
	Alex Deucher <alexander.deucher@amd.com>,
	Christian Koenig <christian.koenig@amd.com>,
	Jesse Zhang <Jesse.Zhang@amd.com>
Subject: [PATCH] tests/amdgpu: add compute scratch memory test
Date: Thu, 9 Jul 2026 16:39:06 +0800	[thread overview]
Message-ID: <20260709084037.1912218-1-Jesse.Zhang@amd.com> (raw)

Add a gfx11 compute scratch-aperture round-trip test on the KGD
user-mode-queue (UQM) path. It assembles a small ScratchCopyDword shader
and dispatches it in two hops (src -> scratch aperture -> dst); dst ==
src proves the SPI scratch base and per-wave offset are correct. The
aperture base comes from the kernel (dev_info.scratch_base) with a gfx11
constant fallback.

The UQM path exercises the compute CWSR context save/restore area:
lib/amdgpu enables the CWSR path and passes a correctly-sized MQD with a
valid ctx_save_area. The compute MQD uAPI gains ctx_save_area_addr/size,
ordered after cu_mask_* and the priority fields to match the kernel and
libdrm layout.

v2: split per-generation packet emission into
    amdgpu_emit_scratch_dispatch_gfx11() selected via a switch, keeping
    the common dispatch init (and IB bind) shared. (Vitaly)

Reviewed-by: Vitaly Prosyak <vitaly.prosyak@amd.com>
Signed-off-by: Jesse Zhang <Jesse.Zhang@amd.com>
---
 include/drm-uapi/amdgpu_drm.h           |  22 +-
 lib/amdgpu/amd_registers.h              |  26 +++
 lib/amdgpu/amd_userq.c                  |   7 +-
 lib/amdgpu/compute_utils/amd_dispatch.c | 266 ++++++++++++++++++++++++
 lib/amdgpu/compute_utils/amd_dispatch.h |   3 +
 tests/amdgpu/amd_dispatch.c             |  21 ++
 6 files changed, 333 insertions(+), 12 deletions(-)

diff --git a/include/drm-uapi/amdgpu_drm.h b/include/drm-uapi/amdgpu_drm.h
index b2a1688e6..66c37191b 100644
--- a/include/drm-uapi/amdgpu_drm.h
+++ b/include/drm-uapi/amdgpu_drm.h
@@ -456,17 +456,6 @@ struct drm_amdgpu_userq_mqd_compute_gfx11 {
 	 * to get the size.
 	 */
 	__u64   eop_va;
-	/**
-	 * @ctx_save_area_addr: Virtual address of the GPU memory for save/restore buffer.
-	 * This must be a from a separate GPU object, and use AMDGPU_INFO IOCTL
-	 * to get the size.
-	 */
-	__u64 ctx_save_area_addr;
-	/**
-	 * @ctx_save_area_size:  Total size allocated for save/restore buffer.
-	 * Use AMDGPU_INFO IOCTL to get the size.
-	 */
-	__u32 ctx_save_area_size;
 	/**
 	 * @cu_mask_ptr: User-space pointer to CU (Compute Unit) mask array
 	 * Points to an array of __u32 values that define which CUs are enabled
@@ -494,6 +483,17 @@ struct drm_amdgpu_userq_mqd_compute_gfx11 {
 	 * Specifies the target XCC (Cross Compute Complex) for PM4 commands
 	 */
 	__u32 pm4_target_xcc;
+	/**
+	 * @ctx_save_area_addr: Virtual address of the GPU memory for save/restore buffer.
+	 * This must be a from a separate GPU object, and use AMDGPU_INFO IOCTL
+	 * to get the size.
+	 */
+	__u64 ctx_save_area_addr;
+	/**
+	 * @ctx_save_area_size:  Total size allocated for save/restore buffer.
+	 * Use AMDGPU_INFO IOCTL to get the size.
+	 */
+	__u32 ctx_save_area_size;
 };
 
 /* userq signal/wait ioctl */
diff --git a/lib/amdgpu/amd_registers.h b/lib/amdgpu/amd_registers.h
index ff62b8931..ef87736a2 100644
--- a/lib/amdgpu/amd_registers.h
+++ b/lib/amdgpu/amd_registers.h
@@ -34,6 +34,32 @@ enum general_reg {
 	COMPUTE_NUM_THREAD_X,
 };
 
+/*
+ * Absolute register offsets (mm*) of the COMPUTE SH registers, from
+ * drivers/gpu/drm/amd/include/asic_reg/gca/gfx_7_2_d.h (gfx9+ regs from
+ * gc_12_0_0_offset.h, converted to the mm scheme). A PM4 SET_SH_REG packet
+ * carries (mm_offset - PACKET3_SET_SH_REG_START); use SH_REG(name) below so
+ * the emit sites read as register names instead of magic numbers.
+ */
+#define PACKET3_SET_SH_REG_START		0x00002c00
+#define mmCOMPUTE_START_X			0x2e04
+#define mmCOMPUTE_NUM_THREAD_X			0x2e07
+#define mmCOMPUTE_PGM_LO			0x2e0c
+#define mmCOMPUTE_DISPATCH_SCRATCH_BASE_LO	0x2e10
+#define mmCOMPUTE_DISPATCH_SCRATCH_BASE_HI	0x2e11
+#define mmCOMPUTE_PGM_RSRC1			0x2e12
+#define mmCOMPUTE_PGM_RSRC2			0x2e13
+#define mmCOMPUTE_RESOURCE_LIMITS		0x2e15
+#define mmCOMPUTE_TMPRING_SIZE			0x2e18
+#define mmCOMPUTE_PGM_RSRC3			0x2e28
+#define mmCOMPUTE_USER_DATA_0			0x2e40
+
+/* PM4 SET_SH_REG register-field offset for a named compute register. */
+#define SH_REG(mmreg)		((mmreg) - PACKET3_SET_SH_REG_START)
+
+/* COMPUTE_PGM_RSRC2.SCRATCH_EN (bit 0). */
+#define COMPUTE_PGM_RSRC2__SCRATCH_EN		0x1
+
 struct amd_reg {
 	enum general_reg reg_name;
 	int 	 reg_offset;
diff --git a/lib/amdgpu/amd_userq.c b/lib/amdgpu/amd_userq.c
index 98a53223d..f94991971 100644
--- a/lib/amdgpu/amd_userq.c
+++ b/lib/amdgpu/amd_userq.c
@@ -3,6 +3,11 @@
  * Copyright 2025 Advanced Micro Devices, Inc.
  */
 
+/* libdrm exposes amdgpu_query_cwsr_info + struct drm_amdgpu_info_cwsr; enable
+ * the CWSR path so compute userq passes a valid ctx_save_area to the
+ * (cwsr-enabled) kernel. */
+#define HAVE_AMDGPU_INFO_CWSR 1
+
 #include "amd_userq.h"
 #include "amd_memory.h"
 #include "amd_PM4.h"
@@ -298,7 +303,7 @@ void amdgpu_user_queue_create(amdgpu_device_handle device_handle, struct amdgpu_
 	uint64_t gtt_flags = 0, queue_flags = 0;
 	struct drm_amdgpu_userq_mqd_gfx11 gfx_mqd;
 	struct drm_amdgpu_userq_mqd_sdma_gfx11 sdma_mqd;
-	struct drm_amdgpu_userq_mqd_compute_gfx11 compute_mqd;
+	struct drm_amdgpu_userq_mqd_compute_gfx11 compute_mqd = {0};
 	uint32_t ctl_stack_size_bytes = 0, dbg_mem_size_bytes = 0, min_save_area_size = 0;
 	bool compute_need_cwsr = false;
 	void *mqd;
diff --git a/lib/amdgpu/compute_utils/amd_dispatch.c b/lib/amdgpu/compute_utils/amd_dispatch.c
index 7bb6f4174..926690f13 100644
--- a/lib/amdgpu/compute_utils/amd_dispatch.c
+++ b/lib/amdgpu/compute_utils/amd_dispatch.c
@@ -4,6 +4,7 @@
 // Copyright 2023 Advanced Micro Devices, Inc.
 
 #include <amdgpu.h>
+#include <amdgpu_drm.h>
 #include "amdgpu/amd_memory.h"
 #include "amdgpu/amd_userq.h"
 #include "amd_dispatch.h"
@@ -11,7 +12,10 @@
 #include "amd_dispatch_helpers.h"
 #include "amdgpu/amd_PM4.h"
 #include "amdgpu/amd_ip_blocks.h"
+#include "amdgpu/amd_registers.h"
 #include "amdgpu/shaders/amd_shaders.h"
+#include "amdgpu/shaders/amd_shader_store.h"
+#include "amdgpu/shaders/amd_llvm_asm.h"
 
 static void
 amdgpu_memset_dispatch_test(amdgpu_device_handle device_handle,
@@ -442,6 +446,268 @@ amdgpu_memcpy_dispatch_test(amdgpu_device_handle device_handle,
 	return r;
 }
 
+/*
+ * Emit one scratch-enabled compute dispatch that copies a dword from arg_src to
+ * arg_dst (used by the kfdtest-style FlatScratchAccess two-hop below). Register
+ * offsets use the named mmCOMPUTE_* macros in amd_registers.h.
+ *
+ * Scratch base is provided per-gen: <=gfx11 the shader writes FLAT_SCR from
+ * s[4:5]; gfx12 SCRATCH_BASE is read-only and HW-loaded from
+ * COMPUTE_DISPATCH_SCRATCH_BASE. Enable via COMPUTE_PGM_RSRC2.SCRATCH_EN +
+ * COMPUTE_TMPRING_SIZE (WAVES=#SE). Shader assembled at runtime via LLVM MC.
+ */
+#ifdef AMDGPU_LLVM_ENABLED
+static void
+amdgpu_emit_scratch_dispatch_gfx11(struct amdgpu_cmd_base *base_cmd,
+			 uint64_t mc_shader, uint64_t mc_scratch,
+			 uint64_t arg_src, uint64_t arg_dst, uint32_t num_waves)
+{
+
+	/* COMPUTE_PGM_LO/HI */
+	base_cmd->emit(base_cmd, PACKET3_COMPUTE(PKT3_SET_SH_REG, 2));
+	base_cmd->emit(base_cmd, SH_REG(mmCOMPUTE_PGM_LO));
+	base_cmd->emit(base_cmd, mc_shader >> 8);
+	base_cmd->emit(base_cmd, mc_shader >> 40);
+
+	/* COMPUTE_PGM_RSRC1 / RSRC2 (enable scratch) */
+	base_cmd->emit(base_cmd, PACKET3_COMPUTE(PKT3_SET_SH_REG, 2));
+	base_cmd->emit(base_cmd, SH_REG(mmCOMPUTE_PGM_RSRC1));
+	base_cmd->emit(base_cmd, 0x600C0041 & ~(1u << 29));
+	base_cmd->emit(base_cmd, 0x00000090 | COMPUTE_PGM_RSRC2__SCRATCH_EN);
+
+	/* COMPUTE_DISPATCH_SCRATCH_BASE_LO/HI (256-byte units); gfx12 HW loads
+	 * the read-only SCRATCH_BASE from this. */
+	base_cmd->emit(base_cmd, PACKET3_COMPUTE(PKT3_SET_SH_REG, 2));
+	base_cmd->emit(base_cmd, SH_REG(mmCOMPUTE_DISPATCH_SCRATCH_BASE_LO));
+	base_cmd->emit(base_cmd, (mc_scratch >> 8) & 0xffffffff);
+	base_cmd->emit(base_cmd, mc_scratch >> 40);
+
+	/* COMPUTE_NUM_THREAD_X/Y/Z = 1 */
+	base_cmd->emit(base_cmd, PACKET3_COMPUTE(PKT3_SET_SH_REG, 3));
+	base_cmd->emit(base_cmd, SH_REG(mmCOMPUTE_NUM_THREAD_X));
+	base_cmd->emit(base_cmd, 1);
+	base_cmd->emit(base_cmd, 1);
+	base_cmd->emit(base_cmd, 1);
+
+	/* COMPUTE_PGM_RSRC3 - required on gfx11+ */
+	base_cmd->emit(base_cmd, PACKET3_COMPUTE(PKT3_SET_SH_REG, 1));
+	base_cmd->emit(base_cmd, SH_REG(mmCOMPUTE_PGM_RSRC3));
+	base_cmd->emit(base_cmd, 0x3f0);
+
+	/* COMPUTE_TMPRING_SIZE = (WAVESIZE<<12)|WAVES; WAVES=#SE (kfdtest sizing) */
+	base_cmd->emit(base_cmd, PACKET3_COMPUTE(PKT3_SET_SH_REG, 1));
+	base_cmd->emit(base_cmd, SH_REG(mmCOMPUTE_TMPRING_SIZE));
+	base_cmd->emit(base_cmd, (1u << 12) | (num_waves & 0xfff));
+
+	/* User data: s[0:1]=src, s[2:3]=dst, s[4:5]=scratch base (byte; <=gfx11 FLAT_SCR) */
+	base_cmd->emit(base_cmd, PACKET3_COMPUTE(PKT3_SET_SH_REG, 6));
+	base_cmd->emit(base_cmd, SH_REG(mmCOMPUTE_USER_DATA_0));
+	base_cmd->emit(base_cmd, arg_src & 0xffffffff);
+	base_cmd->emit(base_cmd, arg_src >> 32);
+	base_cmd->emit(base_cmd, arg_dst & 0xffffffff);
+	base_cmd->emit(base_cmd, arg_dst >> 32);
+	base_cmd->emit(base_cmd, mc_scratch & 0xffffffff);
+	base_cmd->emit(base_cmd, mc_scratch >> 32);
+
+	base_cmd->emit(base_cmd, PACKET3_COMPUTE(PKT3_SET_SH_REG, 1));
+	base_cmd->emit(base_cmd, SH_REG(mmCOMPUTE_RESOURCE_LIMITS));
+	base_cmd->emit(base_cmd, 0);
+
+	base_cmd->emit(base_cmd, PACKET3_COMPUTE(PACKET3_DISPATCH_DIRECT, 3));
+	base_cmd->emit(base_cmd, 0x10);
+	base_cmd->emit(base_cmd, 1);
+	base_cmd->emit(base_cmd, 1);
+	base_cmd->emit(base_cmd, 1);
+	base_cmd->emit_aligned(base_cmd, 7, GFX_COMPUTE_NOP);
+}
+
+/*
+ * Allocate+map a BO for the scratch test. On a user queue every BO the queue
+ * touches must be made resident, so use the sync variant + timeline wait.
+ */
+static int
+scratch_alloc_bo(amdgpu_device_handle dev, int size, uint32_t domain,
+		 struct amdgpu_ring_context *rc,
+		 amdgpu_bo_handle *bo, void **cpu, uint64_t *mc,
+		 amdgpu_va_handle *va)
+{
+	int r;
+
+	r = amdgpu_bo_alloc_and_map_sync(dev, size, 4096, domain, 0,
+					 AMDGPU_VM_MTYPE_UC, bo, cpu, mc, va,
+					 rc->timeline_syncobj_handle,
+					 ++rc->point, true);
+	if (r)
+		return r;
+	return amdgpu_timeline_syncobj_wait(dev, rc->timeline_syncobj_handle,
+					    rc->point);
+}
+#endif
+
+/*
+ * GPU scratch (private) memory round-trip test, a direct port of kfdtest
+ * KFDMemoryTest.FlatScratchAccess to the amdgpu KGD path. Same shader
+ * (ScratchCopyDwordIsa) and same two-hop structure:
+ *   hop0: *src -> scratch aperture VA; hop1: scratch aperture VA -> *dst.
+ * The FLAT load/store is routed to scratch by the private aperture
+ * (private_base<<48 == 0x1000000000000000 on gfx11). dst==src proves the
+ * cross-dispatch scratch round-trip worked. Runs on a KGD user queue.
+ *
+ * Determinism (matching kfdtest) requires:
+ *   1. both dispatches share ONE scratch backing BO so the written slot persists;
+ *   2. WAVES=#SE, waveSize=1, dim 1x1x1 -> exactly one wave, placed by the SPI at
+ *      scratch offset 0 on each dispatch (same physical slot);
+ *   3. a full wait (== kfdtest Sync) between the two submits (the
+ *      synchronous user-queue submit);
+ *   4. a FRESH IB command BO per submit — reusing one IB BO for a back-to-back
+ *      compute submit makes the 2nd dispatch read ring NOP-fill and fault
+ *      (bad_op / ring reset). This is the crux; kfdtest gets it for free via a
+ *      per-dispatch IndirectBuffer.
+ * gfx11 only.
+ */
+int
+amdgpu_scratch_dispatch_test(amdgpu_device_handle device_handle,
+			   uint32_t ip_type, uint32_t version)
+{
+#ifndef AMDGPU_LLVM_ENABLED
+	igt_info("SKIP scratch two-hop: built without LLVM MC assembler\n");
+	return 0;
+#else
+	uint64_t aperture;
+	amdgpu_bo_handle bo_src, bo_dst, bo_shader, bo_scratch;
+	volatile uint32_t *ptr_dst;
+	void *ptr_shader, *ptr_scratch;
+	uint32_t *ptr_src;
+	uint64_t mc_src, mc_dst, mc_shader, mc_scratch;
+	amdgpu_va_handle va_src, va_dst, va_shader, va_scratch;
+	int r, hop;
+	const int bo_size = 4096;
+	const int bo_scratch_size = 0x10000;
+	struct amdgpu_gpu_info gpu_info = {0};
+	struct drm_amdgpu_info_device dev_info = {0};
+	struct amdgpu_ring_context *ring_context = NULL;
+	const struct amdgpu_ip_block_version *ip_block = NULL;
+	uint32_t num_waves;
+	char mcpu[16];
+	uint8_t isa[4096];
+	size_t isa_size = 0;
+
+	if (version != 11) {
+		igt_info("SKIP scratch two-hop: gfx11 only, got %u\n", version);
+		return 0;
+	}
+
+	r = amdgpu_query_gpu_info(device_handle, &gpu_info);
+	igt_assert_eq(r, 0);
+	/* Prefer the kernel-reported scratch/private aperture; fall back to the
+	 * gfx11 constant (gmc private_aperture_start) on older kernels that don't
+	 * export it. kfdtest gets the same value from KFD topology. */
+	r = amdgpu_query_info(device_handle, AMDGPU_INFO_DEV_INFO,
+			      sizeof(dev_info), &dev_info);
+	igt_assert_eq(r, 0);
+	aperture = dev_info.scratch_base ? dev_info.scratch_base
+					 : 0x1000000000000000ull;
+	igt_info("scratch aperture base: 0x%016lx (%s)\n", aperture,
+		 dev_info.scratch_base ? "kernel" : "fallback constant");
+	/* WAVES = #SE so the SPI deterministically places the single wave at
+	 * scratch offset 0 on every dispatch (kfdtest SetScratch numWaves). */
+	num_waves = gpu_info.num_shader_engines ? gpu_info.num_shader_engines : 1;
+	amdgpu_family_id_to_mcpu(gpu_info.family_id, mcpu, sizeof(mcpu));
+	if (amdgpu_llvm_asm_init() != 0 ||
+	    amdgpu_llvm_assemble(mcpu, ScratchCopyDwordIsa, isa, sizeof(isa),
+				 &isa_size) != 0 || isa_size == 0) {
+		igt_info("SKIP scratch two-hop: LLVM assemble failed for %s\n", mcpu);
+		return 0;
+	}
+
+	ring_context = calloc(1, sizeof(*ring_context));
+	igt_assert(ring_context);
+	ip_block = get_ip_block(device_handle, ip_type);
+	ip_block->funcs->userq_create(device_handle, ring_context,
+				      ip_block->type);
+
+	r = scratch_alloc_bo(device_handle, bo_size, AMDGPU_GEM_DOMAIN_VRAM,
+			ring_context, &bo_shader, &ptr_shader,
+			&mc_shader, &va_shader);
+	igt_assert_eq(r, 0);
+	memset(ptr_shader, 0, bo_size);
+	memcpy(ptr_shader, isa, isa_size);
+	r = scratch_alloc_bo(device_handle, bo_size, AMDGPU_GEM_DOMAIN_VRAM,
+			ring_context, &bo_src, (void **)&ptr_src,
+			&mc_src, &va_src);
+	igt_assert_eq(r, 0);
+	r = scratch_alloc_bo(device_handle, bo_size, AMDGPU_GEM_DOMAIN_VRAM,
+			ring_context, &bo_dst, (void **)&ptr_dst,
+			&mc_dst, &va_dst);
+	igt_assert_eq(r, 0);
+	/* One shared scratch backing BO for BOTH hops (kfdtest shares scratchBuffer). */
+	r = scratch_alloc_bo(device_handle, bo_scratch_size, AMDGPU_GEM_DOMAIN_VRAM,
+			ring_context, &bo_scratch, &ptr_scratch,
+			&mc_scratch, &va_scratch);
+	igt_assert_eq(r, 0);
+
+	ptr_src[0] = 0x01010101;
+	*ptr_dst = 0;
+
+	for (hop = 0; hop < 2; hop++) {
+		struct amdgpu_cmd_base *cmd = get_cmd_base();
+		amdgpu_bo_handle bo_cmd;
+		amdgpu_va_handle va_cmd;
+		uint32_t *ptr_cmd;
+		uint64_t mc_cmd;
+		/* hop0: *src -> aperture; hop1: aperture -> *dst. */
+		uint64_t arg_src = hop == 0 ? mc_src : aperture;
+		uint64_t arg_dst = hop == 0 ? aperture : mc_dst;
+
+		/* Fresh IB per hop; user queues need it mapped+resident (sync). */
+		r = scratch_alloc_bo(device_handle, bo_size, AMDGPU_GEM_DOMAIN_GTT,
+				ring_context, &bo_cmd,
+				(void **)&ptr_cmd, &mc_cmd, &va_cmd);
+		igt_assert_eq(r, 0);
+
+		/* Bind the freshly allocated IB as the PM4 command buffer. */
+		memset(ptr_cmd, 0, bo_size);
+		cmd->attach_buf(cmd, ptr_cmd, bo_size);
+
+		/* Common dispatch initialization */
+		amdgpu_dispatch_init(ip_type, cmd, version);
+		amdgpu_dispatch_write_cumask(cmd, version);
+
+		/* Generation-specific scratch dispatch packets */
+		switch (version) {
+		case 11:
+			amdgpu_emit_scratch_dispatch_gfx11(cmd, mc_shader,
+							   mc_scratch, arg_src, arg_dst, num_waves);
+			break;
+		default:
+			igt_assert_f(0, "Unsupported gfx version %u for scratch dispatch\n", version);
+		}
+
+		/* user_queue_submit synchronizes, so it doubles as the
+		 * kfdtest Sync between the two hops. */
+		ring_context->pm4_dw = cmd->cdw;
+		ip_block->funcs->userq_submit(device_handle, ring_context,
+					      ip_block->type, mc_cmd);
+
+		amdgpu_bo_unmap_and_free(bo_cmd, va_cmd, mc_cmd, bo_size);
+		free_cmd_base(cmd);
+	}
+
+	igt_info("scratch two-hop (userq, flat->aperture, WAVES=%u): dst=0x%08x\n",
+		 num_waves, *ptr_dst);
+	igt_assert_eq(*ptr_dst, 0x01010101);
+
+	amdgpu_bo_unmap_and_free(bo_scratch, va_scratch, mc_scratch, bo_scratch_size);
+	amdgpu_bo_unmap_and_free(bo_src, va_src, mc_src, bo_size);
+	amdgpu_bo_unmap_and_free(bo_dst, va_dst, mc_dst, bo_size);
+	amdgpu_bo_unmap_and_free(bo_shader, va_shader, mc_shader, bo_size);
+	ip_block->funcs->userq_destroy(device_handle, ring_context,
+				       ip_block->type);
+	free(ring_context);
+	return 0;
+#endif
+}
+
 static void
 amdgpu_memcpy_dispatch_hang_slow_test(amdgpu_device_handle device_handle,
 				      uint32_t ip_type, uint32_t priority,
diff --git a/lib/amdgpu/compute_utils/amd_dispatch.h b/lib/amdgpu/compute_utils/amd_dispatch.h
index 45858ba4b..6a0612779 100644
--- a/lib/amdgpu/compute_utils/amd_dispatch.h
+++ b/lib/amdgpu/compute_utils/amd_dispatch.h
@@ -44,5 +44,8 @@ int amdgpu_memcpy_dispatch_test(amdgpu_device_handle device_handle,
 void amdgpu_dispatch_hang_slow_helper(amdgpu_device_handle device_handle,
 				      uint32_t ip_type, const struct pci_addr *pci, bool userq);
 
+int amdgpu_scratch_dispatch_test(amdgpu_device_handle device_handle,
+			       uint32_t ip_type, uint32_t version);
+
 
 #endif
diff --git a/tests/amdgpu/amd_dispatch.c b/tests/amdgpu/amd_dispatch.c
index 44aa2d128..0496050b9 100644
--- a/tests/amdgpu/amd_dispatch.c
+++ b/tests/amdgpu/amd_dispatch.c
@@ -42,6 +42,19 @@ amdgpu_dispatch_hang_compute(amdgpu_device_handle device_handle,
 	amdgpu_gfx_dispatch_test(device_handle, AMDGPU_HW_IP_COMPUTE, error, pci, userq);
 }
 
+static void
+amdgpu_dispatch_scratch_compute(amdgpu_device_handle device_handle)
+{
+	struct drm_amdgpu_info_hw_ip info;
+	uint32_t version;
+	int r;
+
+	r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_COMPUTE, 0, &info);
+	igt_assert_eq(r, 0);
+	version = info.hw_ip_version_major;
+	amdgpu_scratch_dispatch_test(device_handle, AMDGPU_HW_IP_COMPUTE, version);
+}
+
 static void
 amdgpu_gpu_reset_test(amdgpu_device_handle device_handle, int drm_amdgpu,
 		const struct pci_addr *pci)
@@ -216,6 +229,14 @@ int igt_main()
 		}
 	}
 
+	igt_describe("Compute scratch(private) memory round-trip via aperture, kfdtest FlatScratchAccess port (user queue path)");
+	igt_subtest_with_dynamic("amdgpu-scratch-test-compute-with-IP-COMPUTE-UQM") {
+		if (enable_test && userq_arr_cap[AMD_IP_COMPUTE]) {
+			igt_dynamic_f("amdgpu-scratch-test-compute-uqm")
+			amdgpu_dispatch_scratch_compute(device);
+		}
+	}
+
 	igt_fixture() {
 		amdgpu_device_deinitialize(device);
 		drm_close_driver(fd);
-- 
2.49.0


             reply	other threads:[~2026-07-09  8:41 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-09  8:39 Jesse Zhang [this message]
2026-07-09 22:09 ` ✗ Fi.CI.BUILD: failure for tests/amdgpu: add compute scratch memory test (rev2) 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=20260709084037.1912218-1-Jesse.Zhang@amd.com \
    --to=jesse.zhang@amd.com \
    --cc=alexander.deucher@amd.com \
    --cc=christian.koenig@amd.com \
    --cc=igt-dev@lists.freedesktop.org \
    --cc=vitaly.prosyak@amd.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