Add debugfs directory "amdgpu_ualink_test" with one entry per test, to
trigger UALink selftests without userspace application. remote_accel_id
and test_size are read/write, the test entries run on write.
Add helper functions: ualink_simple_rw() for remote VRAM R/W,
ualink_remote_shootdown() for TLB shootdown, ualink_send_hello()
for handshake, ualink_update_interrupt_wb()
and ualink_update_shootdown_wb() to read writeback results.
Use lsdma by default, can select sdma with command.
v3: Replace the single entry taking a test number with a debugfs
directory and a named entry per command.
Resync the ring pointers in ualink_send_hello(), the local wptr is
stale after a vpod reconfig.
Take peer->lock to update the writeback address and selftest_mutex
to read the test parameters.
v2: Fix typos and issues from copilot code review.
Signed-off-by: Philip Yang <[email protected]>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 215 ++++++++++++++++++
drivers/gpu/drm/amd/amdgpu/amdgpu_lsdma.c | 49 +++++
drivers/gpu/drm/amd/amdgpu/amdgpu_lsdma.h | 1 +
drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c | 231 +++++++++++++++++++-
drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.h | 14 ++
5 files changed, 509 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
index 35cbd358c28c..16af55905ee2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
@@ -2148,9 +2148,191 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_ib_preempt, NULL,
DEFINE_DEBUGFS_ATTRIBUTE(fops_sclk_set, NULL,
amdgpu_debugfs_sclk_set, "%llu\n");
+
+enum amdgpu_ualink_test_cmd {
+ UALINK_TEST_SW_INIT,
+ UALINK_TEST_SEND_HELLO,
+ UALINK_TEST_REMOTE_SHOOTDOWN,
+ UALINK_TEST_FLUSH_TLB,
+ UALINK_TEST_READ_LSDMA,
+ UALINK_TEST_READ_SDMA,
+ UALINK_TEST_WRITE_LSDMA,
+ UALINK_TEST_WRITE_SDMA,
+ UALINK_TEST_UPDATE_INTERRUPT_WB,
+ UALINK_TEST_UPDATE_SHOOTDOWN_WB,
+ UALINK_TEST_LSDMA_SELFTEST,
+};
+
+/* commands talking to a remote accelerator, remote_accel_id must be set */
+#define UALINK_TEST_NEEDS_ACCEL_ID \
+ (BIT(UALINK_TEST_SEND_HELLO) | BIT(UALINK_TEST_REMOTE_SHOOTDOWN) | \
+ BIT(UALINK_TEST_READ_LSDMA) | BIT(UALINK_TEST_READ_SDMA) | \
+ BIT(UALINK_TEST_WRITE_LSDMA) | BIT(UALINK_TEST_WRITE_SDMA) | \
+ BIT(UALINK_TEST_UPDATE_INTERRUPT_WB) | \
+ BIT(UALINK_TEST_UPDATE_SHOOTDOWN_WB))
+
+static int amdgpu_debugfs_ualink_test_run(struct amdgpu_device *adev,
+ enum amdgpu_ualink_test_cmd cmd)
+{
+ u32 remote_accel_id = adev->ualink.test_remote_accel_id;
+ int r = 0;
+
+ guard(mutex)(&adev->ualink.selftest_mutex);
+
+ if ((BIT(cmd) & UALINK_TEST_NEEDS_ACCEL_ID) &&
+ remote_accel_id >= AMDGPU_UALINK_ACCEL_MAX) {
+ dev_err(adev->dev, "set remote_accel_id first\n");
+ return -EINVAL;
+ }
+
+ adev->ualink.selftesting = true;
+
+ switch (cmd) {
+ case UALINK_TEST_SW_INIT:
+ if (adev->ualink.remote)
+ amdgpu_ualink_sw_fini(adev);
+
+ dev_dbg(adev->dev, "load metadata init MPNHT firmware\n");
+ r = amdgpu_ualink_sw_init(adev);
+ break;
+ case UALINK_TEST_SEND_HELLO:
+ r = ualink_send_hello(adev, remote_accel_id);
+ break;
+ case UALINK_TEST_REMOTE_SHOOTDOWN:
+ r = ualink_remote_shootdown(adev, remote_accel_id, 1UL << 30, 1,
+ TLB_FLUSH_HEAVYWEIGHT);
+ break;
+ case UALINK_TEST_FLUSH_TLB:
+ ualink_flush_tlb(adev, TLB_FLUSH_HEAVYWEIGHT);
+ break;
+ case UALINK_TEST_READ_LSDMA:
+ r = ualink_simple_rw(adev, remote_accel_id, true, true);
+ break;
+ case UALINK_TEST_READ_SDMA:
+ r = ualink_simple_rw(adev, remote_accel_id, true, false);
+ break;
+ case UALINK_TEST_WRITE_LSDMA:
+ r = ualink_simple_rw(adev, remote_accel_id, false, true);
+ break;
+ case UALINK_TEST_WRITE_SDMA:
+ r = ualink_simple_rw(adev, remote_accel_id, false, false);
+ break;
+ case UALINK_TEST_UPDATE_INTERRUPT_WB:
+ r = ualink_update_interrupt_wb(adev, remote_accel_id);
+ break;
+ case UALINK_TEST_UPDATE_SHOOTDOWN_WB:
+ r = ualink_update_shootdown_wb(adev, remote_accel_id);
+ break;
+ case UALINK_TEST_LSDMA_SELFTEST:
+ r = adev->lsdma.funcs ? amdgpu_lsdma_selftest(adev) :
-EOPNOTSUPP;
+ break;
+ }
+
+ adev->ualink.selftesting = false;
+
+ dev_dbg(adev->dev, "ualink test cmd %d remote_accel_id %u ret %d\n",
+ cmd, remote_accel_id, r);
+
+ return r;
+}
+
+#define UALINK_TEST_ATTR(name, cmd) \
+static int amdgpu_debugfs_ualink_##name##_set(void *data, u64 val) \
+{ \
+ return amdgpu_debugfs_ualink_test_run(data, cmd); \
+} \
+DEFINE_DEBUGFS_ATTRIBUTE(amdgpu_ualink_##name##_fops, NULL, \
+ amdgpu_debugfs_ualink_##name##_set, "%llu\n")
+
+UALINK_TEST_ATTR(sw_init, UALINK_TEST_SW_INIT);
+UALINK_TEST_ATTR(send_hello, UALINK_TEST_SEND_HELLO);
+UALINK_TEST_ATTR(remote_shootdown, UALINK_TEST_REMOTE_SHOOTDOWN);
+UALINK_TEST_ATTR(flush_tlb, UALINK_TEST_FLUSH_TLB);
+UALINK_TEST_ATTR(read_lsdma, UALINK_TEST_READ_LSDMA);
+UALINK_TEST_ATTR(read_sdma, UALINK_TEST_READ_SDMA);
+UALINK_TEST_ATTR(write_lsdma, UALINK_TEST_WRITE_LSDMA);
+UALINK_TEST_ATTR(write_sdma, UALINK_TEST_WRITE_SDMA);
+UALINK_TEST_ATTR(update_interrupt_wb, UALINK_TEST_UPDATE_INTERRUPT_WB);
+UALINK_TEST_ATTR(update_shootdown_wb, UALINK_TEST_UPDATE_SHOOTDOWN_WB);
+UALINK_TEST_ATTR(lsdma_selftest, UALINK_TEST_LSDMA_SELFTEST);
+
+static int amdgpu_debugfs_ualink_accel_id_get(void *data, u64 *val)
+{
+ struct amdgpu_device *adev = data;
+
+ guard(mutex)(&adev->ualink.selftest_mutex);
+
+ *val = adev->ualink.test_remote_accel_id;
+
+ return 0;
+}
+
+static int amdgpu_debugfs_ualink_accel_id_set(void *data, u64 val)
+{
+ struct amdgpu_device *adev = data;
+
+ if (!adev->ualink.info)
+ return -EOPNOTSUPP;
+
+ guard(mutex)(&adev->ualink.selftest_mutex);
+
+ if (val >= AMDGPU_UALINK_ACCEL_MAX ||
+ !test_bit(val, adev->ualink.info->vpod.active_accel_bits)) {
+ dev_err(adev->dev, "invalid remote accel_id %llu\n", val);
+ return -EINVAL;
+ }
+
+ if (val == adev->ualink.info->ppod.accel_id) {
+ dev_err(adev->dev, "remote accel_id equals to local
accel_id\n");
+ return -EINVAL;
+ }
+
+ adev->ualink.test_remote_accel_id = val;
+ dev_dbg(adev->dev, "set remote accel_id to %llu, local accel_id %u\n",
+ val, adev->ualink.info->ppod.accel_id);
+
+ return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(amdgpu_ualink_accel_id_fops,
+ amdgpu_debugfs_ualink_accel_id_get,
+ amdgpu_debugfs_ualink_accel_id_set, "%llu\n");
+
+static int amdgpu_debugfs_ualink_test_size_get(void *data, u64 *val)
+{
+ struct amdgpu_device *adev = data;
+
+ guard(mutex)(&adev->ualink.selftest_mutex);
+
+ *val = adev->ualink.test_size_dwords * 4;
+
+ return 0;
+}
+
+static int amdgpu_debugfs_ualink_test_size_set(void *data, u64 val)
+{
+ struct amdgpu_device *adev = data;
+
+ if (val < 4 || val > 8192)
+ return -EINVAL;
+
+ guard(mutex)(&adev->ualink.selftest_mutex);
+
+ adev->ualink.test_size_dwords = val / 4;
+ dev_dbg(adev->dev, "test buffer size %u bytes\n",
+ adev->ualink.test_size_dwords * 4);
+
+ return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(amdgpu_ualink_test_size_fops,
+ amdgpu_debugfs_ualink_test_size_get,
+ amdgpu_debugfs_ualink_test_size_set, "%llu\n");
+
int amdgpu_debugfs_init(struct amdgpu_device *adev)
{
struct dentry *root = adev_to_drm(adev)->primary->debugfs_root;
+ struct dentry *ualink_test;
struct dentry *ent;
int r, i;
@@ -2261,6 +2443,39 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev)
debugfs_create_ulong("amdgpu_ualink_drop_msg_bitmap", 0600, root,
&adev->ualink.drop_msg_bitmap);
+ mutex_init(&adev->ualink.selftest_mutex);
+ /* 64 bytes test size by default */
+ adev->ualink.test_size_dwords = 16;
+ adev->ualink.test_remote_accel_id = AMDGPU_UALINK_ACCEL_MAX;
+
+ ualink_test = debugfs_create_dir("amdgpu_ualink_test", root);
+ debugfs_create_file("remote_accel_id", 0600, ualink_test, adev,
+ &amdgpu_ualink_accel_id_fops);
+ debugfs_create_file("test_size", 0600, ualink_test, adev,
+ &amdgpu_ualink_test_size_fops);
+ debugfs_create_file("sw_init", 0200, ualink_test, adev,
+ &amdgpu_ualink_sw_init_fops);
+ debugfs_create_file("send_hello", 0200, ualink_test, adev,
+ &amdgpu_ualink_send_hello_fops);
+ debugfs_create_file("remote_shootdown", 0200, ualink_test, adev,
+ &amdgpu_ualink_remote_shootdown_fops);
+ debugfs_create_file("flush_tlb", 0200, ualink_test, adev,
+ &amdgpu_ualink_flush_tlb_fops);
+ debugfs_create_file("read_lsdma", 0200, ualink_test, adev,
+ &amdgpu_ualink_read_lsdma_fops);
+ debugfs_create_file("read_sdma", 0200, ualink_test, adev,
+ &amdgpu_ualink_read_sdma_fops);
+ debugfs_create_file("write_lsdma", 0200, ualink_test, adev,
+ &amdgpu_ualink_write_lsdma_fops);
+ debugfs_create_file("write_sdma", 0200, ualink_test, adev,
+ &amdgpu_ualink_write_sdma_fops);
+ debugfs_create_file("update_interrupt_wb", 0200, ualink_test, adev,
+ &amdgpu_ualink_update_interrupt_wb_fops);
+ debugfs_create_file("update_shootdown_wb", 0200, ualink_test, adev,
+ &amdgpu_ualink_update_shootdown_wb_fops);
+ debugfs_create_file("lsdma_selftest", 0200, ualink_test, adev,
+ &amdgpu_ualink_lsdma_selftest_fops);
+
adev->debugfs_vbios_blob.data = adev->bios;
adev->debugfs_vbios_blob.size = adev->bios_size;
debugfs_create_blob("amdgpu_vbios", 0444, root,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_lsdma.c
b/drivers/gpu/drm/amd/amdgpu/amdgpu_lsdma.c
index 05bc281216bf..1f83d9b69135 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_lsdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_lsdma.c
@@ -97,3 +97,52 @@ int amdgpu_lsdma_fill_mem(struct amdgpu_device *adev,
mutex_unlock(&adev->lsdma.lock);
return ret;
}
+
+int amdgpu_lsdma_selftest(struct amdgpu_device *adev)
+{
+ struct amdgpu_ib ib;
+ int i, r;
+ u64 gpu_addr;
+ char *p;
+ u32 size = 128;
+
+ memset(&ib, 0, sizeof(ib));
+ r = amdgpu_ib_get(adev, NULL, 2 * size, AMDGPU_IB_POOL_DIRECT, &ib);
+ if (r)
+ return r;
+
+ gpu_addr = ib.gpu_addr;
+ p = (char *)ib.ptr;
+ memset(p, 0, 2 * size);
+
+ for (i = 0; i < size; i++)
+ *(p + i) = i;
+
+ dev_dbg(adev->dev, "copy src 0x%llx dst 0x%llx size %d bytes\n",
+ gpu_addr, gpu_addr + size, size);
+
+ r = amdgpu_lsdma_copy_mem(adev, gpu_addr, gpu_addr + size, size);
+ if (r)
+ goto out;
+
+ p += size;
+ for (i = 0; i < size; i++) {
+ if (*(p + i) != i) {
+ dev_dbg(adev->dev, "data mismatch expecting 0x%x but
read 0x%x\n",
+ i, *(p + i));
+ break;
+ }
+ }
+ if (i != size)
+ r = -EIO;
+
+out:
+ amdgpu_ib_free(&ib, NULL);
+
+ if (r)
+ dev_dbg(adev->dev, "lsdma selftest failed r=%d\n", r);
+ else
+ dev_dbg(adev->dev, "lsdma selftest passed\n");
+
+ return r;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_lsdma.h
b/drivers/gpu/drm/amd/amdgpu/amdgpu_lsdma.h
index 34e92aaa4617..f0a5eeb3529f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_lsdma.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_lsdma.h
@@ -46,5 +46,6 @@ int amdgpu_lsdma_fill_mem(struct amdgpu_device *adev,
uint64_t dst_addr,
uint32_t data, uint64_t mem_size);
int amdgpu_lsdma_wait_for(struct amdgpu_device *adev, uint32_t reg_index,
uint32_t reg_val, uint32_t mask);
+int amdgpu_lsdma_selftest(struct amdgpu_device *adev);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
index 6cd3927a7e82..94caaa9ae417 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
@@ -5284,7 +5284,8 @@ static int amdgpu_ualink_metadata_init(struct
amdgpu_device *adev)
if (status != AMDGPU_NHT_FW_ST_PREINIT &&
status != AMDGPU_NHT_FW_ST_HALT) {
dev_dbg(adev->dev, "fw status 0x%x not preinit or halt\n",
status);
- return -ENODEV;
+ if (!adev->ualink.selftesting)
+ return -ENODEV;
}
dev_dbg(adev->dev, "accel_id %u addr_mode %d fw status 0x%x\n",
@@ -5333,6 +5334,14 @@ static int amdgpu_ualink_metadata_init(struct
amdgpu_device *adev)
remote->rb_gpu_addr, remote->rb_cpu_addr, adev->gmc.vram_start,
adev->vm_manager.vram_base_offset);
+ if (adev->ualink.selftesting) {
+ u32 *p = remote->rb_cpu_addr;
+ int i;
+
+ for (i = 0; i < rb_size / 4; i++)
+ *(p + i) = 0xdeadbeef;
+ }
+
/*
* address aliasing mode, shared wptr pagee left is not enough for wb
data,
* wb status and rptr, alloc another BO, and then alloc npa address and
map
@@ -5402,6 +5411,8 @@ static int amdgpu_ualink_metadata_init(struct
amdgpu_device *adev)
r = adev->ualink.msg_ctl->send_metadata(adev,
remote->metadata_gpu_addr,
AMDGPU_UALINK_ACCEL_MAX <<
8);
+ if (r && adev->ualink.selftesting)
+ r = 0;
out:
if (r)
@@ -6387,11 +6398,229 @@ void amdgpu_ualink_sw_fini(struct amdgpu_device *adev)
adev->ualink.remote = NULL;
}
+static void dump_buffer(struct amdgpu_device *adev, u32 *src, u32 size_dwords)
+{
+ u32 i = 0;
+ u64 p;
+
+ dev_dbg(adev->dev, "buffer 0x%px 0x%x dwords\n", src, size_dwords);
+
+ /* at least 64 bytes dump */
+ size_dwords = ALIGN_DOWN(size_dwords, 16);
+
+ while (i < size_dwords) {
+ p = (u64)(src + i);
+ dev_dbg(adev->dev, "0x%016llx: 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ p,
+ *(src + i),
+ *(src + i + 1),
+ *(src + i + 2),
+ *(src + i + 3));
+ i += 4;
+ }
+}
+
+/*
+ * With or without MPNHT FW running, write to remote ring buffer
+ *
+ * Write 16 dwords (64 bytes) to ring buffer, don't update wptr and ring the
doorbell
+ *
+ * Dump VRAM content check if remote writing is done correctly
+ *
+ * assuming ring buffer is located at VRAM offset 0x60000000
+ *
+ * root@atitest-MZ01-CE0-00:/home/atitest# cd /sys/kernel/debug/dri/0
+ *
+ * root@atitest-MZ01-CE0-00:/sys/kernel/debug/dri/0# echo 2 >
amdgpu_ualink_test
+ *
+ * root@atitest-MZ01-CE0-00:/sys/kernel/debug/dri/0# xxd -e -g 4 -s 0x60000000
-l 64 amdgpu_vram
+ * 60000000: 00000001 00000002 00000003 00000004 ................
+ * 60000010: 00000005 00000006 00000007 00000008 ................
+ * 60000020: 00000009 0000000a 0000000b 0000000c ................
+ * 60000030: 0000000d 0000000e 0000000f 00000010 ................
+ *
+ * root@atitest-MZ01-CE0-00:/sys/kernel/debug/dri/0# echo 2 >
amdgpu_ualink_test
+ *
+ * root@atitest-MZ01-CE0-00:/sys/kernel/debug/dri/0# xxd -e -g 4 -s 0x60000000
-l 64 amdgpu_vram
+ * 60000000: 00000002 00000003 00000004 00000005 ................
+ * 60000010: 00000006 00000007 00000008 00000009 ................
+ * 60000020: 0000000a 0000000b 0000000c 0000000d ................
+ * 60000030: 0000000e 0000000f 00000010 00000011 ................
+ */
+int ualink_simple_rw(struct amdgpu_device *adev, u32 remote_accel_id, bool
read, bool use_lsdma)
+{
+ struct amdgpu_ualink_remote *remote = to_remote(adev);
+ u32 test_size_dwords = adev->ualink.test_size_dwords;
+ struct amdgpu_ualink_peer *peer;
+ struct amdgpu_ualink_ring *ring;
+ struct dma_fence *fence;
+ struct amdgpu_job *job;
+ struct amdgpu_ib *ib;
+ u32 seq, ndw, ndw_copy_cmd;
+ u32 *src_cpu;
+ u64 src;
+ int r, i;
+
+ if (!remote)
+ return -EINVAL;
+
+ peer = &remote->peer[remote_accel_id];
+ ring = &peer->interrupt;
+
+ /*
+ * 1 sdma copy command to write data to ring buffer
+ *
+ * sdma linear copy command is 7 dwords, align to 8 dwords boundary
+ */
+ ndw_copy_cmd = ALIGN(adev->mman.buffer_funcs->copy_num_dw, 8);
+
+ /*
+ * 16 dwords data
+ */
+ ndw = ndw_copy_cmd + test_size_dwords;
+ r = amdgpu_job_alloc_with_ib(adev, &peer->entity, AMDGPU_FENCE_OWNER_VM,
+ ndw * 4, AMDGPU_IB_POOL_IMMEDIATE,
+ AMDGPU_KERNEL_JOB_ID_TTM_COPY_BUFFER,
&job);
+ if (r)
+ return r;
+
+ mutex_lock(&peer->lock);
+
+ ib = job->ibs;
+ ib->length_dw = 0;
+ src = ib->gpu_addr + ndw_copy_cmd * 4;
+ src_cpu = ib->ptr + ndw_copy_cmd;
+
+ seq = ++ring->seq;
+
+ dev_dbg(adev->dev, "src 0x%llx to npa on gart rb 0x%llx seq 0x%x %s
%s\n",
+ src, ring->rb_npa_gart, seq, read ? "read" : "write",
+ use_lsdma ? "use lsdma" : "use sdma");
+
+ for (i = 0; i < test_size_dwords; i++)
+ *src_cpu++ = seq + i;
+
+ dev_dbg(adev->dev, "dump test buffer data\n");
+ dump_buffer(adev, ib->ptr + ndw_copy_cmd, test_size_dwords);
+
+ remote->use_lsdma = use_lsdma;
+
+ dev_dbg(adev->dev, "use %s\n", remote->use_lsdma ? "lsdma" : "sdma");
+
+ if (remote->use_lsdma) {
+ if (read)
+ r = amdgpu_lsdma_copy_mem(adev, ring->rb_npa_gart, src,
+ test_size_dwords * 4);
+ else
+ r = amdgpu_lsdma_copy_mem(adev, src, ring->rb_npa_gart,
+ test_size_dwords * 4);
+
+ amdgpu_job_free(job);
+ goto out_unlock;
+ }
+
+ /* SDMA commands copy from ib to NPA */
+ if (read)
+ amdgpu_emit_copy_buffer(adev, ib, ring->rb_npa_gart, src,
+ test_size_dwords * 4, 0);
+ else
+ amdgpu_emit_copy_buffer(adev, ib, src, ring->rb_npa_gart,
+ test_size_dwords * 4, 0);
+
+ amdgpu_ring_pad_ib(&adev->sdma.instance[0].ring, ib);
+ WARN_ON(ib->length_dw > ndw_copy_cmd);
+
+ fence = amdgpu_job_submit(job);
+
+ /*
+ * wait sdma done
+ */
+ r = dma_fence_wait_timeout(fence, false, HZ * 10);
+ dma_fence_put(fence);
+ if (r <= 0) {
+ dev_dbg(adev->dev, "remote sdma fence wait timeout %d\n", r);
+ dev_dbg(adev->dev, "use lsdma for testing afterwards\n");
+ remote->use_lsdma = true;
+ r = -ETIME;
+ } else {
+ r = 0;
+ }
+
+out_unlock:
+ mutex_unlock(&peer->lock);
+ if (read) {
+ dev_dbg(adev->dev, "dump remote read data\n");
+ dump_buffer(adev, ib->ptr + ndw_copy_cmd, test_size_dwords);
+ }
+
+ dev_dbg(adev->dev, "ret r=%d\n", r);
+ return r;
+}
+
int ualink_send_hello(struct amdgpu_device *adev, u32 remote_accel_id)
{
+ int r;
+
+ if (!adev->ualink.remote)
+ return -EINVAL;
+
+ /* vpod reconfig leaves the local wptr stale, resync it first, same as
+ * the handshake does before sending HELLO
+ */
+ r = amdgpu_ualink_ring_resync_ptrs(adev, remote_accel_id);
+ if (r < 0)
+ return r;
+
+ amdgpu_ualink_reset_peer_rings(adev, remote_accel_id);
+
return amdgpu_ualink_send_hello_msg(adev, remote_accel_id);
}
+void ualink_flush_tlb(struct amdgpu_device *amdgpu, u32 flush_type)
+{
+ amdgpu_ualink_flush_tlb(amdgpu, flush_type);
+}
+
+int ualink_remote_shootdown(struct amdgpu_device *adev, u32 remote_accel_id,
u64 addr,
+ u32 size_in_pages, u32 flush_type)
+{
+ if (!adev->ualink.remote)
+ return -EINVAL;
+
+ return amdgpu_ualink_remote_shootdown(adev, remote_accel_id, addr,
+ size_in_pages, flush_type);
+}
+
+int ualink_update_interrupt_wb(struct amdgpu_device *adev, u32 remote_accel_id)
+{
+ int r;
+
+ if (!adev->ualink.remote)
+ return -EINVAL;
+
+ guard(mutex)(&adev->ualink.remote->peer[remote_accel_id].lock);
+
+ /* Update interrupt completion write back address */
+ r = amdgpu_ualink_update_wb_address(adev, remote_accel_id,
+ RB_TYPE_REMOTE_INTERRUPT);
+ return r;
+}
+
+int ualink_update_shootdown_wb(struct amdgpu_device *adev, u32 remote_accel_id)
+{
+ int r;
+
+ if (!adev->ualink.remote)
+ return -EINVAL;
+
+ guard(mutex)(&adev->ualink.remote->peer[remote_accel_id].lock);
+
+ /* Update shootdown completion write back address */
+ r = amdgpu_ualink_update_wb_address(adev, remote_accel_id,
+ RB_TYPE_TLB_INV);
+ return r;
+}
+
/*
* The low bits of handle_lo carry the message-header field on the wire.
* Strip those bits and splice in @acc_id to recover the
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.h
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.h
index 85c9a9634a4b..52bcbf1b1107 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.h
@@ -333,6 +333,12 @@ struct amdgpu_ualink_mgr {
/* For remote interrupt and shootdown */
struct amdgpu_ualink_remote *remote;
+ /* true for selftest driver path, ignore FW error */
+ bool selftesting;
+ struct mutex selftest_mutex;
+ u32 test_size_dwords;
+ u32 test_remote_accel_id;
+
/* handle irq from ualink client of remote GPUs */
struct amdgpu_irq_src irq;
@@ -393,6 +399,14 @@ struct amdgpu_ualink_mgr {
int amdgpu_ualink_init_interrupt(struct amdgpu_device *adev,
unsigned int client_id, unsigned int src_id);
+int ualink_simple_rw(struct amdgpu_device *adev, u32 remote_accel_id, bool
read, bool use_lsdma);
+int ualink_send_hello(struct amdgpu_device *adev, u32 remote_accel_id);
+void ualink_flush_tlb(struct amdgpu_device *amdgpu, u32 flush_type);
+int ualink_remote_shootdown(struct amdgpu_device *adev, u32 remote_accel_id,
u64 addr,
+ u32 size_in_pages, u32 flush_type);
+int ualink_update_interrupt_wb(struct amdgpu_device *adev, u32
remote_accel_id);
+int ualink_update_shootdown_wb(struct amdgpu_device *adev, u32
remote_accel_id);
+
int amdgpu_ualink_sw_init(struct amdgpu_device *adev);
void amdgpu_ualink_sw_fini(struct amdgpu_device *adev);
--
2.50.1