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