1 /*
2  * Copyright © 2017 Intel Corporation
3  *
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:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include <errno.h>
25 #include <xf86drm.h>
26 
27 #include "igt.h"
28 #include "igt_syncobj.h"
29 
30 /**
31  * SECTION:igt_syncobj
32  * @short_description: Library with syncobj helpers
33  * @title: syncobj
34  * @include: igt_syncobj.h
35  *
36  * This library contains helpers for sync object tests.
37  */
38 
39 static int
__syncobj_create(int fd,uint32_t * handle,uint32_t flags)40 __syncobj_create(int fd, uint32_t *handle, uint32_t flags)
41 {
42 	struct drm_syncobj_create create = { 0 };
43 	int err = 0;
44 
45 	create.flags = flags;
46 	if (drmIoctl(fd, DRM_IOCTL_SYNCOBJ_CREATE, &create))
47 		err = -errno;
48 	*handle = create.handle;
49 	return err;
50 }
51 
52 /**
53  * syncobj_create
54  * @fd: The DRM file descriptor
55  * @flags: Flags to pass syncobj create
56  *
57  * Create a syncobj with the flags.
58  *
59  * Returns: A newly created syncobj
60  */
61 uint32_t
syncobj_create(int fd,uint32_t flags)62 syncobj_create(int fd, uint32_t flags)
63 {
64 	uint32_t handle;
65 	igt_assert_eq(__syncobj_create(fd, &handle, flags), 0);
66 	igt_assert(handle);
67 	return handle;
68 }
69 
70 static int
__syncobj_destroy(int fd,uint32_t handle)71 __syncobj_destroy(int fd, uint32_t handle)
72 {
73 	struct drm_syncobj_destroy destroy = { 0 };
74 	int err = 0;
75 
76 	destroy.handle = handle;
77 	if (drmIoctl(fd, DRM_IOCTL_SYNCOBJ_DESTROY, &destroy))
78 		err = -errno;
79 	return err;
80 }
81 
82 /**
83  * syncobj_destroy:
84  * @fd: The DRM file descriptor
85  * @handle: The handle to the syncobj to destroy
86  * Destroy a syncobj.
87  */
88 void
syncobj_destroy(int fd,uint32_t handle)89 syncobj_destroy(int fd, uint32_t handle)
90 {
91 	igt_assert_eq(__syncobj_destroy(fd, handle), 0);
92 }
93 
94 int
__syncobj_handle_to_fd(int fd,struct drm_syncobj_handle * args)95 __syncobj_handle_to_fd(int fd, struct drm_syncobj_handle *args)
96 {
97 	int err = 0;
98 	if (drmIoctl(fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, args))
99 		err = -errno;
100 	return err;
101 }
102 
103 /**
104  * syncobj_handle_to_fd:
105  * @fd: The DRM file descriptor
106  * @handle: Handle to syncobj
107  * @flags: Flags to handle to fd ioctl.
108  *
109  * Convert a syncobj handle to an fd using the flags.
110  *
111  * Returns: a file descriptor (either syncobj or sync_file.
112  */
113 int
syncobj_handle_to_fd(int fd,uint32_t handle,uint32_t flags)114 syncobj_handle_to_fd(int fd, uint32_t handle, uint32_t flags)
115 {
116 	struct drm_syncobj_handle args = { 0 };
117 	args.handle = handle;
118 	args.flags = flags;
119 	igt_assert_eq(__syncobj_handle_to_fd(fd, &args), 0);
120 	igt_assert(args.fd >= 0);
121 	return args.fd;
122 }
123 
124 int
__syncobj_fd_to_handle(int fd,struct drm_syncobj_handle * args)125 __syncobj_fd_to_handle(int fd, struct drm_syncobj_handle *args)
126 {
127 	int err = 0;
128 	if (drmIoctl(fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, args))
129 		err = -errno;
130 	return err;
131 }
132 
133 /**
134  * syncobj_fd_to_handle:
135  * @fd: The DRM file descriptor
136  * @syncobj_fd: syncobj fd to convert
137  * @flags: Flags to the syncobj fd to handle ioctl.
138  *
139  * Convert a syncobj fd a syncobj handle using the flags.
140  *
141  * Returns: a syncobj handle.
142  */
143 uint32_t
syncobj_fd_to_handle(int fd,int syncobj_fd,uint32_t flags)144 syncobj_fd_to_handle(int fd, int syncobj_fd, uint32_t flags)
145 {
146 	struct drm_syncobj_handle args = { 0 };
147 	args.fd = syncobj_fd;
148 	args.flags = flags;
149 	igt_assert_eq(__syncobj_fd_to_handle(fd, &args), 0);
150 	igt_assert(args.handle > 0);
151 	return args.handle;
152 }
153 
154 /**
155  * syncobj_import_sync_file:
156  * @fd: The DRM file descriptor
157  * @handle: Handle to the syncobt to import file into
158  * @sync_file: The sync_file fd to import state from.
159  *
160  * Import a sync_file fd into a syncobj handle.
161  */
162 void
syncobj_import_sync_file(int fd,uint32_t handle,int sync_file)163 syncobj_import_sync_file(int fd, uint32_t handle, int sync_file)
164 {
165 	struct drm_syncobj_handle args = { 0 };
166 	args.handle = handle;
167 	args.fd = sync_file;
168 	args.flags = DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE;
169 	igt_assert_eq(__syncobj_fd_to_handle(fd, &args), 0);
170 }
171 
172 int
__syncobj_wait(int fd,struct local_syncobj_wait * args)173 __syncobj_wait(int fd, struct local_syncobj_wait *args)
174 {
175 	int err = 0;
176 	if (drmIoctl(fd, LOCAL_IOCTL_SYNCOBJ_WAIT, args))
177 		err = -errno;
178 	return err;
179 }
180 
181 int
syncobj_wait_err(int fd,uint32_t * handles,uint32_t count,uint64_t abs_timeout_nsec,uint32_t flags)182 syncobj_wait_err(int fd, uint32_t *handles, uint32_t count,
183 		 uint64_t abs_timeout_nsec, uint32_t flags)
184 {
185 	struct local_syncobj_wait wait;
186 
187 	wait.handles = to_user_pointer(handles);
188 	wait.timeout_nsec = abs_timeout_nsec;
189 	wait.count_handles = count;
190 	wait.flags = flags;
191 	wait.first_signaled = 0;
192 	wait.pad = 0;
193 
194 	return __syncobj_wait(fd, &wait);
195 }
196 
197 /**
198  * syncobj_wait:
199  * @fd: The DRM file descriptor
200  * @handles: List of syncobj handles to wait for.
201  * @count: Count of handles
202  * @abs_timeout_nsec: Absolute wait timeout in nanoseconds.
203  * @flags: Wait ioctl flags.
204  * @first_signaled: Returned handle for first signaled syncobj.
205  *
206  * Waits in the kernel for any/all the requested syncobjs
207  * using the timeout and flags.
208  * Returns: bool value - false = timedout, true = signaled
209  */
210 bool
syncobj_wait(int fd,uint32_t * handles,uint32_t count,uint64_t abs_timeout_nsec,uint32_t flags,uint32_t * first_signaled)211 syncobj_wait(int fd, uint32_t *handles, uint32_t count,
212 	     uint64_t abs_timeout_nsec, uint32_t flags,
213 	     uint32_t *first_signaled)
214 {
215 	struct local_syncobj_wait wait;
216 	int ret;
217 
218 	wait.handles = to_user_pointer(handles);
219 	wait.timeout_nsec = abs_timeout_nsec;
220 	wait.count_handles = count;
221 	wait.flags = flags;
222 	wait.first_signaled = 0;
223 	wait.pad = 0;
224 
225 	ret = __syncobj_wait(fd, &wait);
226 	if (ret == -ETIME)
227 		return false;
228 
229 	igt_assert_eq(ret, 0);
230 	if (first_signaled)
231 		*first_signaled = wait.first_signaled;
232 
233 	return true;
234 }
235 
236 static int
__syncobj_reset(int fd,uint32_t * handles,uint32_t count)237 __syncobj_reset(int fd, uint32_t *handles, uint32_t count)
238 {
239 	struct local_syncobj_array array = { 0 };
240 	int err = 0;
241 
242 	array.handles = to_user_pointer(handles);
243 	array.count_handles = count;
244 	if (drmIoctl(fd, LOCAL_IOCTL_SYNCOBJ_RESET, &array))
245 		err = -errno;
246 	return err;
247 }
248 
249 /**
250  * syncobj_reset:
251  * @fd: The DRM file descriptor.
252  * @handles: Array of syncobj handles to reset
253  * @count: Count of syncobj handles.
254  *
255  * Reset state of a set of syncobjs.
256  */
257 void
syncobj_reset(int fd,uint32_t * handles,uint32_t count)258 syncobj_reset(int fd, uint32_t *handles, uint32_t count)
259 {
260 	igt_assert_eq(__syncobj_reset(fd, handles, count), 0);
261 }
262 
263 static int
__syncobj_signal(int fd,uint32_t * handles,uint32_t count)264 __syncobj_signal(int fd, uint32_t *handles, uint32_t count)
265 {
266 	struct local_syncobj_array array = { 0 };
267 	int err = 0;
268 
269 	array.handles = to_user_pointer(handles);
270 	array.count_handles = count;
271 	if (drmIoctl(fd, LOCAL_IOCTL_SYNCOBJ_SIGNAL, &array))
272 		err = -errno;
273 	return err;
274 }
275 
276 /**
277  * syncobj_signal:
278  * @fd: The DRM file descriptor.
279  * @handles: Array of syncobj handles to signal
280  * @count: Count of syncobj handles.
281  *
282  * Signal a set of syncobjs.
283  */
284 void
syncobj_signal(int fd,uint32_t * handles,uint32_t count)285 syncobj_signal(int fd, uint32_t *handles, uint32_t count)
286 {
287 	igt_assert_eq(__syncobj_signal(fd, handles, count), 0);
288 }
289