2 * Copyright 2017 Advanced Micro Devices, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
24 #include "CUnit/Basic.h"
27 #include "amdgpu_test.h"
28 #include "amdgpu_drm.h"
29 #include "amdgpu_internal.h"
32 static amdgpu_device_handle device_handle
;
33 static uint32_t major_version
;
34 static uint32_t minor_version
;
36 static uint32_t family_id
;
37 static uint32_t chip_id
;
38 static uint32_t chip_rev
;
40 static void amdgpu_syncobj_timeline_test(void);
42 CU_BOOL
suite_syncobj_timeline_tests_enable(void)
47 r
= drmGetCap(drm_amdgpu
[0], DRM_CAP_SYNCOBJ_TIMELINE
, &cap
);
54 int suite_syncobj_timeline_tests_init(void)
58 r
= amdgpu_device_initialize(drm_amdgpu
[0], &major_version
,
59 &minor_version
, &device_handle
);
62 if ((r
== -EACCES
) && (errno
== EACCES
))
63 printf("\n\nError:%s. "
64 "Hint:Try to run this test program as root.",
66 return CUE_SINIT_FAILED
;
72 int suite_syncobj_timeline_tests_clean(void)
74 int r
= amdgpu_device_deinitialize(device_handle
);
79 return CUE_SCLEAN_FAILED
;
83 CU_TestInfo syncobj_timeline_tests
[] = {
84 { "syncobj timeline test", amdgpu_syncobj_timeline_test
},
88 #define GFX_COMPUTE_NOP 0xffff1000
90 static int syncobj_command_submission_helper(uint32_t syncobj_handle
, bool
91 wait_or_signal
, uint64_t point
)
93 amdgpu_context_handle context_handle
;
94 amdgpu_bo_handle ib_result_handle
;
96 uint64_t ib_result_mc_address
;
97 struct drm_amdgpu_cs_chunk chunks
[2];
98 struct drm_amdgpu_cs_chunk_data chunk_data
;
99 struct drm_amdgpu_cs_chunk_syncobj syncobj_data
;
100 struct amdgpu_cs_fence fence_status
;
101 amdgpu_bo_list_handle bo_list
;
102 amdgpu_va_handle va_handle
;
106 static uint32_t *ptr
;
107 struct amdgpu_gpu_info gpu_info
= {0};
110 r
= amdgpu_query_gpu_info(device_handle
, &gpu_info
);
111 CU_ASSERT_EQUAL(r
, 0);
113 family_id
= device_handle
->info
.family_id
;
114 chip_id
= device_handle
->info
.chip_external_rev
;
115 chip_rev
= device_handle
->info
.chip_rev
;
117 gc_ip_type
= (asic_is_gfx_pipe_removed(family_id
, chip_id
, chip_rev
)) ?
118 AMDGPU_HW_IP_COMPUTE
: AMDGPU_HW_IP_GFX
;
120 r
= amdgpu_cs_ctx_create(device_handle
, &context_handle
);
121 CU_ASSERT_EQUAL(r
, 0);
123 r
= amdgpu_bo_alloc_and_map(device_handle
, 4096, 4096,
124 AMDGPU_GEM_DOMAIN_GTT
, 0,
125 &ib_result_handle
, &ib_result_cpu
,
126 &ib_result_mc_address
, &va_handle
);
127 CU_ASSERT_EQUAL(r
, 0);
129 r
= amdgpu_get_bo_list(device_handle
, ib_result_handle
, NULL
,
131 CU_ASSERT_EQUAL(r
, 0);
135 for (i
= 0; i
< 16; ++i
)
136 ptr
[i
] = wait_or_signal
? GFX_COMPUTE_NOP
: SDMA_NOP
;
138 chunks
[0].chunk_id
= AMDGPU_CHUNK_ID_IB
;
139 chunks
[0].length_dw
= sizeof(struct drm_amdgpu_cs_chunk_ib
) / 4;
140 chunks
[0].chunk_data
= (uint64_t)(uintptr_t)&chunk_data
;
141 chunk_data
.ib_data
._pad
= 0;
142 chunk_data
.ib_data
.va_start
= ib_result_mc_address
;
143 chunk_data
.ib_data
.ib_bytes
= 16 * 4;
144 chunk_data
.ib_data
.ip_type
= wait_or_signal
? gc_ip_type
:
146 chunk_data
.ib_data
.ip_instance
= 0;
147 chunk_data
.ib_data
.ring
= 0;
148 chunk_data
.ib_data
.flags
= AMDGPU_IB_FLAG_EMIT_MEM_SYNC
;
150 chunks
[1].chunk_id
= wait_or_signal
?
151 AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_WAIT
:
152 AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_SIGNAL
;
153 chunks
[1].length_dw
= sizeof(struct drm_amdgpu_cs_chunk_syncobj
) / 4;
154 chunks
[1].chunk_data
= (uint64_t)(uintptr_t)&syncobj_data
;
155 syncobj_data
.handle
= syncobj_handle
;
156 syncobj_data
.point
= point
;
157 syncobj_data
.flags
= DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT
;
159 r
= amdgpu_cs_submit_raw(device_handle
,
165 CU_ASSERT_EQUAL(r
, 0);
168 memset(&fence_status
, 0, sizeof(struct amdgpu_cs_fence
));
169 fence_status
.context
= context_handle
;
170 fence_status
.ip_type
= wait_or_signal
? gc_ip_type
:
172 fence_status
.ip_instance
= 0;
173 fence_status
.ring
= 0;
174 fence_status
.fence
= seq_no
;
176 r
= amdgpu_cs_query_fence_status(&fence_status
,
177 AMDGPU_TIMEOUT_INFINITE
,0, &expired
);
178 CU_ASSERT_EQUAL(r
, 0);
180 r
= amdgpu_bo_list_destroy(bo_list
);
181 CU_ASSERT_EQUAL(r
, 0);
183 r
= amdgpu_bo_unmap_and_free(ib_result_handle
, va_handle
,
184 ib_result_mc_address
, 4096);
185 CU_ASSERT_EQUAL(r
, 0);
187 r
= amdgpu_cs_ctx_free(context_handle
);
188 CU_ASSERT_EQUAL(r
, 0);
193 struct syncobj_point
{
194 uint32_t syncobj_handle
;
198 static void *syncobj_wait(void *data
)
200 struct syncobj_point
*sp
= (struct syncobj_point
*)data
;
203 r
= syncobj_command_submission_helper(sp
->syncobj_handle
, true,
205 CU_ASSERT_EQUAL(r
, 0);
207 return (void *)(long)r
;
210 static void *syncobj_signal(void *data
)
212 struct syncobj_point
*sp
= (struct syncobj_point
*)data
;
215 r
= syncobj_command_submission_helper(sp
->syncobj_handle
, false,
217 CU_ASSERT_EQUAL(r
, 0);
219 return (void *)(long)r
;
222 static void amdgpu_syncobj_timeline_test(void)
224 static pthread_t wait_thread
;
225 static pthread_t signal_thread
;
226 static pthread_t c_thread
;
227 struct syncobj_point sp1
, sp2
, sp3
;
228 uint32_t syncobj_handle
;
230 uint64_t wait_point
, signal_point
;
236 r
= amdgpu_cs_create_syncobj2(device_handle
, 0, &syncobj_handle
);
237 CU_ASSERT_EQUAL(r
, 0);
240 sp1
.syncobj_handle
= syncobj_handle
;
242 r
= pthread_create(&wait_thread
, NULL
, syncobj_wait
, &sp1
);
243 CU_ASSERT_EQUAL(r
, 0);
245 // signal on point 10
246 sp2
.syncobj_handle
= syncobj_handle
;
248 r
= pthread_create(&signal_thread
, NULL
, syncobj_signal
, &sp2
);
249 CU_ASSERT_EQUAL(r
, 0);
251 r
= pthread_join(wait_thread
, &tmp
);
252 CU_ASSERT_EQUAL(r
, 0);
253 CU_ASSERT_EQUAL(tmp
, 0);
255 r
= pthread_join(signal_thread
, &tmp
);
256 CU_ASSERT_EQUAL(r
, 0);
257 CU_ASSERT_EQUAL(tmp
, 0);
259 //query timeline payload
260 r
= amdgpu_cs_syncobj_query(device_handle
, &syncobj_handle
,
262 CU_ASSERT_EQUAL(r
, 0);
263 CU_ASSERT_EQUAL(payload
, 10);
266 sp3
.syncobj_handle
= syncobj_handle
;
268 r
= pthread_create(&c_thread
, NULL
, syncobj_signal
, &sp3
);
269 CU_ASSERT_EQUAL(r
, 0);
270 //CPU wait on point 16
273 clock_gettime(CLOCK_MONOTONIC
, &tp
);
274 timeout
= tp
.tv_sec
* 1000000000ULL + tp
.tv_nsec
;
275 timeout
+= 0x10000000000; //10s
276 r
= amdgpu_cs_syncobj_timeline_wait(device_handle
, &syncobj_handle
,
277 &wait_point
, 1, timeout
,
278 DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL
|
279 DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT
,
282 CU_ASSERT_EQUAL(r
, 0);
283 r
= pthread_join(c_thread
, &tmp
);
284 CU_ASSERT_EQUAL(r
, 0);
285 CU_ASSERT_EQUAL(tmp
, 0);
287 // export point 16 and import to point 18
288 r
= amdgpu_cs_syncobj_export_sync_file2(device_handle
, syncobj_handle
,
290 DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT
,
292 CU_ASSERT_EQUAL(r
, 0);
293 r
= amdgpu_cs_syncobj_import_sync_file2(device_handle
, syncobj_handle
,
295 CU_ASSERT_EQUAL(r
, 0);
296 r
= amdgpu_cs_syncobj_query(device_handle
, &syncobj_handle
,
298 CU_ASSERT_EQUAL(r
, 0);
299 CU_ASSERT_EQUAL(payload
, 18);
301 // CPU signal on point 20
303 r
= amdgpu_cs_syncobj_timeline_signal(device_handle
, &syncobj_handle
,
305 CU_ASSERT_EQUAL(r
, 0);
306 r
= amdgpu_cs_syncobj_query(device_handle
, &syncobj_handle
,
308 CU_ASSERT_EQUAL(r
, 0);
309 CU_ASSERT_EQUAL(payload
, 20);
311 r
= amdgpu_cs_destroy_syncobj(device_handle
, syncobj_handle
);
312 CU_ASSERT_EQUAL(r
, 0);