1 /*
2 * Copyright © 2012 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 * Authors:
24 * Ben Widawsky <[email protected]>
25 *
26 */
27
28 #include "igt.h"
29 #include "igt_vgem.h"
30
__gem_wait(int fd,struct drm_i915_gem_wait * w)31 static int __gem_wait(int fd, struct drm_i915_gem_wait *w)
32 {
33 int err;
34
35 err = 0;
36 if (igt_ioctl(fd, DRM_IOCTL_I915_GEM_WAIT, w))
37 err = -errno;
38
39 return err;
40 }
41
invalid_flags(int fd)42 static void invalid_flags(int fd)
43 {
44 struct drm_i915_gem_wait wait;
45
46 memset(&wait, 0, sizeof(wait));
47 wait.bo_handle = gem_create(fd, 4096);
48 wait.timeout_ns = 1;
49 /* NOTE: This test intentionally tests for just the next available flag.
50 * Don't "fix" this testcase without the ABI testcases for new flags
51 * first. */
52 wait.flags = 1;
53
54 igt_assert_eq(__gem_wait(fd, &wait), -EINVAL);
55
56 gem_close(fd, wait.bo_handle);
57 }
58
invalid_buf(int fd)59 static void invalid_buf(int fd)
60 {
61 struct drm_i915_gem_wait wait;
62
63 memset(&wait, 0, sizeof(wait));
64 igt_assert_eq(__gem_wait(fd, &wait), -ENOENT);
65 }
66
67 #define BUSY 1
68 #define HANG 2
69 #define AWAIT 4
70 #define WRITE 8
71
basic(int fd,unsigned engine,unsigned flags)72 static void basic(int fd, unsigned engine, unsigned flags)
73 {
74 IGT_CORK_HANDLE(cork);
75 uint32_t plug =
76 flags & (WRITE | AWAIT) ? igt_cork_plug(&cork, fd) : 0;
77 igt_spin_t *spin = igt_spin_new(fd,
78 .engine = engine,
79 .dependency = plug);
80 struct drm_i915_gem_wait wait = {
81 flags & WRITE ? plug : spin->handle
82 };
83
84 igt_assert_eq(__gem_wait(fd, &wait), -ETIME);
85
86 if (flags & BUSY) {
87 struct timespec tv = {};
88 int timeout;
89
90 timeout = 120;
91 if ((flags & HANG) == 0) {
92 igt_spin_set_timeout(spin, NSEC_PER_SEC/2);
93 timeout = 1;
94 }
95
96 if (flags & (WRITE | AWAIT))
97 igt_cork_unplug(&cork);
98
99 igt_assert_eq(__gem_wait(fd, &wait), -ETIME);
100
101 while (__gem_wait(fd, &wait) == -ETIME)
102 igt_assert(igt_seconds_elapsed(&tv) < timeout);
103 } else {
104 wait.timeout_ns = NSEC_PER_SEC / 2; /* 0.5s */
105 igt_assert_eq(__gem_wait(fd, &wait), -ETIME);
106 igt_assert_eq_s64(wait.timeout_ns, 0);
107
108 if (flags & (WRITE | AWAIT))
109 igt_cork_unplug(&cork);
110
111 wait.timeout_ns = 0;
112 igt_assert_eq(__gem_wait(fd, &wait), -ETIME);
113
114 if ((flags & HANG) == 0) {
115 igt_spin_set_timeout(spin, NSEC_PER_SEC/2);
116 wait.timeout_ns = NSEC_PER_SEC; /* 1.0s */
117 igt_assert_eq(__gem_wait(fd, &wait), 0);
118 igt_assert(wait.timeout_ns >= 0);
119 } else {
120 wait.timeout_ns = -1;
121 igt_assert_eq(__gem_wait(fd, &wait), 0);
122 igt_assert(wait.timeout_ns == -1);
123 }
124
125 wait.timeout_ns = 0;
126 igt_assert_eq(__gem_wait(fd, &wait), 0);
127 igt_assert(wait.timeout_ns == 0);
128 }
129
130 if (plug)
131 gem_close(fd, plug);
132 igt_spin_free(fd, spin);
133 }
134
135 igt_main
136 {
137 const struct intel_execution_engine2 *e;
138 int fd = -1;
139
140 igt_skip_on_simulation();
141
142 igt_fixture {
143 fd = drm_open_driver_master(DRIVER_INTEL);
144 igt_require_gem(fd);
145 }
146
147 igt_subtest("invalid-flags")
148 invalid_flags(fd);
149
150 igt_subtest("invalid-buf")
151 invalid_buf(fd);
152
153 igt_subtest_group {
154 igt_fixture {
155 igt_fork_hang_detector(fd);
156 igt_fork_signal_helper();
157 }
158
159 igt_subtest("basic-busy-all") {
160 gem_quiescent_gpu(fd);
161 basic(fd, ALL_ENGINES, BUSY);
162 }
163 igt_subtest("basic-wait-all") {
164 gem_quiescent_gpu(fd);
165 basic(fd, ALL_ENGINES, 0);
166 }
167 igt_subtest("basic-await-all") {
168 gem_quiescent_gpu(fd);
169 basic(fd, ALL_ENGINES, AWAIT);
170 }
171 igt_subtest("basic-busy-write-all") {
172 gem_quiescent_gpu(fd);
173 basic(fd, ALL_ENGINES, BUSY | WRITE);
174 }
175 igt_subtest("basic-wait-write-all") {
176 gem_quiescent_gpu(fd);
177 basic(fd, ALL_ENGINES, WRITE);
178 }
179
__for_each_physical_engine(fd,e)180 __for_each_physical_engine(fd, e) {
181 igt_subtest_group {
182 igt_subtest_f("busy-%s", e->name) {
183 gem_quiescent_gpu(fd);
184 basic(fd, e->flags, BUSY);
185 }
186 igt_subtest_f("wait-%s", e->name) {
187 gem_quiescent_gpu(fd);
188 basic(fd, e->flags, 0);
189 }
190 igt_subtest_f("await-%s", e->name) {
191 gem_quiescent_gpu(fd);
192 basic(fd, e->flags, AWAIT);
193 }
194 igt_subtest_f("write-busy-%s", e->name) {
195 gem_quiescent_gpu(fd);
196 basic(fd, e->flags, BUSY | WRITE);
197 }
198 igt_subtest_f("write-wait-%s", e->name) {
199 gem_quiescent_gpu(fd);
200 basic(fd, e->flags, WRITE);
201 }
202 }
203 }
204
205 igt_fixture {
206 igt_stop_signal_helper();
207 igt_stop_hang_detector();
208 }
209 }
210
211 igt_subtest_group {
212 igt_hang_t hang;
213
214 igt_fixture {
215 hang = igt_allow_hang(fd, 0, 0);
216 igt_fork_signal_helper();
217 }
218
219 igt_subtest("hang-busy-all") {
220 gem_quiescent_gpu(fd);
221 basic(fd, ALL_ENGINES, BUSY | HANG);
222 }
223 igt_subtest("hang-wait-all") {
224 gem_quiescent_gpu(fd);
225 basic(fd, ALL_ENGINES, HANG);
226 }
227
228 igt_subtest("hang-busy-write-all") {
229 gem_quiescent_gpu(fd);
230 basic(fd, ALL_ENGINES, BUSY | WRITE | HANG);
231 }
232 igt_subtest("hang-wait-write-all") {
233 gem_quiescent_gpu(fd);
234 basic(fd, ALL_ENGINES, WRITE | HANG);
235 }
236
__for_each_physical_engine(fd,e)237 __for_each_physical_engine(fd, e) {
238 igt_subtest_f("hang-busy-%s", e->name) {
239 gem_quiescent_gpu(fd);
240 basic(fd, e->flags, HANG | BUSY);
241 }
242 igt_subtest_f("hang-wait-%s", e->name) {
243 gem_quiescent_gpu(fd);
244 basic(fd, e->flags, HANG);
245 }
246 igt_subtest_f("hang-busy-write-%s", e->name) {
247 gem_quiescent_gpu(fd);
248 basic(fd, e->flags, HANG | WRITE | BUSY);
249 }
250 igt_subtest_f("hang-wait-write-%s", e->name) {
251 gem_quiescent_gpu(fd);
252 basic(fd, e->flags, HANG | WRITE);
253 }
254 }
255
256 igt_fixture {
257 igt_stop_signal_helper();
258 igt_disallow_hang(fd, hang);
259 }
260 }
261
262 igt_fixture {
263 close(fd);
264 }
265 }
266