1d722e3fbSopenharmony_ci/*
2d722e3fbSopenharmony_ci * Copyright 2014 Advanced Micro Devices, Inc.
3d722e3fbSopenharmony_ci *
4d722e3fbSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5d722e3fbSopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6d722e3fbSopenharmony_ci * to deal in the Software without restriction, including without limitation
7d722e3fbSopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8d722e3fbSopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9d722e3fbSopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10d722e3fbSopenharmony_ci *
11d722e3fbSopenharmony_ci * The above copyright notice and this permission notice shall be included in
12d722e3fbSopenharmony_ci * all copies or substantial portions of the Software.
13d722e3fbSopenharmony_ci *
14d722e3fbSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15d722e3fbSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16d722e3fbSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17d722e3fbSopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18d722e3fbSopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19d722e3fbSopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20d722e3fbSopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
21d722e3fbSopenharmony_ci *
22d722e3fbSopenharmony_ci */
23d722e3fbSopenharmony_ci
24d722e3fbSopenharmony_ci#include <stdlib.h>
25d722e3fbSopenharmony_ci#include <stdio.h>
26d722e3fbSopenharmony_ci#include <string.h>
27d722e3fbSopenharmony_ci#include <errno.h>
28d722e3fbSopenharmony_ci#include <pthread.h>
29d722e3fbSopenharmony_ci#include <sched.h>
30d722e3fbSopenharmony_ci#include <sys/ioctl.h>
31d722e3fbSopenharmony_ci#if HAVE_ALLOCA_H
32d722e3fbSopenharmony_ci# include <alloca.h>
33d722e3fbSopenharmony_ci#endif
34d722e3fbSopenharmony_ci
35d722e3fbSopenharmony_ci#include "xf86drm.h"
36d722e3fbSopenharmony_ci#include "amdgpu_drm.h"
37d722e3fbSopenharmony_ci#include "amdgpu_internal.h"
38d722e3fbSopenharmony_ci
39d722e3fbSopenharmony_cistatic int amdgpu_cs_unreference_sem(amdgpu_semaphore_handle sem);
40d722e3fbSopenharmony_cistatic int amdgpu_cs_reset_sem(amdgpu_semaphore_handle sem);
41d722e3fbSopenharmony_ci
42d722e3fbSopenharmony_ci/**
43d722e3fbSopenharmony_ci * Create command submission context
44d722e3fbSopenharmony_ci *
45d722e3fbSopenharmony_ci * \param   dev      - \c [in] Device handle. See #amdgpu_device_initialize()
46d722e3fbSopenharmony_ci * \param   priority - \c [in] Context creation flags. See AMDGPU_CTX_PRIORITY_*
47d722e3fbSopenharmony_ci * \param   context  - \c [out] GPU Context handle
48d722e3fbSopenharmony_ci *
49d722e3fbSopenharmony_ci * \return  0 on success otherwise POSIX Error code
50d722e3fbSopenharmony_ci*/
51d722e3fbSopenharmony_cidrm_public int amdgpu_cs_ctx_create2(amdgpu_device_handle dev,
52d722e3fbSopenharmony_ci				     uint32_t priority,
53d722e3fbSopenharmony_ci				     amdgpu_context_handle *context)
54d722e3fbSopenharmony_ci{
55d722e3fbSopenharmony_ci	struct amdgpu_context *gpu_context;
56d722e3fbSopenharmony_ci	union drm_amdgpu_ctx args;
57d722e3fbSopenharmony_ci	int i, j, k;
58d722e3fbSopenharmony_ci	int r;
59d722e3fbSopenharmony_ci
60d722e3fbSopenharmony_ci	if (!dev || !context)
61d722e3fbSopenharmony_ci		return -EINVAL;
62d722e3fbSopenharmony_ci
63d722e3fbSopenharmony_ci	gpu_context = calloc(1, sizeof(struct amdgpu_context));
64d722e3fbSopenharmony_ci	if (!gpu_context)
65d722e3fbSopenharmony_ci		return -ENOMEM;
66d722e3fbSopenharmony_ci
67d722e3fbSopenharmony_ci	gpu_context->dev = dev;
68d722e3fbSopenharmony_ci
69d722e3fbSopenharmony_ci	r = pthread_mutex_init(&gpu_context->sequence_mutex, NULL);
70d722e3fbSopenharmony_ci	if (r)
71d722e3fbSopenharmony_ci		goto error;
72d722e3fbSopenharmony_ci
73d722e3fbSopenharmony_ci	/* Create the context */
74d722e3fbSopenharmony_ci	memset(&args, 0, sizeof(args));
75d722e3fbSopenharmony_ci	args.in.op = AMDGPU_CTX_OP_ALLOC_CTX;
76d722e3fbSopenharmony_ci	args.in.priority = priority;
77d722e3fbSopenharmony_ci
78d722e3fbSopenharmony_ci	r = drmCommandWriteRead(dev->fd, DRM_AMDGPU_CTX, &args, sizeof(args));
79d722e3fbSopenharmony_ci	if (r)
80d722e3fbSopenharmony_ci		goto error;
81d722e3fbSopenharmony_ci
82d722e3fbSopenharmony_ci	gpu_context->id = args.out.alloc.ctx_id;
83d722e3fbSopenharmony_ci	for (i = 0; i < AMDGPU_HW_IP_NUM; i++)
84d722e3fbSopenharmony_ci		for (j = 0; j < AMDGPU_HW_IP_INSTANCE_MAX_COUNT; j++)
85d722e3fbSopenharmony_ci			for (k = 0; k < AMDGPU_CS_MAX_RINGS; k++)
86d722e3fbSopenharmony_ci				list_inithead(&gpu_context->sem_list[i][j][k]);
87d722e3fbSopenharmony_ci	*context = (amdgpu_context_handle)gpu_context;
88d722e3fbSopenharmony_ci
89d722e3fbSopenharmony_ci	return 0;
90d722e3fbSopenharmony_ci
91d722e3fbSopenharmony_cierror:
92d722e3fbSopenharmony_ci	pthread_mutex_destroy(&gpu_context->sequence_mutex);
93d722e3fbSopenharmony_ci	free(gpu_context);
94d722e3fbSopenharmony_ci	return r;
95d722e3fbSopenharmony_ci}
96d722e3fbSopenharmony_ci
97d722e3fbSopenharmony_cidrm_public int amdgpu_cs_ctx_create(amdgpu_device_handle dev,
98d722e3fbSopenharmony_ci				    amdgpu_context_handle *context)
99d722e3fbSopenharmony_ci{
100d722e3fbSopenharmony_ci	return amdgpu_cs_ctx_create2(dev, AMDGPU_CTX_PRIORITY_NORMAL, context);
101d722e3fbSopenharmony_ci}
102d722e3fbSopenharmony_ci
103d722e3fbSopenharmony_ci/**
104d722e3fbSopenharmony_ci * Release command submission context
105d722e3fbSopenharmony_ci *
106d722e3fbSopenharmony_ci * \param   dev - \c [in] amdgpu device handle
107d722e3fbSopenharmony_ci * \param   context - \c [in] amdgpu context handle
108d722e3fbSopenharmony_ci *
109d722e3fbSopenharmony_ci * \return  0 on success otherwise POSIX Error code
110d722e3fbSopenharmony_ci*/
111d722e3fbSopenharmony_cidrm_public int amdgpu_cs_ctx_free(amdgpu_context_handle context)
112d722e3fbSopenharmony_ci{
113d722e3fbSopenharmony_ci	union drm_amdgpu_ctx args;
114d722e3fbSopenharmony_ci	int i, j, k;
115d722e3fbSopenharmony_ci	int r;
116d722e3fbSopenharmony_ci
117d722e3fbSopenharmony_ci	if (!context)
118d722e3fbSopenharmony_ci		return -EINVAL;
119d722e3fbSopenharmony_ci
120d722e3fbSopenharmony_ci	pthread_mutex_destroy(&context->sequence_mutex);
121d722e3fbSopenharmony_ci
122d722e3fbSopenharmony_ci	/* now deal with kernel side */
123d722e3fbSopenharmony_ci	memset(&args, 0, sizeof(args));
124d722e3fbSopenharmony_ci	args.in.op = AMDGPU_CTX_OP_FREE_CTX;
125d722e3fbSopenharmony_ci	args.in.ctx_id = context->id;
126d722e3fbSopenharmony_ci	r = drmCommandWriteRead(context->dev->fd, DRM_AMDGPU_CTX,
127d722e3fbSopenharmony_ci				&args, sizeof(args));
128d722e3fbSopenharmony_ci	for (i = 0; i < AMDGPU_HW_IP_NUM; i++) {
129d722e3fbSopenharmony_ci		for (j = 0; j < AMDGPU_HW_IP_INSTANCE_MAX_COUNT; j++) {
130d722e3fbSopenharmony_ci			for (k = 0; k < AMDGPU_CS_MAX_RINGS; k++) {
131d722e3fbSopenharmony_ci				amdgpu_semaphore_handle sem;
132d722e3fbSopenharmony_ci				LIST_FOR_EACH_ENTRY(sem, &context->sem_list[i][j][k], list) {
133d722e3fbSopenharmony_ci					list_del(&sem->list);
134d722e3fbSopenharmony_ci					amdgpu_cs_reset_sem(sem);
135d722e3fbSopenharmony_ci					amdgpu_cs_unreference_sem(sem);
136d722e3fbSopenharmony_ci				}
137d722e3fbSopenharmony_ci			}
138d722e3fbSopenharmony_ci		}
139d722e3fbSopenharmony_ci	}
140d722e3fbSopenharmony_ci	free(context);
141d722e3fbSopenharmony_ci
142d722e3fbSopenharmony_ci	return r;
143d722e3fbSopenharmony_ci}
144d722e3fbSopenharmony_ci
145d722e3fbSopenharmony_cidrm_public int amdgpu_cs_ctx_override_priority(amdgpu_device_handle dev,
146d722e3fbSopenharmony_ci                                               amdgpu_context_handle context,
147d722e3fbSopenharmony_ci                                               int master_fd,
148d722e3fbSopenharmony_ci                                               unsigned priority)
149d722e3fbSopenharmony_ci{
150d722e3fbSopenharmony_ci	union drm_amdgpu_sched args;
151d722e3fbSopenharmony_ci	int r;
152d722e3fbSopenharmony_ci
153d722e3fbSopenharmony_ci	if (!dev || !context || master_fd < 0)
154d722e3fbSopenharmony_ci		return -EINVAL;
155d722e3fbSopenharmony_ci
156d722e3fbSopenharmony_ci	memset(&args, 0, sizeof(args));
157d722e3fbSopenharmony_ci
158d722e3fbSopenharmony_ci	args.in.op = AMDGPU_SCHED_OP_CONTEXT_PRIORITY_OVERRIDE;
159d722e3fbSopenharmony_ci	args.in.fd = dev->fd;
160d722e3fbSopenharmony_ci	args.in.priority = priority;
161d722e3fbSopenharmony_ci	args.in.ctx_id = context->id;
162d722e3fbSopenharmony_ci
163d722e3fbSopenharmony_ci	r = drmCommandWrite(master_fd, DRM_AMDGPU_SCHED, &args, sizeof(args));
164d722e3fbSopenharmony_ci	if (r)
165d722e3fbSopenharmony_ci		return r;
166d722e3fbSopenharmony_ci
167d722e3fbSopenharmony_ci	return 0;
168d722e3fbSopenharmony_ci}
169d722e3fbSopenharmony_ci
170d722e3fbSopenharmony_cidrm_public int amdgpu_cs_ctx_stable_pstate(amdgpu_context_handle context,
171d722e3fbSopenharmony_ci					   uint32_t op,
172d722e3fbSopenharmony_ci					   uint32_t flags,
173d722e3fbSopenharmony_ci					   uint32_t *out_flags)
174d722e3fbSopenharmony_ci{
175d722e3fbSopenharmony_ci	union drm_amdgpu_ctx args;
176d722e3fbSopenharmony_ci	int r;
177d722e3fbSopenharmony_ci
178d722e3fbSopenharmony_ci	if (!context)
179d722e3fbSopenharmony_ci		return -EINVAL;
180d722e3fbSopenharmony_ci
181d722e3fbSopenharmony_ci	memset(&args, 0, sizeof(args));
182d722e3fbSopenharmony_ci	args.in.op = op;
183d722e3fbSopenharmony_ci	args.in.ctx_id = context->id;
184d722e3fbSopenharmony_ci	args.in.flags = flags;
185d722e3fbSopenharmony_ci	r = drmCommandWriteRead(context->dev->fd, DRM_AMDGPU_CTX,
186d722e3fbSopenharmony_ci				&args, sizeof(args));
187d722e3fbSopenharmony_ci	if (!r && out_flags)
188d722e3fbSopenharmony_ci		*out_flags = args.out.pstate.flags;
189d722e3fbSopenharmony_ci	return r;
190d722e3fbSopenharmony_ci}
191d722e3fbSopenharmony_ci
192d722e3fbSopenharmony_cidrm_public int amdgpu_cs_query_reset_state(amdgpu_context_handle context,
193d722e3fbSopenharmony_ci					   uint32_t *state, uint32_t *hangs)
194d722e3fbSopenharmony_ci{
195d722e3fbSopenharmony_ci	union drm_amdgpu_ctx args;
196d722e3fbSopenharmony_ci	int r;
197d722e3fbSopenharmony_ci
198d722e3fbSopenharmony_ci	if (!context)
199d722e3fbSopenharmony_ci		return -EINVAL;
200d722e3fbSopenharmony_ci
201d722e3fbSopenharmony_ci	memset(&args, 0, sizeof(args));
202d722e3fbSopenharmony_ci	args.in.op = AMDGPU_CTX_OP_QUERY_STATE;
203d722e3fbSopenharmony_ci	args.in.ctx_id = context->id;
204d722e3fbSopenharmony_ci	r = drmCommandWriteRead(context->dev->fd, DRM_AMDGPU_CTX,
205d722e3fbSopenharmony_ci				&args, sizeof(args));
206d722e3fbSopenharmony_ci	if (!r) {
207d722e3fbSopenharmony_ci		*state = args.out.state.reset_status;
208d722e3fbSopenharmony_ci		*hangs = args.out.state.hangs;
209d722e3fbSopenharmony_ci	}
210d722e3fbSopenharmony_ci	return r;
211d722e3fbSopenharmony_ci}
212d722e3fbSopenharmony_ci
213d722e3fbSopenharmony_cidrm_public int amdgpu_cs_query_reset_state2(amdgpu_context_handle context,
214d722e3fbSopenharmony_ci					    uint64_t *flags)
215d722e3fbSopenharmony_ci{
216d722e3fbSopenharmony_ci	union drm_amdgpu_ctx args;
217d722e3fbSopenharmony_ci	int r;
218d722e3fbSopenharmony_ci
219d722e3fbSopenharmony_ci	if (!context)
220d722e3fbSopenharmony_ci		return -EINVAL;
221d722e3fbSopenharmony_ci
222d722e3fbSopenharmony_ci	memset(&args, 0, sizeof(args));
223d722e3fbSopenharmony_ci	args.in.op = AMDGPU_CTX_OP_QUERY_STATE2;
224d722e3fbSopenharmony_ci	args.in.ctx_id = context->id;
225d722e3fbSopenharmony_ci	r = drmCommandWriteRead(context->dev->fd, DRM_AMDGPU_CTX,
226d722e3fbSopenharmony_ci				&args, sizeof(args));
227d722e3fbSopenharmony_ci	if (!r)
228d722e3fbSopenharmony_ci		*flags = args.out.state.flags;
229d722e3fbSopenharmony_ci	return r;
230d722e3fbSopenharmony_ci}
231d722e3fbSopenharmony_ci
232d722e3fbSopenharmony_ci/**
233d722e3fbSopenharmony_ci * Submit command to kernel DRM
234d722e3fbSopenharmony_ci * \param   dev - \c [in]  Device handle
235d722e3fbSopenharmony_ci * \param   context - \c [in]  GPU Context
236d722e3fbSopenharmony_ci * \param   ibs_request - \c [in]  Pointer to submission requests
237d722e3fbSopenharmony_ci * \param   fence - \c [out] return fence for this submission
238d722e3fbSopenharmony_ci *
239d722e3fbSopenharmony_ci * \return  0 on success otherwise POSIX Error code
240d722e3fbSopenharmony_ci * \sa amdgpu_cs_submit()
241d722e3fbSopenharmony_ci*/
242d722e3fbSopenharmony_cistatic int amdgpu_cs_submit_one(amdgpu_context_handle context,
243d722e3fbSopenharmony_ci				struct amdgpu_cs_request *ibs_request)
244d722e3fbSopenharmony_ci{
245d722e3fbSopenharmony_ci	struct drm_amdgpu_cs_chunk *chunks;
246d722e3fbSopenharmony_ci	struct drm_amdgpu_cs_chunk_data *chunk_data;
247d722e3fbSopenharmony_ci	struct drm_amdgpu_cs_chunk_dep *dependencies = NULL;
248d722e3fbSopenharmony_ci	struct drm_amdgpu_cs_chunk_dep *sem_dependencies = NULL;
249d722e3fbSopenharmony_ci	amdgpu_device_handle dev = context->dev;
250d722e3fbSopenharmony_ci	struct list_head *sem_list;
251d722e3fbSopenharmony_ci	amdgpu_semaphore_handle sem, tmp;
252d722e3fbSopenharmony_ci	uint32_t i, size, num_chunks, bo_list_handle = 0, sem_count = 0;
253d722e3fbSopenharmony_ci	uint64_t seq_no;
254d722e3fbSopenharmony_ci	bool user_fence;
255d722e3fbSopenharmony_ci	int r = 0;
256d722e3fbSopenharmony_ci
257d722e3fbSopenharmony_ci	if (ibs_request->ip_type >= AMDGPU_HW_IP_NUM)
258d722e3fbSopenharmony_ci		return -EINVAL;
259d722e3fbSopenharmony_ci	if (ibs_request->ring >= AMDGPU_CS_MAX_RINGS)
260d722e3fbSopenharmony_ci		return -EINVAL;
261d722e3fbSopenharmony_ci	if (ibs_request->number_of_ibs == 0) {
262d722e3fbSopenharmony_ci		ibs_request->seq_no = AMDGPU_NULL_SUBMIT_SEQ;
263d722e3fbSopenharmony_ci		return 0;
264d722e3fbSopenharmony_ci	}
265d722e3fbSopenharmony_ci	user_fence = (ibs_request->fence_info.handle != NULL);
266d722e3fbSopenharmony_ci
267d722e3fbSopenharmony_ci	size = ibs_request->number_of_ibs + (user_fence ? 2 : 1) + 1;
268d722e3fbSopenharmony_ci
269d722e3fbSopenharmony_ci	chunks = alloca(sizeof(struct drm_amdgpu_cs_chunk) * size);
270d722e3fbSopenharmony_ci
271d722e3fbSopenharmony_ci	size = ibs_request->number_of_ibs + (user_fence ? 1 : 0);
272d722e3fbSopenharmony_ci
273d722e3fbSopenharmony_ci	chunk_data = alloca(sizeof(struct drm_amdgpu_cs_chunk_data) * size);
274d722e3fbSopenharmony_ci
275d722e3fbSopenharmony_ci	if (ibs_request->resources)
276d722e3fbSopenharmony_ci		bo_list_handle = ibs_request->resources->handle;
277d722e3fbSopenharmony_ci	num_chunks = ibs_request->number_of_ibs;
278d722e3fbSopenharmony_ci	/* IB chunks */
279d722e3fbSopenharmony_ci	for (i = 0; i < ibs_request->number_of_ibs; i++) {
280d722e3fbSopenharmony_ci		struct amdgpu_cs_ib_info *ib;
281d722e3fbSopenharmony_ci		chunks[i].chunk_id = AMDGPU_CHUNK_ID_IB;
282d722e3fbSopenharmony_ci		chunks[i].length_dw = sizeof(struct drm_amdgpu_cs_chunk_ib) / 4;
283d722e3fbSopenharmony_ci		chunks[i].chunk_data = (uint64_t)(uintptr_t)&chunk_data[i];
284d722e3fbSopenharmony_ci
285d722e3fbSopenharmony_ci		ib = &ibs_request->ibs[i];
286d722e3fbSopenharmony_ci
287d722e3fbSopenharmony_ci		chunk_data[i].ib_data._pad = 0;
288d722e3fbSopenharmony_ci		chunk_data[i].ib_data.va_start = ib->ib_mc_address;
289d722e3fbSopenharmony_ci		chunk_data[i].ib_data.ib_bytes = ib->size * 4;
290d722e3fbSopenharmony_ci		chunk_data[i].ib_data.ip_type = ibs_request->ip_type;
291d722e3fbSopenharmony_ci		chunk_data[i].ib_data.ip_instance = ibs_request->ip_instance;
292d722e3fbSopenharmony_ci		chunk_data[i].ib_data.ring = ibs_request->ring;
293d722e3fbSopenharmony_ci		chunk_data[i].ib_data.flags = ib->flags;
294d722e3fbSopenharmony_ci	}
295d722e3fbSopenharmony_ci
296d722e3fbSopenharmony_ci	pthread_mutex_lock(&context->sequence_mutex);
297d722e3fbSopenharmony_ci
298d722e3fbSopenharmony_ci	if (user_fence) {
299d722e3fbSopenharmony_ci		i = num_chunks++;
300d722e3fbSopenharmony_ci
301d722e3fbSopenharmony_ci		/* fence chunk */
302d722e3fbSopenharmony_ci		chunks[i].chunk_id = AMDGPU_CHUNK_ID_FENCE;
303d722e3fbSopenharmony_ci		chunks[i].length_dw = sizeof(struct drm_amdgpu_cs_chunk_fence) / 4;
304d722e3fbSopenharmony_ci		chunks[i].chunk_data = (uint64_t)(uintptr_t)&chunk_data[i];
305d722e3fbSopenharmony_ci
306d722e3fbSopenharmony_ci		/* fence bo handle */
307d722e3fbSopenharmony_ci		chunk_data[i].fence_data.handle = ibs_request->fence_info.handle->handle;
308d722e3fbSopenharmony_ci		/* offset */
309d722e3fbSopenharmony_ci		chunk_data[i].fence_data.offset =
310d722e3fbSopenharmony_ci			ibs_request->fence_info.offset * sizeof(uint64_t);
311d722e3fbSopenharmony_ci	}
312d722e3fbSopenharmony_ci
313d722e3fbSopenharmony_ci	if (ibs_request->number_of_dependencies) {
314d722e3fbSopenharmony_ci		dependencies = alloca(sizeof(struct drm_amdgpu_cs_chunk_dep) *
315d722e3fbSopenharmony_ci			ibs_request->number_of_dependencies);
316d722e3fbSopenharmony_ci		if (!dependencies) {
317d722e3fbSopenharmony_ci			r = -ENOMEM;
318d722e3fbSopenharmony_ci			goto error_unlock;
319d722e3fbSopenharmony_ci		}
320d722e3fbSopenharmony_ci
321d722e3fbSopenharmony_ci		for (i = 0; i < ibs_request->number_of_dependencies; ++i) {
322d722e3fbSopenharmony_ci			struct amdgpu_cs_fence *info = &ibs_request->dependencies[i];
323d722e3fbSopenharmony_ci			struct drm_amdgpu_cs_chunk_dep *dep = &dependencies[i];
324d722e3fbSopenharmony_ci			dep->ip_type = info->ip_type;
325d722e3fbSopenharmony_ci			dep->ip_instance = info->ip_instance;
326d722e3fbSopenharmony_ci			dep->ring = info->ring;
327d722e3fbSopenharmony_ci			dep->ctx_id = info->context->id;
328d722e3fbSopenharmony_ci			dep->handle = info->fence;
329d722e3fbSopenharmony_ci		}
330d722e3fbSopenharmony_ci
331d722e3fbSopenharmony_ci		i = num_chunks++;
332d722e3fbSopenharmony_ci
333d722e3fbSopenharmony_ci		/* dependencies chunk */
334d722e3fbSopenharmony_ci		chunks[i].chunk_id = AMDGPU_CHUNK_ID_DEPENDENCIES;
335d722e3fbSopenharmony_ci		chunks[i].length_dw = sizeof(struct drm_amdgpu_cs_chunk_dep) / 4
336d722e3fbSopenharmony_ci			* ibs_request->number_of_dependencies;
337d722e3fbSopenharmony_ci		chunks[i].chunk_data = (uint64_t)(uintptr_t)dependencies;
338d722e3fbSopenharmony_ci	}
339d722e3fbSopenharmony_ci
340d722e3fbSopenharmony_ci	sem_list = &context->sem_list[ibs_request->ip_type][ibs_request->ip_instance][ibs_request->ring];
341d722e3fbSopenharmony_ci	LIST_FOR_EACH_ENTRY(sem, sem_list, list)
342d722e3fbSopenharmony_ci		sem_count++;
343d722e3fbSopenharmony_ci	if (sem_count) {
344d722e3fbSopenharmony_ci		sem_dependencies = alloca(sizeof(struct drm_amdgpu_cs_chunk_dep) * sem_count);
345d722e3fbSopenharmony_ci		if (!sem_dependencies) {
346d722e3fbSopenharmony_ci			r = -ENOMEM;
347d722e3fbSopenharmony_ci			goto error_unlock;
348d722e3fbSopenharmony_ci		}
349d722e3fbSopenharmony_ci		sem_count = 0;
350d722e3fbSopenharmony_ci		LIST_FOR_EACH_ENTRY_SAFE(sem, tmp, sem_list, list) {
351d722e3fbSopenharmony_ci			struct amdgpu_cs_fence *info = &sem->signal_fence;
352d722e3fbSopenharmony_ci			struct drm_amdgpu_cs_chunk_dep *dep = &sem_dependencies[sem_count++];
353d722e3fbSopenharmony_ci			dep->ip_type = info->ip_type;
354d722e3fbSopenharmony_ci			dep->ip_instance = info->ip_instance;
355d722e3fbSopenharmony_ci			dep->ring = info->ring;
356d722e3fbSopenharmony_ci			dep->ctx_id = info->context->id;
357d722e3fbSopenharmony_ci			dep->handle = info->fence;
358d722e3fbSopenharmony_ci
359d722e3fbSopenharmony_ci			list_del(&sem->list);
360d722e3fbSopenharmony_ci			amdgpu_cs_reset_sem(sem);
361d722e3fbSopenharmony_ci			amdgpu_cs_unreference_sem(sem);
362d722e3fbSopenharmony_ci		}
363d722e3fbSopenharmony_ci		i = num_chunks++;
364d722e3fbSopenharmony_ci
365d722e3fbSopenharmony_ci		/* dependencies chunk */
366d722e3fbSopenharmony_ci		chunks[i].chunk_id = AMDGPU_CHUNK_ID_DEPENDENCIES;
367d722e3fbSopenharmony_ci		chunks[i].length_dw = sizeof(struct drm_amdgpu_cs_chunk_dep) / 4 * sem_count;
368d722e3fbSopenharmony_ci		chunks[i].chunk_data = (uint64_t)(uintptr_t)sem_dependencies;
369d722e3fbSopenharmony_ci	}
370d722e3fbSopenharmony_ci
371d722e3fbSopenharmony_ci	r = amdgpu_cs_submit_raw2(dev, context, bo_list_handle, num_chunks,
372d722e3fbSopenharmony_ci				  chunks, &seq_no);
373d722e3fbSopenharmony_ci	if (r)
374d722e3fbSopenharmony_ci		goto error_unlock;
375d722e3fbSopenharmony_ci
376d722e3fbSopenharmony_ci	ibs_request->seq_no = seq_no;
377d722e3fbSopenharmony_ci	context->last_seq[ibs_request->ip_type][ibs_request->ip_instance][ibs_request->ring] = ibs_request->seq_no;
378d722e3fbSopenharmony_cierror_unlock:
379d722e3fbSopenharmony_ci	pthread_mutex_unlock(&context->sequence_mutex);
380d722e3fbSopenharmony_ci	return r;
381d722e3fbSopenharmony_ci}
382d722e3fbSopenharmony_ci
383d722e3fbSopenharmony_cidrm_public int amdgpu_cs_submit(amdgpu_context_handle context,
384d722e3fbSopenharmony_ci				uint64_t flags,
385d722e3fbSopenharmony_ci				struct amdgpu_cs_request *ibs_request,
386d722e3fbSopenharmony_ci				uint32_t number_of_requests)
387d722e3fbSopenharmony_ci{
388d722e3fbSopenharmony_ci	uint32_t i;
389d722e3fbSopenharmony_ci	int r;
390d722e3fbSopenharmony_ci
391d722e3fbSopenharmony_ci	if (!context || !ibs_request)
392d722e3fbSopenharmony_ci		return -EINVAL;
393d722e3fbSopenharmony_ci
394d722e3fbSopenharmony_ci	r = 0;
395d722e3fbSopenharmony_ci	for (i = 0; i < number_of_requests; i++) {
396d722e3fbSopenharmony_ci		r = amdgpu_cs_submit_one(context, ibs_request);
397d722e3fbSopenharmony_ci		if (r)
398d722e3fbSopenharmony_ci			break;
399d722e3fbSopenharmony_ci		ibs_request++;
400d722e3fbSopenharmony_ci	}
401d722e3fbSopenharmony_ci
402d722e3fbSopenharmony_ci	return r;
403d722e3fbSopenharmony_ci}
404d722e3fbSopenharmony_ci
405d722e3fbSopenharmony_ci/**
406d722e3fbSopenharmony_ci * Calculate absolute timeout.
407d722e3fbSopenharmony_ci *
408d722e3fbSopenharmony_ci * \param   timeout - \c [in] timeout in nanoseconds.
409d722e3fbSopenharmony_ci *
410d722e3fbSopenharmony_ci * \return  absolute timeout in nanoseconds
411d722e3fbSopenharmony_ci*/
412d722e3fbSopenharmony_cidrm_private uint64_t amdgpu_cs_calculate_timeout(uint64_t timeout)
413d722e3fbSopenharmony_ci{
414d722e3fbSopenharmony_ci	int r;
415d722e3fbSopenharmony_ci
416d722e3fbSopenharmony_ci	if (timeout != AMDGPU_TIMEOUT_INFINITE) {
417d722e3fbSopenharmony_ci		struct timespec current;
418d722e3fbSopenharmony_ci		uint64_t current_ns;
419d722e3fbSopenharmony_ci		r = clock_gettime(CLOCK_MONOTONIC, &current);
420d722e3fbSopenharmony_ci		if (r) {
421d722e3fbSopenharmony_ci			fprintf(stderr, "clock_gettime() returned error (%d)!", errno);
422d722e3fbSopenharmony_ci			return AMDGPU_TIMEOUT_INFINITE;
423d722e3fbSopenharmony_ci		}
424d722e3fbSopenharmony_ci
425d722e3fbSopenharmony_ci		current_ns = ((uint64_t)current.tv_sec) * 1000000000ull;
426d722e3fbSopenharmony_ci		current_ns += current.tv_nsec;
427d722e3fbSopenharmony_ci		timeout += current_ns;
428d722e3fbSopenharmony_ci		if (timeout < current_ns)
429d722e3fbSopenharmony_ci			timeout = AMDGPU_TIMEOUT_INFINITE;
430d722e3fbSopenharmony_ci	}
431d722e3fbSopenharmony_ci	return timeout;
432d722e3fbSopenharmony_ci}
433d722e3fbSopenharmony_ci
434d722e3fbSopenharmony_cistatic int amdgpu_ioctl_wait_cs(amdgpu_context_handle context,
435d722e3fbSopenharmony_ci				unsigned ip,
436d722e3fbSopenharmony_ci				unsigned ip_instance,
437d722e3fbSopenharmony_ci				uint32_t ring,
438d722e3fbSopenharmony_ci				uint64_t handle,
439d722e3fbSopenharmony_ci				uint64_t timeout_ns,
440d722e3fbSopenharmony_ci				uint64_t flags,
441d722e3fbSopenharmony_ci				bool *busy)
442d722e3fbSopenharmony_ci{
443d722e3fbSopenharmony_ci	amdgpu_device_handle dev = context->dev;
444d722e3fbSopenharmony_ci	union drm_amdgpu_wait_cs args;
445d722e3fbSopenharmony_ci	int r;
446d722e3fbSopenharmony_ci
447d722e3fbSopenharmony_ci	memset(&args, 0, sizeof(args));
448d722e3fbSopenharmony_ci	args.in.handle = handle;
449d722e3fbSopenharmony_ci	args.in.ip_type = ip;
450d722e3fbSopenharmony_ci	args.in.ip_instance = ip_instance;
451d722e3fbSopenharmony_ci	args.in.ring = ring;
452d722e3fbSopenharmony_ci	args.in.ctx_id = context->id;
453d722e3fbSopenharmony_ci
454d722e3fbSopenharmony_ci	if (flags & AMDGPU_QUERY_FENCE_TIMEOUT_IS_ABSOLUTE)
455d722e3fbSopenharmony_ci		args.in.timeout = timeout_ns;
456d722e3fbSopenharmony_ci	else
457d722e3fbSopenharmony_ci		args.in.timeout = amdgpu_cs_calculate_timeout(timeout_ns);
458d722e3fbSopenharmony_ci
459d722e3fbSopenharmony_ci	r = drmIoctl(dev->fd, DRM_IOCTL_AMDGPU_WAIT_CS, &args);
460d722e3fbSopenharmony_ci	if (r)
461d722e3fbSopenharmony_ci		return -errno;
462d722e3fbSopenharmony_ci
463d722e3fbSopenharmony_ci	*busy = args.out.status;
464d722e3fbSopenharmony_ci	return 0;
465d722e3fbSopenharmony_ci}
466d722e3fbSopenharmony_ci
467d722e3fbSopenharmony_cidrm_public int amdgpu_cs_query_fence_status(struct amdgpu_cs_fence *fence,
468d722e3fbSopenharmony_ci					    uint64_t timeout_ns,
469d722e3fbSopenharmony_ci					    uint64_t flags,
470d722e3fbSopenharmony_ci					    uint32_t *expired)
471d722e3fbSopenharmony_ci{
472d722e3fbSopenharmony_ci	bool busy = true;
473d722e3fbSopenharmony_ci	int r;
474d722e3fbSopenharmony_ci
475d722e3fbSopenharmony_ci	if (!fence || !expired || !fence->context)
476d722e3fbSopenharmony_ci		return -EINVAL;
477d722e3fbSopenharmony_ci	if (fence->ip_type >= AMDGPU_HW_IP_NUM)
478d722e3fbSopenharmony_ci		return -EINVAL;
479d722e3fbSopenharmony_ci	if (fence->ring >= AMDGPU_CS_MAX_RINGS)
480d722e3fbSopenharmony_ci		return -EINVAL;
481d722e3fbSopenharmony_ci	if (fence->fence == AMDGPU_NULL_SUBMIT_SEQ) {
482d722e3fbSopenharmony_ci		*expired = true;
483d722e3fbSopenharmony_ci		return 0;
484d722e3fbSopenharmony_ci	}
485d722e3fbSopenharmony_ci
486d722e3fbSopenharmony_ci	*expired = false;
487d722e3fbSopenharmony_ci
488d722e3fbSopenharmony_ci	r = amdgpu_ioctl_wait_cs(fence->context, fence->ip_type,
489d722e3fbSopenharmony_ci				fence->ip_instance, fence->ring,
490d722e3fbSopenharmony_ci			       	fence->fence, timeout_ns, flags, &busy);
491d722e3fbSopenharmony_ci
492d722e3fbSopenharmony_ci	if (!r && !busy)
493d722e3fbSopenharmony_ci		*expired = true;
494d722e3fbSopenharmony_ci
495d722e3fbSopenharmony_ci	return r;
496d722e3fbSopenharmony_ci}
497d722e3fbSopenharmony_ci
498d722e3fbSopenharmony_cistatic int amdgpu_ioctl_wait_fences(struct amdgpu_cs_fence *fences,
499d722e3fbSopenharmony_ci				    uint32_t fence_count,
500d722e3fbSopenharmony_ci				    bool wait_all,
501d722e3fbSopenharmony_ci				    uint64_t timeout_ns,
502d722e3fbSopenharmony_ci				    uint32_t *status,
503d722e3fbSopenharmony_ci				    uint32_t *first)
504d722e3fbSopenharmony_ci{
505d722e3fbSopenharmony_ci	struct drm_amdgpu_fence *drm_fences;
506d722e3fbSopenharmony_ci	amdgpu_device_handle dev = fences[0].context->dev;
507d722e3fbSopenharmony_ci	union drm_amdgpu_wait_fences args;
508d722e3fbSopenharmony_ci	int r;
509d722e3fbSopenharmony_ci	uint32_t i;
510d722e3fbSopenharmony_ci
511d722e3fbSopenharmony_ci	drm_fences = alloca(sizeof(struct drm_amdgpu_fence) * fence_count);
512d722e3fbSopenharmony_ci	for (i = 0; i < fence_count; i++) {
513d722e3fbSopenharmony_ci		drm_fences[i].ctx_id = fences[i].context->id;
514d722e3fbSopenharmony_ci		drm_fences[i].ip_type = fences[i].ip_type;
515d722e3fbSopenharmony_ci		drm_fences[i].ip_instance = fences[i].ip_instance;
516d722e3fbSopenharmony_ci		drm_fences[i].ring = fences[i].ring;
517d722e3fbSopenharmony_ci		drm_fences[i].seq_no = fences[i].fence;
518d722e3fbSopenharmony_ci	}
519d722e3fbSopenharmony_ci
520d722e3fbSopenharmony_ci	memset(&args, 0, sizeof(args));
521d722e3fbSopenharmony_ci	args.in.fences = (uint64_t)(uintptr_t)drm_fences;
522d722e3fbSopenharmony_ci	args.in.fence_count = fence_count;
523d722e3fbSopenharmony_ci	args.in.wait_all = wait_all;
524d722e3fbSopenharmony_ci	args.in.timeout_ns = amdgpu_cs_calculate_timeout(timeout_ns);
525d722e3fbSopenharmony_ci
526d722e3fbSopenharmony_ci	r = drmIoctl(dev->fd, DRM_IOCTL_AMDGPU_WAIT_FENCES, &args);
527d722e3fbSopenharmony_ci	if (r)
528d722e3fbSopenharmony_ci		return -errno;
529d722e3fbSopenharmony_ci
530d722e3fbSopenharmony_ci	*status = args.out.status;
531d722e3fbSopenharmony_ci
532d722e3fbSopenharmony_ci	if (first)
533d722e3fbSopenharmony_ci		*first = args.out.first_signaled;
534d722e3fbSopenharmony_ci
535d722e3fbSopenharmony_ci	return 0;
536d722e3fbSopenharmony_ci}
537d722e3fbSopenharmony_ci
538d722e3fbSopenharmony_cidrm_public int amdgpu_cs_wait_fences(struct amdgpu_cs_fence *fences,
539d722e3fbSopenharmony_ci				     uint32_t fence_count,
540d722e3fbSopenharmony_ci				     bool wait_all,
541d722e3fbSopenharmony_ci				     uint64_t timeout_ns,
542d722e3fbSopenharmony_ci				     uint32_t *status,
543d722e3fbSopenharmony_ci				     uint32_t *first)
544d722e3fbSopenharmony_ci{
545d722e3fbSopenharmony_ci	uint32_t i;
546d722e3fbSopenharmony_ci
547d722e3fbSopenharmony_ci	/* Sanity check */
548d722e3fbSopenharmony_ci	if (!fences || !status || !fence_count)
549d722e3fbSopenharmony_ci		return -EINVAL;
550d722e3fbSopenharmony_ci
551d722e3fbSopenharmony_ci	for (i = 0; i < fence_count; i++) {
552d722e3fbSopenharmony_ci		if (NULL == fences[i].context)
553d722e3fbSopenharmony_ci			return -EINVAL;
554d722e3fbSopenharmony_ci		if (fences[i].ip_type >= AMDGPU_HW_IP_NUM)
555d722e3fbSopenharmony_ci			return -EINVAL;
556d722e3fbSopenharmony_ci		if (fences[i].ring >= AMDGPU_CS_MAX_RINGS)
557d722e3fbSopenharmony_ci			return -EINVAL;
558d722e3fbSopenharmony_ci	}
559d722e3fbSopenharmony_ci
560d722e3fbSopenharmony_ci	*status = 0;
561d722e3fbSopenharmony_ci
562d722e3fbSopenharmony_ci	return amdgpu_ioctl_wait_fences(fences, fence_count, wait_all,
563d722e3fbSopenharmony_ci					timeout_ns, status, first);
564d722e3fbSopenharmony_ci}
565d722e3fbSopenharmony_ci
566d722e3fbSopenharmony_cidrm_public int amdgpu_cs_create_semaphore(amdgpu_semaphore_handle *sem)
567d722e3fbSopenharmony_ci{
568d722e3fbSopenharmony_ci	struct amdgpu_semaphore *gpu_semaphore;
569d722e3fbSopenharmony_ci
570d722e3fbSopenharmony_ci	if (!sem)
571d722e3fbSopenharmony_ci		return -EINVAL;
572d722e3fbSopenharmony_ci
573d722e3fbSopenharmony_ci	gpu_semaphore = calloc(1, sizeof(struct amdgpu_semaphore));
574d722e3fbSopenharmony_ci	if (!gpu_semaphore)
575d722e3fbSopenharmony_ci		return -ENOMEM;
576d722e3fbSopenharmony_ci
577d722e3fbSopenharmony_ci	atomic_set(&gpu_semaphore->refcount, 1);
578d722e3fbSopenharmony_ci	*sem = gpu_semaphore;
579d722e3fbSopenharmony_ci
580d722e3fbSopenharmony_ci	return 0;
581d722e3fbSopenharmony_ci}
582d722e3fbSopenharmony_ci
583d722e3fbSopenharmony_cidrm_public int amdgpu_cs_signal_semaphore(amdgpu_context_handle ctx,
584d722e3fbSopenharmony_ci					  uint32_t ip_type,
585d722e3fbSopenharmony_ci			       uint32_t ip_instance,
586d722e3fbSopenharmony_ci			       uint32_t ring,
587d722e3fbSopenharmony_ci			       amdgpu_semaphore_handle sem)
588d722e3fbSopenharmony_ci{
589d722e3fbSopenharmony_ci	if (!ctx || !sem)
590d722e3fbSopenharmony_ci		return -EINVAL;
591d722e3fbSopenharmony_ci	if (ip_type >= AMDGPU_HW_IP_NUM)
592d722e3fbSopenharmony_ci		return -EINVAL;
593d722e3fbSopenharmony_ci	if (ring >= AMDGPU_CS_MAX_RINGS)
594d722e3fbSopenharmony_ci		return -EINVAL;
595d722e3fbSopenharmony_ci	/* sem has been signaled */
596d722e3fbSopenharmony_ci	if (sem->signal_fence.context)
597d722e3fbSopenharmony_ci		return -EINVAL;
598d722e3fbSopenharmony_ci	pthread_mutex_lock(&ctx->sequence_mutex);
599d722e3fbSopenharmony_ci	sem->signal_fence.context = ctx;
600d722e3fbSopenharmony_ci	sem->signal_fence.ip_type = ip_type;
601d722e3fbSopenharmony_ci	sem->signal_fence.ip_instance = ip_instance;
602d722e3fbSopenharmony_ci	sem->signal_fence.ring = ring;
603d722e3fbSopenharmony_ci	sem->signal_fence.fence = ctx->last_seq[ip_type][ip_instance][ring];
604d722e3fbSopenharmony_ci	update_references(NULL, &sem->refcount);
605d722e3fbSopenharmony_ci	pthread_mutex_unlock(&ctx->sequence_mutex);
606d722e3fbSopenharmony_ci	return 0;
607d722e3fbSopenharmony_ci}
608d722e3fbSopenharmony_ci
609d722e3fbSopenharmony_cidrm_public int amdgpu_cs_wait_semaphore(amdgpu_context_handle ctx,
610d722e3fbSopenharmony_ci					uint32_t ip_type,
611d722e3fbSopenharmony_ci			     uint32_t ip_instance,
612d722e3fbSopenharmony_ci			     uint32_t ring,
613d722e3fbSopenharmony_ci			     amdgpu_semaphore_handle sem)
614d722e3fbSopenharmony_ci{
615d722e3fbSopenharmony_ci	if (!ctx || !sem)
616d722e3fbSopenharmony_ci		return -EINVAL;
617d722e3fbSopenharmony_ci	if (ip_type >= AMDGPU_HW_IP_NUM)
618d722e3fbSopenharmony_ci		return -EINVAL;
619d722e3fbSopenharmony_ci	if (ring >= AMDGPU_CS_MAX_RINGS)
620d722e3fbSopenharmony_ci		return -EINVAL;
621d722e3fbSopenharmony_ci	/* must signal first */
622d722e3fbSopenharmony_ci	if (!sem->signal_fence.context)
623d722e3fbSopenharmony_ci		return -EINVAL;
624d722e3fbSopenharmony_ci
625d722e3fbSopenharmony_ci	pthread_mutex_lock(&ctx->sequence_mutex);
626d722e3fbSopenharmony_ci	list_add(&sem->list, &ctx->sem_list[ip_type][ip_instance][ring]);
627d722e3fbSopenharmony_ci	pthread_mutex_unlock(&ctx->sequence_mutex);
628d722e3fbSopenharmony_ci	return 0;
629d722e3fbSopenharmony_ci}
630d722e3fbSopenharmony_ci
631d722e3fbSopenharmony_cistatic int amdgpu_cs_reset_sem(amdgpu_semaphore_handle sem)
632d722e3fbSopenharmony_ci{
633d722e3fbSopenharmony_ci	if (!sem || !sem->signal_fence.context)
634d722e3fbSopenharmony_ci		return -EINVAL;
635d722e3fbSopenharmony_ci
636d722e3fbSopenharmony_ci	sem->signal_fence.context = NULL;
637d722e3fbSopenharmony_ci	sem->signal_fence.ip_type = 0;
638d722e3fbSopenharmony_ci	sem->signal_fence.ip_instance = 0;
639d722e3fbSopenharmony_ci	sem->signal_fence.ring = 0;
640d722e3fbSopenharmony_ci	sem->signal_fence.fence = 0;
641d722e3fbSopenharmony_ci
642d722e3fbSopenharmony_ci	return 0;
643d722e3fbSopenharmony_ci}
644d722e3fbSopenharmony_ci
645d722e3fbSopenharmony_cistatic int amdgpu_cs_unreference_sem(amdgpu_semaphore_handle sem)
646d722e3fbSopenharmony_ci{
647d722e3fbSopenharmony_ci	if (!sem)
648d722e3fbSopenharmony_ci		return -EINVAL;
649d722e3fbSopenharmony_ci
650d722e3fbSopenharmony_ci	if (update_references(&sem->refcount, NULL))
651d722e3fbSopenharmony_ci		free(sem);
652d722e3fbSopenharmony_ci	return 0;
653d722e3fbSopenharmony_ci}
654d722e3fbSopenharmony_ci
655d722e3fbSopenharmony_cidrm_public int amdgpu_cs_destroy_semaphore(amdgpu_semaphore_handle sem)
656d722e3fbSopenharmony_ci{
657d722e3fbSopenharmony_ci	return amdgpu_cs_unreference_sem(sem);
658d722e3fbSopenharmony_ci}
659d722e3fbSopenharmony_ci
660d722e3fbSopenharmony_cidrm_public int amdgpu_cs_create_syncobj2(amdgpu_device_handle dev,
661d722e3fbSopenharmony_ci					 uint32_t  flags,
662d722e3fbSopenharmony_ci					 uint32_t *handle)
663d722e3fbSopenharmony_ci{
664d722e3fbSopenharmony_ci	if (NULL == dev)
665d722e3fbSopenharmony_ci		return -EINVAL;
666d722e3fbSopenharmony_ci
667d722e3fbSopenharmony_ci	return drmSyncobjCreate(dev->fd, flags, handle);
668d722e3fbSopenharmony_ci}
669d722e3fbSopenharmony_ci
670d722e3fbSopenharmony_cidrm_public int amdgpu_cs_create_syncobj(amdgpu_device_handle dev,
671d722e3fbSopenharmony_ci					uint32_t *handle)
672d722e3fbSopenharmony_ci{
673d722e3fbSopenharmony_ci	if (NULL == dev)
674d722e3fbSopenharmony_ci		return -EINVAL;
675d722e3fbSopenharmony_ci
676d722e3fbSopenharmony_ci	return drmSyncobjCreate(dev->fd, 0, handle);
677d722e3fbSopenharmony_ci}
678d722e3fbSopenharmony_ci
679d722e3fbSopenharmony_cidrm_public int amdgpu_cs_destroy_syncobj(amdgpu_device_handle dev,
680d722e3fbSopenharmony_ci					 uint32_t handle)
681d722e3fbSopenharmony_ci{
682d722e3fbSopenharmony_ci	if (NULL == dev)
683d722e3fbSopenharmony_ci		return -EINVAL;
684d722e3fbSopenharmony_ci
685d722e3fbSopenharmony_ci	return drmSyncobjDestroy(dev->fd, handle);
686d722e3fbSopenharmony_ci}
687d722e3fbSopenharmony_ci
688d722e3fbSopenharmony_cidrm_public int amdgpu_cs_syncobj_reset(amdgpu_device_handle dev,
689d722e3fbSopenharmony_ci				       const uint32_t *syncobjs,
690d722e3fbSopenharmony_ci				       uint32_t syncobj_count)
691d722e3fbSopenharmony_ci{
692d722e3fbSopenharmony_ci	if (NULL == dev)
693d722e3fbSopenharmony_ci		return -EINVAL;
694d722e3fbSopenharmony_ci
695d722e3fbSopenharmony_ci	return drmSyncobjReset(dev->fd, syncobjs, syncobj_count);
696d722e3fbSopenharmony_ci}
697d722e3fbSopenharmony_ci
698d722e3fbSopenharmony_cidrm_public int amdgpu_cs_syncobj_signal(amdgpu_device_handle dev,
699d722e3fbSopenharmony_ci					const uint32_t *syncobjs,
700d722e3fbSopenharmony_ci					uint32_t syncobj_count)
701d722e3fbSopenharmony_ci{
702d722e3fbSopenharmony_ci	if (NULL == dev)
703d722e3fbSopenharmony_ci		return -EINVAL;
704d722e3fbSopenharmony_ci
705d722e3fbSopenharmony_ci	return drmSyncobjSignal(dev->fd, syncobjs, syncobj_count);
706d722e3fbSopenharmony_ci}
707d722e3fbSopenharmony_ci
708d722e3fbSopenharmony_cidrm_public int amdgpu_cs_syncobj_timeline_signal(amdgpu_device_handle dev,
709d722e3fbSopenharmony_ci						 const uint32_t *syncobjs,
710d722e3fbSopenharmony_ci						 uint64_t *points,
711d722e3fbSopenharmony_ci						 uint32_t syncobj_count)
712d722e3fbSopenharmony_ci{
713d722e3fbSopenharmony_ci	if (NULL == dev)
714d722e3fbSopenharmony_ci		return -EINVAL;
715d722e3fbSopenharmony_ci
716d722e3fbSopenharmony_ci	return drmSyncobjTimelineSignal(dev->fd, syncobjs,
717d722e3fbSopenharmony_ci					points, syncobj_count);
718d722e3fbSopenharmony_ci}
719d722e3fbSopenharmony_ci
720d722e3fbSopenharmony_cidrm_public int amdgpu_cs_syncobj_wait(amdgpu_device_handle dev,
721d722e3fbSopenharmony_ci				      uint32_t *handles, unsigned num_handles,
722d722e3fbSopenharmony_ci				      int64_t timeout_nsec, unsigned flags,
723d722e3fbSopenharmony_ci				      uint32_t *first_signaled)
724d722e3fbSopenharmony_ci{
725d722e3fbSopenharmony_ci	if (NULL == dev)
726d722e3fbSopenharmony_ci		return -EINVAL;
727d722e3fbSopenharmony_ci
728d722e3fbSopenharmony_ci	return drmSyncobjWait(dev->fd, handles, num_handles, timeout_nsec,
729d722e3fbSopenharmony_ci			      flags, first_signaled);
730d722e3fbSopenharmony_ci}
731d722e3fbSopenharmony_ci
732d722e3fbSopenharmony_cidrm_public int amdgpu_cs_syncobj_timeline_wait(amdgpu_device_handle dev,
733d722e3fbSopenharmony_ci					       uint32_t *handles, uint64_t *points,
734d722e3fbSopenharmony_ci					       unsigned num_handles,
735d722e3fbSopenharmony_ci					       int64_t timeout_nsec, unsigned flags,
736d722e3fbSopenharmony_ci					       uint32_t *first_signaled)
737d722e3fbSopenharmony_ci{
738d722e3fbSopenharmony_ci	if (NULL == dev)
739d722e3fbSopenharmony_ci		return -EINVAL;
740d722e3fbSopenharmony_ci
741d722e3fbSopenharmony_ci	return drmSyncobjTimelineWait(dev->fd, handles, points, num_handles,
742d722e3fbSopenharmony_ci				      timeout_nsec, flags, first_signaled);
743d722e3fbSopenharmony_ci}
744d722e3fbSopenharmony_ci
745d722e3fbSopenharmony_cidrm_public int amdgpu_cs_syncobj_query(amdgpu_device_handle dev,
746d722e3fbSopenharmony_ci				       uint32_t *handles, uint64_t *points,
747d722e3fbSopenharmony_ci				       unsigned num_handles)
748d722e3fbSopenharmony_ci{
749d722e3fbSopenharmony_ci	if (NULL == dev)
750d722e3fbSopenharmony_ci		return -EINVAL;
751d722e3fbSopenharmony_ci
752d722e3fbSopenharmony_ci	return drmSyncobjQuery(dev->fd, handles, points, num_handles);
753d722e3fbSopenharmony_ci}
754d722e3fbSopenharmony_ci
755d722e3fbSopenharmony_cidrm_public int amdgpu_cs_syncobj_query2(amdgpu_device_handle dev,
756d722e3fbSopenharmony_ci					uint32_t *handles, uint64_t *points,
757d722e3fbSopenharmony_ci					unsigned num_handles, uint32_t flags)
758d722e3fbSopenharmony_ci{
759d722e3fbSopenharmony_ci	if (!dev)
760d722e3fbSopenharmony_ci		return -EINVAL;
761d722e3fbSopenharmony_ci
762d722e3fbSopenharmony_ci	return drmSyncobjQuery2(dev->fd, handles, points, num_handles, flags);
763d722e3fbSopenharmony_ci}
764d722e3fbSopenharmony_ci
765d722e3fbSopenharmony_cidrm_public int amdgpu_cs_export_syncobj(amdgpu_device_handle dev,
766d722e3fbSopenharmony_ci					uint32_t handle,
767d722e3fbSopenharmony_ci					int *shared_fd)
768d722e3fbSopenharmony_ci{
769d722e3fbSopenharmony_ci	if (NULL == dev)
770d722e3fbSopenharmony_ci		return -EINVAL;
771d722e3fbSopenharmony_ci
772d722e3fbSopenharmony_ci	return drmSyncobjHandleToFD(dev->fd, handle, shared_fd);
773d722e3fbSopenharmony_ci}
774d722e3fbSopenharmony_ci
775d722e3fbSopenharmony_cidrm_public int amdgpu_cs_import_syncobj(amdgpu_device_handle dev,
776d722e3fbSopenharmony_ci					int shared_fd,
777d722e3fbSopenharmony_ci					uint32_t *handle)
778d722e3fbSopenharmony_ci{
779d722e3fbSopenharmony_ci	if (NULL == dev)
780d722e3fbSopenharmony_ci		return -EINVAL;
781d722e3fbSopenharmony_ci
782d722e3fbSopenharmony_ci	return drmSyncobjFDToHandle(dev->fd, shared_fd, handle);
783d722e3fbSopenharmony_ci}
784d722e3fbSopenharmony_ci
785d722e3fbSopenharmony_cidrm_public int amdgpu_cs_syncobj_export_sync_file(amdgpu_device_handle dev,
786d722e3fbSopenharmony_ci						  uint32_t syncobj,
787d722e3fbSopenharmony_ci						  int *sync_file_fd)
788d722e3fbSopenharmony_ci{
789d722e3fbSopenharmony_ci	if (NULL == dev)
790d722e3fbSopenharmony_ci		return -EINVAL;
791d722e3fbSopenharmony_ci
792d722e3fbSopenharmony_ci	return drmSyncobjExportSyncFile(dev->fd, syncobj, sync_file_fd);
793d722e3fbSopenharmony_ci}
794d722e3fbSopenharmony_ci
795d722e3fbSopenharmony_cidrm_public int amdgpu_cs_syncobj_import_sync_file(amdgpu_device_handle dev,
796d722e3fbSopenharmony_ci						  uint32_t syncobj,
797d722e3fbSopenharmony_ci						  int sync_file_fd)
798d722e3fbSopenharmony_ci{
799d722e3fbSopenharmony_ci	if (NULL == dev)
800d722e3fbSopenharmony_ci		return -EINVAL;
801d722e3fbSopenharmony_ci
802d722e3fbSopenharmony_ci	return drmSyncobjImportSyncFile(dev->fd, syncobj, sync_file_fd);
803d722e3fbSopenharmony_ci}
804d722e3fbSopenharmony_ci
805d722e3fbSopenharmony_cidrm_public int amdgpu_cs_syncobj_export_sync_file2(amdgpu_device_handle dev,
806d722e3fbSopenharmony_ci						   uint32_t syncobj,
807d722e3fbSopenharmony_ci						   uint64_t point,
808d722e3fbSopenharmony_ci						   uint32_t flags,
809d722e3fbSopenharmony_ci						   int *sync_file_fd)
810d722e3fbSopenharmony_ci{
811d722e3fbSopenharmony_ci	uint32_t binary_handle;
812d722e3fbSopenharmony_ci	int ret;
813d722e3fbSopenharmony_ci
814d722e3fbSopenharmony_ci	if (NULL == dev)
815d722e3fbSopenharmony_ci		return -EINVAL;
816d722e3fbSopenharmony_ci
817d722e3fbSopenharmony_ci	if (!point)
818d722e3fbSopenharmony_ci		return drmSyncobjExportSyncFile(dev->fd, syncobj, sync_file_fd);
819d722e3fbSopenharmony_ci
820d722e3fbSopenharmony_ci	ret = drmSyncobjCreate(dev->fd, 0, &binary_handle);
821d722e3fbSopenharmony_ci	if (ret)
822d722e3fbSopenharmony_ci		return ret;
823d722e3fbSopenharmony_ci
824d722e3fbSopenharmony_ci	ret = drmSyncobjTransfer(dev->fd, binary_handle, 0,
825d722e3fbSopenharmony_ci				 syncobj, point, flags);
826d722e3fbSopenharmony_ci	if (ret)
827d722e3fbSopenharmony_ci		goto out;
828d722e3fbSopenharmony_ci	ret = drmSyncobjExportSyncFile(dev->fd, binary_handle, sync_file_fd);
829d722e3fbSopenharmony_ciout:
830d722e3fbSopenharmony_ci	drmSyncobjDestroy(dev->fd, binary_handle);
831d722e3fbSopenharmony_ci	return ret;
832d722e3fbSopenharmony_ci}
833d722e3fbSopenharmony_ci
834d722e3fbSopenharmony_cidrm_public int amdgpu_cs_syncobj_import_sync_file2(amdgpu_device_handle dev,
835d722e3fbSopenharmony_ci						   uint32_t syncobj,
836d722e3fbSopenharmony_ci						   uint64_t point,
837d722e3fbSopenharmony_ci						   int sync_file_fd)
838d722e3fbSopenharmony_ci{
839d722e3fbSopenharmony_ci	uint32_t binary_handle;
840d722e3fbSopenharmony_ci	int ret;
841d722e3fbSopenharmony_ci
842d722e3fbSopenharmony_ci	if (NULL == dev)
843d722e3fbSopenharmony_ci		return -EINVAL;
844d722e3fbSopenharmony_ci
845d722e3fbSopenharmony_ci	if (!point)
846d722e3fbSopenharmony_ci		return drmSyncobjImportSyncFile(dev->fd, syncobj, sync_file_fd);
847d722e3fbSopenharmony_ci
848d722e3fbSopenharmony_ci	ret = drmSyncobjCreate(dev->fd, 0, &binary_handle);
849d722e3fbSopenharmony_ci	if (ret)
850d722e3fbSopenharmony_ci		return ret;
851d722e3fbSopenharmony_ci	ret = drmSyncobjImportSyncFile(dev->fd, binary_handle, sync_file_fd);
852d722e3fbSopenharmony_ci	if (ret)
853d722e3fbSopenharmony_ci		goto out;
854d722e3fbSopenharmony_ci	ret = drmSyncobjTransfer(dev->fd, syncobj, point,
855d722e3fbSopenharmony_ci				 binary_handle, 0, 0);
856d722e3fbSopenharmony_ciout:
857d722e3fbSopenharmony_ci	drmSyncobjDestroy(dev->fd, binary_handle);
858d722e3fbSopenharmony_ci	return ret;
859d722e3fbSopenharmony_ci}
860d722e3fbSopenharmony_ci
861d722e3fbSopenharmony_cidrm_public int amdgpu_cs_syncobj_transfer(amdgpu_device_handle dev,
862d722e3fbSopenharmony_ci					  uint32_t dst_handle,
863d722e3fbSopenharmony_ci					  uint64_t dst_point,
864d722e3fbSopenharmony_ci					  uint32_t src_handle,
865d722e3fbSopenharmony_ci					  uint64_t src_point,
866d722e3fbSopenharmony_ci					  uint32_t flags)
867d722e3fbSopenharmony_ci{
868d722e3fbSopenharmony_ci	if (NULL == dev)
869d722e3fbSopenharmony_ci		return -EINVAL;
870d722e3fbSopenharmony_ci
871d722e3fbSopenharmony_ci	return drmSyncobjTransfer(dev->fd,
872d722e3fbSopenharmony_ci				  dst_handle, dst_point,
873d722e3fbSopenharmony_ci				  src_handle, src_point,
874d722e3fbSopenharmony_ci				  flags);
875d722e3fbSopenharmony_ci}
876d722e3fbSopenharmony_ci
877d722e3fbSopenharmony_cidrm_public int amdgpu_cs_submit_raw(amdgpu_device_handle dev,
878d722e3fbSopenharmony_ci				    amdgpu_context_handle context,
879d722e3fbSopenharmony_ci				    amdgpu_bo_list_handle bo_list_handle,
880d722e3fbSopenharmony_ci				    int num_chunks,
881d722e3fbSopenharmony_ci				    struct drm_amdgpu_cs_chunk *chunks,
882d722e3fbSopenharmony_ci				    uint64_t *seq_no)
883d722e3fbSopenharmony_ci{
884d722e3fbSopenharmony_ci	union drm_amdgpu_cs cs;
885d722e3fbSopenharmony_ci	uint64_t *chunk_array;
886d722e3fbSopenharmony_ci	int i, r;
887d722e3fbSopenharmony_ci	if (num_chunks == 0)
888d722e3fbSopenharmony_ci		return -EINVAL;
889d722e3fbSopenharmony_ci
890d722e3fbSopenharmony_ci	memset(&cs, 0, sizeof(cs));
891d722e3fbSopenharmony_ci	chunk_array = alloca(sizeof(uint64_t) * num_chunks);
892d722e3fbSopenharmony_ci	for (i = 0; i < num_chunks; i++)
893d722e3fbSopenharmony_ci		chunk_array[i] = (uint64_t)(uintptr_t)&chunks[i];
894d722e3fbSopenharmony_ci	cs.in.chunks = (uint64_t)(uintptr_t)chunk_array;
895d722e3fbSopenharmony_ci	cs.in.ctx_id = context->id;
896d722e3fbSopenharmony_ci	cs.in.bo_list_handle = bo_list_handle ? bo_list_handle->handle : 0;
897d722e3fbSopenharmony_ci	cs.in.num_chunks = num_chunks;
898d722e3fbSopenharmony_ci	r = drmCommandWriteRead(dev->fd, DRM_AMDGPU_CS,
899d722e3fbSopenharmony_ci				&cs, sizeof(cs));
900d722e3fbSopenharmony_ci	if (r)
901d722e3fbSopenharmony_ci		return r;
902d722e3fbSopenharmony_ci
903d722e3fbSopenharmony_ci	if (seq_no)
904d722e3fbSopenharmony_ci		*seq_no = cs.out.handle;
905d722e3fbSopenharmony_ci	return 0;
906d722e3fbSopenharmony_ci}
907d722e3fbSopenharmony_ci
908d722e3fbSopenharmony_cidrm_public int amdgpu_cs_submit_raw2(amdgpu_device_handle dev,
909d722e3fbSopenharmony_ci				     amdgpu_context_handle context,
910d722e3fbSopenharmony_ci				     uint32_t bo_list_handle,
911d722e3fbSopenharmony_ci				     int num_chunks,
912d722e3fbSopenharmony_ci				     struct drm_amdgpu_cs_chunk *chunks,
913d722e3fbSopenharmony_ci				     uint64_t *seq_no)
914d722e3fbSopenharmony_ci{
915d722e3fbSopenharmony_ci	union drm_amdgpu_cs cs;
916d722e3fbSopenharmony_ci	uint64_t *chunk_array;
917d722e3fbSopenharmony_ci	int i, r;
918d722e3fbSopenharmony_ci
919d722e3fbSopenharmony_ci	memset(&cs, 0, sizeof(cs));
920d722e3fbSopenharmony_ci	chunk_array = alloca(sizeof(uint64_t) * num_chunks);
921d722e3fbSopenharmony_ci	for (i = 0; i < num_chunks; i++)
922d722e3fbSopenharmony_ci		chunk_array[i] = (uint64_t)(uintptr_t)&chunks[i];
923d722e3fbSopenharmony_ci	cs.in.chunks = (uint64_t)(uintptr_t)chunk_array;
924d722e3fbSopenharmony_ci	cs.in.ctx_id = context->id;
925d722e3fbSopenharmony_ci	cs.in.bo_list_handle = bo_list_handle;
926d722e3fbSopenharmony_ci	cs.in.num_chunks = num_chunks;
927d722e3fbSopenharmony_ci	r = drmCommandWriteRead(dev->fd, DRM_AMDGPU_CS,
928d722e3fbSopenharmony_ci				&cs, sizeof(cs));
929d722e3fbSopenharmony_ci	if (!r && seq_no)
930d722e3fbSopenharmony_ci		*seq_no = cs.out.handle;
931d722e3fbSopenharmony_ci	return r;
932d722e3fbSopenharmony_ci}
933d722e3fbSopenharmony_ci
934d722e3fbSopenharmony_cidrm_public void amdgpu_cs_chunk_fence_info_to_data(struct amdgpu_cs_fence_info *fence_info,
935d722e3fbSopenharmony_ci					struct drm_amdgpu_cs_chunk_data *data)
936d722e3fbSopenharmony_ci{
937d722e3fbSopenharmony_ci	data->fence_data.handle = fence_info->handle->handle;
938d722e3fbSopenharmony_ci	data->fence_data.offset = fence_info->offset * sizeof(uint64_t);
939d722e3fbSopenharmony_ci}
940d722e3fbSopenharmony_ci
941d722e3fbSopenharmony_cidrm_public void amdgpu_cs_chunk_fence_to_dep(struct amdgpu_cs_fence *fence,
942d722e3fbSopenharmony_ci					struct drm_amdgpu_cs_chunk_dep *dep)
943d722e3fbSopenharmony_ci{
944d722e3fbSopenharmony_ci	dep->ip_type = fence->ip_type;
945d722e3fbSopenharmony_ci	dep->ip_instance = fence->ip_instance;
946d722e3fbSopenharmony_ci	dep->ring = fence->ring;
947d722e3fbSopenharmony_ci	dep->ctx_id = fence->context->id;
948d722e3fbSopenharmony_ci	dep->handle = fence->fence;
949d722e3fbSopenharmony_ci}
950d722e3fbSopenharmony_ci
951d722e3fbSopenharmony_cidrm_public int amdgpu_cs_fence_to_handle(amdgpu_device_handle dev,
952d722e3fbSopenharmony_ci					 struct amdgpu_cs_fence *fence,
953d722e3fbSopenharmony_ci					 uint32_t what,
954d722e3fbSopenharmony_ci					 uint32_t *out_handle)
955d722e3fbSopenharmony_ci{
956d722e3fbSopenharmony_ci	union drm_amdgpu_fence_to_handle fth;
957d722e3fbSopenharmony_ci	int r;
958d722e3fbSopenharmony_ci
959d722e3fbSopenharmony_ci	memset(&fth, 0, sizeof(fth));
960d722e3fbSopenharmony_ci	fth.in.fence.ctx_id = fence->context->id;
961d722e3fbSopenharmony_ci	fth.in.fence.ip_type = fence->ip_type;
962d722e3fbSopenharmony_ci	fth.in.fence.ip_instance = fence->ip_instance;
963d722e3fbSopenharmony_ci	fth.in.fence.ring = fence->ring;
964d722e3fbSopenharmony_ci	fth.in.fence.seq_no = fence->fence;
965d722e3fbSopenharmony_ci	fth.in.what = what;
966d722e3fbSopenharmony_ci
967d722e3fbSopenharmony_ci	r = drmCommandWriteRead(dev->fd, DRM_AMDGPU_FENCE_TO_HANDLE,
968d722e3fbSopenharmony_ci				&fth, sizeof(fth));
969d722e3fbSopenharmony_ci	if (r == 0)
970d722e3fbSopenharmony_ci		*out_handle = fth.out.handle;
971d722e3fbSopenharmony_ci	return r;
972d722e3fbSopenharmony_ci}
973