tests/gem_dummy_reloc_loop: Add one subtest based on multi drm_fd to test CPU<->GPU...
[platform/upstream/intel-gpu-tools.git] / tests / gem_dummy_reloc_loop.c
1 /*
2  * Copyright © 2011 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  *    Daniel Vetter <daniel.vetter@ffwll.ch> (based on gem_storedw_*.c)
25  *
26  */
27
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <fcntl.h>
32 #include <inttypes.h>
33 #include <errno.h>
34 #include <sys/stat.h>
35 #include <sys/time.h>
36 #include "drm.h"
37 #include "ioctl_wrappers.h"
38 #include "drmtest.h"
39 #include "intel_bufmgr.h"
40 #include "intel_batchbuffer.h"
41 #include "intel_io.h"
42 #include "i830_reg.h"
43 #include "intel_chipset.h"
44
45 #define LOCAL_I915_EXEC_VEBOX (4<<0)
46
47 static drm_intel_bufmgr *bufmgr;
48 struct intel_batchbuffer *batch;
49 static drm_intel_bo *target_buffer;
50
51 #define NUM_FD  50
52
53 static int mfd[NUM_FD];
54 static drm_intel_bufmgr *mbufmgr[NUM_FD];
55 static struct intel_batchbuffer *mbatch[NUM_FD];
56 static drm_intel_bo *mbuffer[NUM_FD];
57
58 /*
59  * Testcase: Basic check of ring<->cpu sync using a dummy reloc
60  *
61  * The last test (that randomly switches the ring) seems to be pretty effective
62  * at hitting the missed irq bug that's worked around with the HWSTAM irq write.
63  */
64
65
66 #define MI_COND_BATCH_BUFFER_END        (0x36<<23 | 1)
67 #define MI_DO_COMPARE                   (1<<21)
68 static void
69 dummy_reloc_loop(int ring)
70 {
71         int i;
72
73         for (i = 0; i < 0x100000; i++) {
74                 if (ring == I915_EXEC_RENDER) {
75                         BEGIN_BATCH(4);
76                         OUT_BATCH(MI_COND_BATCH_BUFFER_END | MI_DO_COMPARE);
77                         OUT_BATCH(0xffffffff); /* compare dword */
78                         OUT_RELOC(target_buffer, I915_GEM_DOMAIN_RENDER,
79                                         I915_GEM_DOMAIN_RENDER, 0);
80                         OUT_BATCH(MI_NOOP);
81                         ADVANCE_BATCH();
82                 } else {
83                         BEGIN_BATCH(4);
84                         OUT_BATCH(MI_FLUSH_DW | 1);
85                         OUT_BATCH(0); /* reserved */
86                         OUT_RELOC(target_buffer, I915_GEM_DOMAIN_RENDER,
87                                         I915_GEM_DOMAIN_RENDER, 0);
88                         OUT_BATCH(MI_NOOP | (1<<22) | (0xf));
89                         ADVANCE_BATCH();
90                 }
91                 intel_batchbuffer_flush_on_ring(batch, ring);
92
93                 drm_intel_bo_map(target_buffer, 0);
94                 // map to force completion
95                 drm_intel_bo_unmap(target_buffer);
96         }
97 }
98
99 static void
100 dummy_reloc_loop_random_ring(int num_rings)
101 {
102         int i;
103
104         srandom(0xdeadbeef);
105
106         for (i = 0; i < 0x100000; i++) {
107                 int ring = random() % num_rings + 1;
108
109                 if (ring == I915_EXEC_RENDER) {
110                         BEGIN_BATCH(4);
111                         OUT_BATCH(MI_COND_BATCH_BUFFER_END | MI_DO_COMPARE);
112                         OUT_BATCH(0xffffffff); /* compare dword */
113                         OUT_RELOC(target_buffer, I915_GEM_DOMAIN_RENDER,
114                                         I915_GEM_DOMAIN_RENDER, 0);
115                         OUT_BATCH(MI_NOOP);
116                         ADVANCE_BATCH();
117                 } else {
118                         BEGIN_BATCH(4);
119                         OUT_BATCH(MI_FLUSH_DW | 1);
120                         OUT_BATCH(0); /* reserved */
121                         OUT_RELOC(target_buffer, I915_GEM_DOMAIN_RENDER,
122                                         I915_GEM_DOMAIN_RENDER, 0);
123                         OUT_BATCH(MI_NOOP | (1<<22) | (0xf));
124                         ADVANCE_BATCH();
125                 }
126                 intel_batchbuffer_flush_on_ring(batch, ring);
127
128                 drm_intel_bo_map(target_buffer, 0);
129                 // map to force waiting on rendering
130                 drm_intel_bo_unmap(target_buffer);
131         }
132 }
133
134 static void
135 dummy_reloc_loop_random_ring_multi_fd(int num_rings)
136 {
137         int i;
138         struct intel_batchbuffer *saved_batch;
139
140         saved_batch = batch;
141
142         srandom(0xdeadbeef);
143
144         for (i = 0; i < 0x100000; i++) {
145                 int mindex;
146                 int ring = random() % num_rings + 1;
147
148                 mindex = random() % NUM_FD;
149                 batch = mbatch[mindex];
150
151                 if (ring == I915_EXEC_RENDER) {
152                         BEGIN_BATCH(4);
153                         OUT_BATCH(MI_COND_BATCH_BUFFER_END | MI_DO_COMPARE);
154                         OUT_BATCH(0xffffffff); /* compare dword */
155                         OUT_RELOC(mbuffer[mindex], I915_GEM_DOMAIN_RENDER,
156                                         I915_GEM_DOMAIN_RENDER, 0);
157                         OUT_BATCH(MI_NOOP);
158                         ADVANCE_BATCH();
159                 } else {
160                         BEGIN_BATCH(4);
161                         OUT_BATCH(MI_FLUSH_DW | 1);
162                         OUT_BATCH(0); /* reserved */
163                         OUT_RELOC(mbuffer[mindex], I915_GEM_DOMAIN_RENDER,
164                                         I915_GEM_DOMAIN_RENDER, 0);
165                         OUT_BATCH(MI_NOOP | (1<<22) | (0xf));
166                         ADVANCE_BATCH();
167                 }
168                 intel_batchbuffer_flush_on_ring(batch, ring);
169
170                 drm_intel_bo_map(target_buffer, 0);
171                 // map to force waiting on rendering
172                 drm_intel_bo_unmap(target_buffer);
173         }
174
175         batch = saved_batch;
176 }
177
178 int fd;
179 int devid;
180 int num_rings;
181
182 igt_main
183 {
184         igt_skip_on_simulation();
185
186         igt_fixture {
187                 int i;
188                 fd = drm_open_any();
189                 devid = intel_get_drm_devid(fd);
190                 num_rings = gem_get_num_rings(fd);
191                 /* Not yet implemented on pre-snb. */
192                 igt_require(HAS_BLT_RING(devid));
193
194                 bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
195                 igt_assert(bufmgr);
196                 drm_intel_bufmgr_gem_enable_reuse(bufmgr);
197
198                 batch = intel_batchbuffer_alloc(bufmgr, devid);
199                 igt_assert(batch);
200
201                 target_buffer = drm_intel_bo_alloc(bufmgr, "target bo", 4096, 4096);
202                 igt_assert(target_buffer);
203
204                 /* Create multi drm_fd and map one gem object to multi gem_contexts */
205                 {
206                         unsigned int target_flink;
207                         char buffer_name[32];
208                         if (dri_bo_flink(target_buffer, &target_flink)) {
209                                 printf("fail to get flink for target buffer\n");
210                                 igt_assert_f(0, "fail to create global "
211                                              "gem_handle for target buffer\n");
212                         }
213                         for (i = 0; i < NUM_FD; i++) {
214                                 sprintf(buffer_name, "Target buffer %d\n", i);
215                                 mfd[i] = drm_open_any();
216                                 mbufmgr[i] = drm_intel_bufmgr_gem_init(mfd[i], 4096);
217                                 igt_assert_f(mbufmgr[i],
218                                              "fail to initialize buf manager "
219                                              "for drm_fd %d\n",
220                                              mfd[i]);
221                                 drm_intel_bufmgr_gem_enable_reuse(mbufmgr[i]);
222                                 mbatch[i] = intel_batchbuffer_alloc(mbufmgr[i], devid);
223                                 igt_assert_f(mbatch[i],
224                                              "fail to create batchbuffer "
225                                              "for drm_fd %d\n",
226                                              mfd[i]);
227                                 mbuffer[i] = intel_bo_gem_create_from_name(
228                                                                 mbufmgr[i],
229                                                                 buffer_name,
230                                                                 target_flink);
231                                 igt_assert_f(mbuffer[i],
232                                              "fail to create gem bo from global "
233                                              "gem_handle %d for drm_fd %d\n",
234                                              target_flink, mfd[i]);
235                         }
236                 }
237         }
238
239         igt_subtest("render") {
240                 printf("running dummy loop on render\n");
241                 dummy_reloc_loop(I915_EXEC_RENDER);
242                 printf("dummy loop run on render completed\n");
243         }
244
245         igt_subtest("bsd") {
246                 gem_require_ring(fd, I915_EXEC_BSD);
247                 sleep(2);
248                 printf("running dummy loop on bsd\n");
249                 dummy_reloc_loop(I915_EXEC_BSD);
250                 printf("dummy loop run on bsd completed\n");
251         }
252
253         igt_subtest("blt") {
254                 gem_require_ring(fd, I915_EXEC_BLT);
255                 sleep(2);
256                 printf("running dummy loop on blt\n");
257                 dummy_reloc_loop(I915_EXEC_BLT);
258                 printf("dummy loop run on blt completed\n");
259         }
260
261 #ifdef I915_EXEC_VEBOX
262         igt_subtest("vebox") {
263                 gem_require_ring(fd, I915_EXEC_VEBOX);
264                 sleep(2);
265                 printf("running dummy loop on vebox\n");
266                 dummy_reloc_loop(LOCAL_I915_EXEC_VEBOX);
267                 printf("dummy loop run on vebox completed\n");
268         }
269 #endif
270
271         igt_subtest("mixed") {
272                 if (num_rings > 1) {
273                         sleep(2);
274                         printf("running dummy loop on random rings\n");
275                         dummy_reloc_loop_random_ring(num_rings);
276                         printf("dummy loop run on random rings completed\n");
277                 }
278         }
279         igt_subtest("mixed_multi_fd") {
280                 if (num_rings > 1) {
281                         sleep(2);
282                         printf("running dummy loop on random rings based on "
283                                         "multi drm_fd\n");
284                         dummy_reloc_loop_random_ring_multi_fd(num_rings);
285                         printf("dummy loop run on random rings based on "
286                                         "multi drm_fd completed\n");
287                 }
288         }
289         igt_fixture {
290                 int i;
291                 /* Free the buffer/batchbuffer/buffer mgr for multi-fd */
292                 {
293                         for (i = 0; i < NUM_FD; i++) {
294                                 dri_bo_unreference(mbuffer[i]);
295                                 intel_batchbuffer_free(mbatch[i]);
296                                 drm_intel_bufmgr_destroy(mbufmgr[i]);
297                                 close(mfd[i]);
298                         }
299                 }
300                 drm_intel_bo_unreference(target_buffer);
301                 intel_batchbuffer_free(batch);
302                 drm_intel_bufmgr_destroy(bufmgr);
303
304                 close(fd);
305         }
306 }