xref: /aosp_15_r20/external/igt-gpu-tools/lib/sw_sync.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker  * Copyright © 2016 Collabora, Ltd.
3*d83cc019SAndroid Build Coastguard Worker  *
4*d83cc019SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*d83cc019SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*d83cc019SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*d83cc019SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*d83cc019SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*d83cc019SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*d83cc019SAndroid Build Coastguard Worker  *
11*d83cc019SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*d83cc019SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*d83cc019SAndroid Build Coastguard Worker  * Software.
14*d83cc019SAndroid Build Coastguard Worker  *
15*d83cc019SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*d83cc019SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*d83cc019SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*d83cc019SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*d83cc019SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*d83cc019SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*d83cc019SAndroid Build Coastguard Worker  * IN THE SOFTWARE.
22*d83cc019SAndroid Build Coastguard Worker  *
23*d83cc019SAndroid Build Coastguard Worker  * Authors:
24*d83cc019SAndroid Build Coastguard Worker  *    Robert Foss <[email protected]>
25*d83cc019SAndroid Build Coastguard Worker  */
26*d83cc019SAndroid Build Coastguard Worker 
27*d83cc019SAndroid Build Coastguard Worker #ifdef HAVE_LIBGEN_H
28*d83cc019SAndroid Build Coastguard Worker #include <libgen.h>
29*d83cc019SAndroid Build Coastguard Worker #endif
30*d83cc019SAndroid Build Coastguard Worker #include <fcntl.h>
31*d83cc019SAndroid Build Coastguard Worker #include <poll.h>
32*d83cc019SAndroid Build Coastguard Worker #include <stdbool.h>
33*d83cc019SAndroid Build Coastguard Worker #include <stdint.h>
34*d83cc019SAndroid Build Coastguard Worker #include <sys/ioctl.h>
35*d83cc019SAndroid Build Coastguard Worker 
36*d83cc019SAndroid Build Coastguard Worker #include <linux/sync_file.h>
37*d83cc019SAndroid Build Coastguard Worker 
38*d83cc019SAndroid Build Coastguard Worker #include "igt_debugfs.h"
39*d83cc019SAndroid Build Coastguard Worker #include "igt_kmod.h"
40*d83cc019SAndroid Build Coastguard Worker #include "sw_sync.h"
41*d83cc019SAndroid Build Coastguard Worker #include "drmtest.h"
42*d83cc019SAndroid Build Coastguard Worker #include "ioctl_wrappers.h"
43*d83cc019SAndroid Build Coastguard Worker 
44*d83cc019SAndroid Build Coastguard Worker /**
45*d83cc019SAndroid Build Coastguard Worker  * SECTION:sw_sync
46*d83cc019SAndroid Build Coastguard Worker  * @short_description: Software sync (fencing) support library
47*d83cc019SAndroid Build Coastguard Worker  * @title: SW Sync
48*d83cc019SAndroid Build Coastguard Worker  * @include: sw_sync.h
49*d83cc019SAndroid Build Coastguard Worker  */
50*d83cc019SAndroid Build Coastguard Worker 
51*d83cc019SAndroid Build Coastguard Worker struct int_sync_create_fence_data {
52*d83cc019SAndroid Build Coastguard Worker 	__u32	value;
53*d83cc019SAndroid Build Coastguard Worker 	char	name[32];
54*d83cc019SAndroid Build Coastguard Worker 	__s32	fence;
55*d83cc019SAndroid Build Coastguard Worker };
56*d83cc019SAndroid Build Coastguard Worker 
57*d83cc019SAndroid Build Coastguard Worker #define INT_SYNC_IOC_MAGIC 'W'
58*d83cc019SAndroid Build Coastguard Worker #define INT_SYNC_IOC_CREATE_FENCE	_IOWR(INT_SYNC_IOC_MAGIC, 0, struct int_sync_create_fence_data)
59*d83cc019SAndroid Build Coastguard Worker #define INT_SYNC_IOC_INC		_IOW(INT_SYNC_IOC_MAGIC, 1, __u32)
60*d83cc019SAndroid Build Coastguard Worker 
kernel_sw_sync_path(char * path,int length)61*d83cc019SAndroid Build Coastguard Worker static bool kernel_sw_sync_path(char *path, int length)
62*d83cc019SAndroid Build Coastguard Worker {
63*d83cc019SAndroid Build Coastguard Worker 	snprintf(path, length, "%s", "/dev/sw_sync");
64*d83cc019SAndroid Build Coastguard Worker 	if (access(path, R_OK | W_OK) == 0)
65*d83cc019SAndroid Build Coastguard Worker 		return true;
66*d83cc019SAndroid Build Coastguard Worker 
67*d83cc019SAndroid Build Coastguard Worker 	snprintf(path, length, "%s", "/sys/kernel/debug/sync/sw_sync");
68*d83cc019SAndroid Build Coastguard Worker 	if (access(path, R_OK | W_OK) == 0)
69*d83cc019SAndroid Build Coastguard Worker 		return true;
70*d83cc019SAndroid Build Coastguard Worker 
71*d83cc019SAndroid Build Coastguard Worker 	snprintf(path, length, "%s/sw_sync", igt_debugfs_mount());
72*d83cc019SAndroid Build Coastguard Worker 	if (access(path, R_OK | W_OK) == 0)
73*d83cc019SAndroid Build Coastguard Worker 		return true;
74*d83cc019SAndroid Build Coastguard Worker 
75*d83cc019SAndroid Build Coastguard Worker 	return false;
76*d83cc019SAndroid Build Coastguard Worker }
77*d83cc019SAndroid Build Coastguard Worker 
sw_sync_fd_is_valid(int fd)78*d83cc019SAndroid Build Coastguard Worker static bool sw_sync_fd_is_valid(int fd)
79*d83cc019SAndroid Build Coastguard Worker {
80*d83cc019SAndroid Build Coastguard Worker 	int status;
81*d83cc019SAndroid Build Coastguard Worker 
82*d83cc019SAndroid Build Coastguard Worker 	if (fd < 0)
83*d83cc019SAndroid Build Coastguard Worker 		return false;
84*d83cc019SAndroid Build Coastguard Worker 
85*d83cc019SAndroid Build Coastguard Worker 	status = fcntl(fd, F_GETFD, 0);
86*d83cc019SAndroid Build Coastguard Worker 	return status >= 0;
87*d83cc019SAndroid Build Coastguard Worker }
88*d83cc019SAndroid Build Coastguard Worker 
sw_sync_timeline_create(void)89*d83cc019SAndroid Build Coastguard Worker int sw_sync_timeline_create(void)
90*d83cc019SAndroid Build Coastguard Worker {
91*d83cc019SAndroid Build Coastguard Worker 	char buf[128];
92*d83cc019SAndroid Build Coastguard Worker 	int fd;
93*d83cc019SAndroid Build Coastguard Worker 
94*d83cc019SAndroid Build Coastguard Worker 	igt_assert_f(kernel_sw_sync_path(buf, sizeof(buf)),
95*d83cc019SAndroid Build Coastguard Worker 	    "Unable to find valid path for sw_sync\n");
96*d83cc019SAndroid Build Coastguard Worker 
97*d83cc019SAndroid Build Coastguard Worker 	fd = open(buf, O_RDWR);
98*d83cc019SAndroid Build Coastguard Worker 	igt_assert_f(sw_sync_fd_is_valid(fd), "Created invalid timeline\n");
99*d83cc019SAndroid Build Coastguard Worker 
100*d83cc019SAndroid Build Coastguard Worker 	return fd;
101*d83cc019SAndroid Build Coastguard Worker }
102*d83cc019SAndroid Build Coastguard Worker 
__sw_sync_timeline_create_fence(int fd,uint32_t seqno)103*d83cc019SAndroid Build Coastguard Worker int __sw_sync_timeline_create_fence(int fd, uint32_t seqno)
104*d83cc019SAndroid Build Coastguard Worker {
105*d83cc019SAndroid Build Coastguard Worker 	struct int_sync_create_fence_data data = { .value = seqno};
106*d83cc019SAndroid Build Coastguard Worker 
107*d83cc019SAndroid Build Coastguard Worker 	if (igt_ioctl(fd, INT_SYNC_IOC_CREATE_FENCE, &data))
108*d83cc019SAndroid Build Coastguard Worker 		return -errno;
109*d83cc019SAndroid Build Coastguard Worker 
110*d83cc019SAndroid Build Coastguard Worker 	return data.fence;
111*d83cc019SAndroid Build Coastguard Worker }
112*d83cc019SAndroid Build Coastguard Worker 
sw_sync_timeline_create_fence(int fd,uint32_t seqno)113*d83cc019SAndroid Build Coastguard Worker int sw_sync_timeline_create_fence(int fd, uint32_t seqno)
114*d83cc019SAndroid Build Coastguard Worker {
115*d83cc019SAndroid Build Coastguard Worker 	int fence = __sw_sync_timeline_create_fence(fd, seqno);
116*d83cc019SAndroid Build Coastguard Worker 
117*d83cc019SAndroid Build Coastguard Worker 	igt_assert_f(sw_sync_fd_is_valid(fence), "Created invalid fence\n");
118*d83cc019SAndroid Build Coastguard Worker 
119*d83cc019SAndroid Build Coastguard Worker 	return fence;
120*d83cc019SAndroid Build Coastguard Worker }
121*d83cc019SAndroid Build Coastguard Worker 
sw_sync_timeline_inc(int fd,uint32_t count)122*d83cc019SAndroid Build Coastguard Worker void sw_sync_timeline_inc(int fd, uint32_t count)
123*d83cc019SAndroid Build Coastguard Worker {
124*d83cc019SAndroid Build Coastguard Worker 	do_ioctl(fd, INT_SYNC_IOC_INC, &count);
125*d83cc019SAndroid Build Coastguard Worker }
126*d83cc019SAndroid Build Coastguard Worker 
sync_fence_merge(int fd1,int fd2)127*d83cc019SAndroid Build Coastguard Worker int sync_fence_merge(int fd1, int fd2)
128*d83cc019SAndroid Build Coastguard Worker {
129*d83cc019SAndroid Build Coastguard Worker 	struct sync_merge_data data = { .fd2 = fd2};
130*d83cc019SAndroid Build Coastguard Worker 
131*d83cc019SAndroid Build Coastguard Worker 	if (ioctl(fd1, SYNC_IOC_MERGE, &data))
132*d83cc019SAndroid Build Coastguard Worker 		return -errno;
133*d83cc019SAndroid Build Coastguard Worker 
134*d83cc019SAndroid Build Coastguard Worker 	return data.fence;
135*d83cc019SAndroid Build Coastguard Worker }
136*d83cc019SAndroid Build Coastguard Worker 
sync_fence_wait(int fd,int timeout)137*d83cc019SAndroid Build Coastguard Worker int sync_fence_wait(int fd, int timeout)
138*d83cc019SAndroid Build Coastguard Worker {
139*d83cc019SAndroid Build Coastguard Worker 	struct pollfd fds = { fd, POLLIN };
140*d83cc019SAndroid Build Coastguard Worker 	int ret;
141*d83cc019SAndroid Build Coastguard Worker 
142*d83cc019SAndroid Build Coastguard Worker 	do {
143*d83cc019SAndroid Build Coastguard Worker 		ret = poll(&fds, 1, timeout);
144*d83cc019SAndroid Build Coastguard Worker 		if (ret > 0) {
145*d83cc019SAndroid Build Coastguard Worker 			if (fds.revents & (POLLERR | POLLNVAL))
146*d83cc019SAndroid Build Coastguard Worker 				return -EINVAL;
147*d83cc019SAndroid Build Coastguard Worker 
148*d83cc019SAndroid Build Coastguard Worker 			return 0;
149*d83cc019SAndroid Build Coastguard Worker 		} else if (ret == 0) {
150*d83cc019SAndroid Build Coastguard Worker 			return -ETIME;
151*d83cc019SAndroid Build Coastguard Worker 		} else  {
152*d83cc019SAndroid Build Coastguard Worker 			ret = -errno;
153*d83cc019SAndroid Build Coastguard Worker 			if (ret == -EINTR || ret == -EAGAIN)
154*d83cc019SAndroid Build Coastguard Worker 				continue;
155*d83cc019SAndroid Build Coastguard Worker 			return ret;
156*d83cc019SAndroid Build Coastguard Worker 		}
157*d83cc019SAndroid Build Coastguard Worker 	} while (1);
158*d83cc019SAndroid Build Coastguard Worker }
159*d83cc019SAndroid Build Coastguard Worker 
sync_fence_count(int fd)160*d83cc019SAndroid Build Coastguard Worker int sync_fence_count(int fd)
161*d83cc019SAndroid Build Coastguard Worker {
162*d83cc019SAndroid Build Coastguard Worker 	struct sync_file_info info = {};
163*d83cc019SAndroid Build Coastguard Worker 
164*d83cc019SAndroid Build Coastguard Worker 	if (ioctl(fd, SYNC_IOC_FILE_INFO, &info))
165*d83cc019SAndroid Build Coastguard Worker 		return -errno;
166*d83cc019SAndroid Build Coastguard Worker 
167*d83cc019SAndroid Build Coastguard Worker 	return info.num_fences;
168*d83cc019SAndroid Build Coastguard Worker }
169*d83cc019SAndroid Build Coastguard Worker 
__sync_fence_count_status(int fd,int status)170*d83cc019SAndroid Build Coastguard Worker static int __sync_fence_count_status(int fd, int status)
171*d83cc019SAndroid Build Coastguard Worker {
172*d83cc019SAndroid Build Coastguard Worker 	struct sync_file_info info = {};
173*d83cc019SAndroid Build Coastguard Worker 	struct sync_fence_info *fence_info;
174*d83cc019SAndroid Build Coastguard Worker 	int count;
175*d83cc019SAndroid Build Coastguard Worker 	int i;
176*d83cc019SAndroid Build Coastguard Worker 
177*d83cc019SAndroid Build Coastguard Worker 	if (ioctl(fd, SYNC_IOC_FILE_INFO, &info))
178*d83cc019SAndroid Build Coastguard Worker 		return -errno;
179*d83cc019SAndroid Build Coastguard Worker 
180*d83cc019SAndroid Build Coastguard Worker 	fence_info = calloc(info.num_fences, sizeof(*fence_info));
181*d83cc019SAndroid Build Coastguard Worker 	if (!fence_info)
182*d83cc019SAndroid Build Coastguard Worker 		return -ENOMEM;
183*d83cc019SAndroid Build Coastguard Worker 
184*d83cc019SAndroid Build Coastguard Worker 	info.sync_fence_info = to_user_pointer(fence_info);
185*d83cc019SAndroid Build Coastguard Worker 	if (ioctl(fd, SYNC_IOC_FILE_INFO, &info)) {
186*d83cc019SAndroid Build Coastguard Worker 		count = -errno;
187*d83cc019SAndroid Build Coastguard Worker 	} else {
188*d83cc019SAndroid Build Coastguard Worker 		count = 0;
189*d83cc019SAndroid Build Coastguard Worker 		for (i = 0 ; i < info.num_fences ; i++)
190*d83cc019SAndroid Build Coastguard Worker 			if (fence_info[i].status == status)
191*d83cc019SAndroid Build Coastguard Worker 				count++;
192*d83cc019SAndroid Build Coastguard Worker 	}
193*d83cc019SAndroid Build Coastguard Worker 
194*d83cc019SAndroid Build Coastguard Worker 	free(fence_info);
195*d83cc019SAndroid Build Coastguard Worker 
196*d83cc019SAndroid Build Coastguard Worker 	return count;
197*d83cc019SAndroid Build Coastguard Worker }
198*d83cc019SAndroid Build Coastguard Worker 
sync_fence_count_status(int fd,int status)199*d83cc019SAndroid Build Coastguard Worker int sync_fence_count_status(int fd, int status)
200*d83cc019SAndroid Build Coastguard Worker {
201*d83cc019SAndroid Build Coastguard Worker 	int count = __sync_fence_count_status(fd, status);
202*d83cc019SAndroid Build Coastguard Worker 	igt_assert_f(count >= 0, "No fences with supplied status found\n");
203*d83cc019SAndroid Build Coastguard Worker 
204*d83cc019SAndroid Build Coastguard Worker 	return count;
205*d83cc019SAndroid Build Coastguard Worker }
206*d83cc019SAndroid Build Coastguard Worker 
sync_fence_status(int fence)207*d83cc019SAndroid Build Coastguard Worker int sync_fence_status(int fence)
208*d83cc019SAndroid Build Coastguard Worker {
209*d83cc019SAndroid Build Coastguard Worker 	struct sync_file_info info = { };
210*d83cc019SAndroid Build Coastguard Worker 
211*d83cc019SAndroid Build Coastguard Worker 	if (ioctl(fence, SYNC_IOC_FILE_INFO, &info))
212*d83cc019SAndroid Build Coastguard Worker 		return -errno;
213*d83cc019SAndroid Build Coastguard Worker 
214*d83cc019SAndroid Build Coastguard Worker 	return info.status;
215*d83cc019SAndroid Build Coastguard Worker }
216*d83cc019SAndroid Build Coastguard Worker 
modprobe(const char * driver)217*d83cc019SAndroid Build Coastguard Worker static void modprobe(const char *driver)
218*d83cc019SAndroid Build Coastguard Worker {
219*d83cc019SAndroid Build Coastguard Worker 	igt_kmod_load(driver, NULL);
220*d83cc019SAndroid Build Coastguard Worker }
221*d83cc019SAndroid Build Coastguard Worker 
kernel_has_sw_sync(void)222*d83cc019SAndroid Build Coastguard Worker static bool kernel_has_sw_sync(void)
223*d83cc019SAndroid Build Coastguard Worker {
224*d83cc019SAndroid Build Coastguard Worker 	char buf[128];
225*d83cc019SAndroid Build Coastguard Worker 
226*d83cc019SAndroid Build Coastguard Worker 	modprobe("sw_sync");
227*d83cc019SAndroid Build Coastguard Worker 
228*d83cc019SAndroid Build Coastguard Worker 	return kernel_sw_sync_path(buf, sizeof(buf));
229*d83cc019SAndroid Build Coastguard Worker }
230*d83cc019SAndroid Build Coastguard Worker 
igt_require_sw_sync(void)231*d83cc019SAndroid Build Coastguard Worker void igt_require_sw_sync(void)
232*d83cc019SAndroid Build Coastguard Worker {
233*d83cc019SAndroid Build Coastguard Worker 	igt_require(kernel_has_sw_sync());
234*d83cc019SAndroid Build Coastguard Worker }
235