<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<p style="font-family:Arial;font-size:10pt;color:#008000;margin:15pt;font-style:normal;font-weight:normal;text-decoration:none;" align="Left">
[Public]<br>
</p>
<br>
<div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof ContentPasted0">
Hi Kamil,
<div class="ContentPasted0">Yes, sure, </div>
<div class="ContentPasted0">I will work on this using your suggestion in the previous email.</div>
Thanks, Vitaly<br>
</div>
<div id="appendonsend"></div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> Kamil Konieczny <kamil.konieczny@linux.intel.com><br>
<b>Sent:</b> Monday, July 3, 2023 3:39 AM<br>
<b>To:</b> igt-dev@lists.freedesktop.org <igt-dev@lists.freedesktop.org><br>
<b>Cc:</b> Prosyak, Vitaly <Vitaly.Prosyak@amd.com>; Koenig, Christian <Christian.Koenig@amd.com><br>
<b>Subject:</b> Re: [PATCH] tests/amdgpu: add sync object tests</font>
<div> </div>
</div>
<div class="BodyFragment"><font size="2"><span style="font-size:11pt;">
<div class="PlainText">Hi Vitaly,<br>
<br>
On 2023-07-01 at 21:22:30 -0400, vitaly.prosyak@amd.com wrote:<br>
> From: Vitaly Prosyak <vitaly.prosyak@amd.com><br>
> <br>
> Using worker thread to wait on point and then signal point on other thread.<br>
> Another test uses a worker thread to signal point and wait on the main<br>
> thread using amdgpu_cs_syncobj_timeline_wait.<br>
> <br>
> The command consists of two chunks :<br>
> 1. AMDGPU_CHUNK_ID_IB uses GFX_COMPUTE_NOP  or SDMA_NOP.<br>
> 2. The second chunk is AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_WAIT<br>
>    or AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_SIGNAL which has the<br>
>    point number .<br>
> <br>
> v1->v2. Fixed style issues - Christian.<br>
>         Fixed formatting issues - Kamil.<br>
> <br>
> Signed-off-by: Vitaly Prosyak <vitaly.prosyak@amd.com><br>
> Acked-by: Christian Koenig <christian.koenig@amd.com><br>
> Acked-by: Kamil Konieczny <kamil.konieczny@linux.intel.com><br>
<br>
Please do not merge this until you address GitLab compilation<br>
issue.<br>
<br>
Regards,<br>
Kamil<br>
<br>
> ---<br>
>  tests/amdgpu/amd_syncobj.c | 266 +++++++++++++++++++++++++++++++++++++<br>
>  tests/amdgpu/meson.build   |   1 +<br>
>  2 files changed, 267 insertions(+)<br>
>  create mode 100644 tests/amdgpu/amd_syncobj.c<br>
> <br>
> diff --git a/tests/amdgpu/amd_syncobj.c b/tests/amdgpu/amd_syncobj.c<br>
> new file mode 100644<br>
> index 000000000..7cab093c9<br>
> --- /dev/null<br>
> +++ b/tests/amdgpu/amd_syncobj.c<br>
> @@ -0,0 +1,266 @@<br>
> +// SPDX-License-Identifier: MIT<br>
> +/*<br>
> + * Copyright 2023 Advanced Micro Devices, Inc.<br>
> + */<br>
> +<br>
> +#include <pthread.h><br>
> +<br>
> +#include <amdgpu.h><br>
> +#include <amdgpu_drm.h><br>
> +<br>
> +#include "igt.h"<br>
> +#include "lib/amdgpu/amd_PM4.h"<br>
> +#include "lib/amdgpu/amd_sdma.h"<br>
> +#include "lib/amdgpu/amd_memory.h"<br>
> +<br>
> +struct syncobj_point {<br>
> +     amdgpu_device_handle device;<br>
> +     uint32_t syncobj_handle;<br>
> +     uint64_t point;<br>
> +};<br>
> +<br>
> +<br>
> +static bool<br>
> +syncobj_timeline_enable(int fd)<br>
> +{<br>
> +     int r;<br>
> +     bool ret = false;<br>
> +     uint64_t cap = 0;<br>
> +<br>
> +     r = drmGetCap(fd, DRM_CAP_SYNCOBJ_TIMELINE, &cap);<br>
> +     if (r || cap == 0)<br>
> +             return ret;<br>
> +     ret = true;<br>
> +<br>
> +     return ret;<br>
> +}<br>
> +<br>
> +static void<br>
> +syncobj_command_submission_helper(amdgpu_device_handle device_handle,<br>
> +             uint32_t syncobj_handle, bool wait_or_signal, uint64_t point)<br>
> +{<br>
> +     amdgpu_context_handle context_handle;<br>
> +     amdgpu_bo_handle ib_result_handle;<br>
> +     void *ib_result_cpu;<br>
> +     uint64_t ib_result_mc_address;<br>
> +     struct drm_amdgpu_cs_chunk chunks[2];<br>
> +     struct drm_amdgpu_cs_chunk_data chunk_data;<br>
> +     struct drm_amdgpu_cs_chunk_syncobj syncobj_data;<br>
> +     struct amdgpu_cs_fence fence_status;<br>
> +     amdgpu_bo_list_handle bo_list;<br>
> +     amdgpu_va_handle va_handle;<br>
> +     uint32_t expired;<br>
> +     int i, r;<br>
> +     uint64_t seq_no;<br>
> +     uint32_t *ptr;<br>
> +<br>
> +     r = amdgpu_cs_ctx_create(device_handle, &context_handle);<br>
> +     igt_assert_eq(r, 0);<br>
> +<br>
> +     r = amdgpu_bo_alloc_and_map(device_handle, 4096, 4096,<br>
> +                                 AMDGPU_GEM_DOMAIN_GTT, 0,<br>
> +                                 &ib_result_handle, &ib_result_cpu,<br>
> +                                 &ib_result_mc_address, &va_handle);<br>
> +     igt_assert_eq(r, 0);<br>
> +<br>
> +     r = amdgpu_get_bo_list(device_handle, ib_result_handle, NULL, &bo_list);<br>
> +     igt_assert_eq(r, 0);<br>
> +<br>
> +     ptr = ib_result_cpu;<br>
> +<br>
> +     for (i = 0; i < 16; ++i)<br>
> +             ptr[i] = wait_or_signal ? GFX_COMPUTE_NOP : SDMA_NOP;<br>
> +<br>
> +     chunks[0].chunk_id = AMDGPU_CHUNK_ID_IB;<br>
> +     chunks[0].length_dw = sizeof(struct drm_amdgpu_cs_chunk_ib) / 4;<br>
> +     chunks[0].chunk_data = (uint64_t)(uintptr_t)&chunk_data;<br>
> +     chunk_data.ib_data._pad = 0;<br>
> +     chunk_data.ib_data.va_start = ib_result_mc_address;<br>
> +     chunk_data.ib_data.ib_bytes = 16 * 4;<br>
> +     chunk_data.ib_data.ip_type = wait_or_signal ? AMDGPU_HW_IP_GFX : AMDGPU_HW_IP_DMA;<br>
> +     chunk_data.ib_data.ip_instance = 0;<br>
> +     chunk_data.ib_data.ring = 0;<br>
> +     chunk_data.ib_data.flags = 0;<br>
> +<br>
> +     chunks[1].chunk_id = wait_or_signal ?<br>
> +             AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_WAIT :<br>
> +             AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_SIGNAL;<br>
> +     chunks[1].length_dw = sizeof(struct drm_amdgpu_cs_chunk_syncobj) / 4;<br>
> +     chunks[1].chunk_data = (uint64_t)(uintptr_t)&syncobj_data;<br>
> +     syncobj_data.handle = syncobj_handle;<br>
> +     syncobj_data.point = point;<br>
> +     syncobj_data.flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT;<br>
> +<br>
> +     r = amdgpu_cs_submit_raw(device_handle,<br>
> +                              context_handle,<br>
> +                              bo_list,<br>
> +                              2,<br>
> +                              chunks,<br>
> +                              &seq_no);<br>
> +     igt_assert_eq(r, 0);<br>
> +<br>
> +     memset(&fence_status, 0, sizeof(struct amdgpu_cs_fence));<br>
> +     fence_status.context = context_handle;<br>
> +     fence_status.ip_type = wait_or_signal ? AMDGPU_HW_IP_GFX : AMDGPU_HW_IP_DMA;<br>
> +     fence_status.ip_instance = 0;<br>
> +     fence_status.ring = 0;<br>
> +     fence_status.fence = seq_no;<br>
> +<br>
> +     r = amdgpu_cs_query_fence_status(&fence_status,<br>
> +                     AMDGPU_TIMEOUT_INFINITE, 0, &expired);<br>
> +     igt_assert_eq(r, 0);<br>
> +<br>
> +     r = amdgpu_bo_list_destroy(bo_list);<br>
> +     igt_assert_eq(r, 0);<br>
> +<br>
> +     amdgpu_bo_unmap_and_free(ib_result_handle, va_handle,<br>
> +                                  ib_result_mc_address, 4096);<br>
> +<br>
> +     r = amdgpu_cs_ctx_free(context_handle);<br>
> +     igt_assert_eq(r, 0);<br>
> +}<br>
> +<br>
> +static void *<br>
> +syncobj_wait(void *data)<br>
> +{<br>
> +     struct syncobj_point *sp = (struct syncobj_point *)data;<br>
> +<br>
> +     syncobj_command_submission_helper(sp->device, sp->syncobj_handle, true,<br>
> +                     sp->point);<br>
> +<br>
> +     return (void *)0;<br>
> +}<br>
> +<br>
> +static void *<br>
> +syncobj_signal(void *data)<br>
> +{<br>
> +     struct syncobj_point *sp = (struct syncobj_point *)data;<br>
> +<br>
> +     syncobj_command_submission_helper(sp->device, sp->syncobj_handle, false,<br>
> +                     sp->point);<br>
> +<br>
> +     return (void *)0;<br>
> +}<br>
> +<br>
> +static void<br>
> +amdgpu_syncobj_timeline(amdgpu_device_handle device_handle)<br>
> +{<br>
> +     static pthread_t wait_thread;<br>
> +     static pthread_t signal_thread;<br>
> +     static pthread_t c_thread;<br>
> +     struct syncobj_point sp1, sp2, sp3;<br>
> +     uint32_t syncobj_handle;<br>
> +     uint64_t payload;<br>
> +     uint64_t wait_point, signal_point;<br>
> +     uint64_t timeout;<br>
> +     struct timespec tp;<br>
> +     int r, sync_fd;<br>
> +     void *tmp, *tmp2;<br>
> +<br>
> +     r =  amdgpu_cs_create_syncobj2(device_handle, 0, &syncobj_handle);<br>
> +     igt_assert_eq(r, 0);<br>
> +<br>
> +     // wait on point 5<br>
> +     sp1.syncobj_handle = syncobj_handle;<br>
> +     sp1.device = device_handle;<br>
> +     sp1.point = 5;<br>
> +     r = pthread_create(&wait_thread, NULL, syncobj_wait, &sp1);<br>
> +     igt_assert_eq(r, 0);<br>
> +<br>
> +     // signal on point 10<br>
> +     sp2.syncobj_handle = syncobj_handle;<br>
> +     sp2.device = device_handle;<br>
> +     sp2.point = 10;<br>
> +     r = pthread_create(&signal_thread, NULL, syncobj_signal, &sp2);<br>
> +     igt_assert_eq(r, 0);<br>
> +<br>
> +     r = pthread_join(signal_thread, &tmp);<br>
> +     igt_assert_eq(r, 0);<br>
> +<br>
> +     r = pthread_join(wait_thread, &tmp2);<br>
> +     igt_assert_eq(r, 0);<br>
> +<br>
> +     //query timeline payload<br>
> +     r = amdgpu_cs_syncobj_query(device_handle, &syncobj_handle,<br>
> +                                 &payload, 1);<br>
> +     igt_assert_eq(r, 0);<br>
> +     igt_assert_eq(payload, 10);<br>
> +<br>
> +     //signal on point 16<br>
> +     sp3.syncobj_handle = syncobj_handle;<br>
> +     sp3.device = device_handle;<br>
> +     sp3.point = 16;<br>
> +     r = pthread_create(&c_thread, NULL, syncobj_signal, &sp3);<br>
> +     igt_assert_eq(r, 0);<br>
> +<br>
> +     //CPU wait on point 16<br>
> +     wait_point = 16;<br>
> +     timeout = 0;<br>
> +     clock_gettime(CLOCK_MONOTONIC, &tp);<br>
> +     timeout = tp.tv_sec * 1000000000ULL + tp.tv_nsec;<br>
> +     timeout += 10000000000; //10s<br>
> +     r = amdgpu_cs_syncobj_timeline_wait(device_handle, &syncobj_handle,<br>
> +                                         &wait_point, 1, timeout,<br>
> +                                         DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL |<br>
> +                                         DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,<br>
> +                                         NULL);<br>
> +<br>
> +     igt_assert_eq(r, 0);<br>
> +     r = pthread_join(c_thread, &tmp);<br>
> +     igt_assert_eq(r, 0);<br>
> +<br>
> +     // export point 16 and import to point 18<br>
> +     r = amdgpu_cs_syncobj_export_sync_file2(device_handle, syncobj_handle,<br>
> +                                             16,<br>
> +                                             DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,<br>
> +                                             &sync_fd);<br>
> +     igt_assert_eq(r, 0);<br>
> +     r = amdgpu_cs_syncobj_import_sync_file2(device_handle, syncobj_handle,<br>
> +                                             18, sync_fd);<br>
> +     igt_assert_eq(r, 0);<br>
> +     r = amdgpu_cs_syncobj_query(device_handle, &syncobj_handle,<br>
> +                                 &payload, 1);<br>
> +     igt_assert_eq(r, 0);<br>
> +     igt_assert_eq(payload, 18);<br>
> +<br>
> +     // CPU signal on point 20<br>
> +     signal_point = 20;<br>
> +     r = amdgpu_cs_syncobj_timeline_signal(device_handle, &syncobj_handle,<br>
> +                                           &signal_point, 1);<br>
> +     igt_assert_eq(r, 0);<br>
> +     r = amdgpu_cs_syncobj_query(device_handle, &syncobj_handle,<br>
> +                                 &payload, 1);<br>
> +     igt_assert_eq(r, 0);<br>
> +     igt_assert_eq(payload, 20);<br>
> +<br>
> +     r = amdgpu_cs_destroy_syncobj(device_handle, syncobj_handle);<br>
> +     igt_assert_eq(r, 0);<br>
> +<br>
> +}<br>
> +<br>
> +igt_main<br>
> +{<br>
> +     amdgpu_device_handle device;<br>
> +     int fd = -1;<br>
> +<br>
> +     igt_fixture {<br>
> +             uint32_t major, minor;<br>
> +             int err;<br>
> +<br>
> +             fd = drm_open_driver(DRIVER_AMDGPU);<br>
> +             err = amdgpu_device_initialize(fd, &major, &minor, &device);<br>
> +             igt_require(err == 0);<br>
> +             igt_require(syncobj_timeline_enable(fd));<br>
> +             igt_info("Initialized amdgpu, driver version %d.%d\n",<br>
> +                      major, minor);<br>
> +<br>
> +     }<br>
> +<br>
> +     igt_subtest("amdgpu_syncobj_timeline")<br>
> +     amdgpu_syncobj_timeline(device);<br>
> +<br>
> +     igt_fixture {<br>
> +             amdgpu_device_deinitialize(device);<br>
> +             close(fd);<br>
> +     }<br>
> +}<br>
> diff --git a/tests/amdgpu/meson.build b/tests/amdgpu/meson.build<br>
> index 24843de73..02096934d 100644<br>
> --- a/tests/amdgpu/meson.build<br>
> +++ b/tests/amdgpu/meson.build<br>
> @@ -6,6 +6,7 @@ if libdrm_amdgpu.found()<br>
>                          'amd_assr',<br>
>                          'amd_basic',<br>
>                          'amd_bo',<br>
> +                       'amd_syncobj',<br>
>                          'amd_bypass',<br>
>                          'amd_color',<br>
>                          'amd_cp_dma_misc',<br>
> -- <br>
> 2.25.1<br>
> <br>
</div>
</span></font></div>
</div>
</body>
</html>