fbdev: Garbage collect fbdev scrolling acceleration, part 1 (from TODO list)
[linux-2.6-microblaze.git] / drivers / gpu / drm / i915 / gem / selftests / i915_gem_dmabuf.c
1 /*
2  * SPDX-License-Identifier: MIT
3  *
4  * Copyright © 2016 Intel Corporation
5  */
6
7 #include "i915_drv.h"
8 #include "i915_selftest.h"
9
10 #include "mock_dmabuf.h"
11 #include "selftests/mock_gem_device.h"
12
13 static int igt_dmabuf_export(void *arg)
14 {
15         struct drm_i915_private *i915 = arg;
16         struct drm_i915_gem_object *obj;
17         struct dma_buf *dmabuf;
18
19         obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
20         if (IS_ERR(obj))
21                 return PTR_ERR(obj);
22
23         dmabuf = i915_gem_prime_export(&obj->base, 0);
24         i915_gem_object_put(obj);
25         if (IS_ERR(dmabuf)) {
26                 pr_err("i915_gem_prime_export failed with err=%d\n",
27                        (int)PTR_ERR(dmabuf));
28                 return PTR_ERR(dmabuf);
29         }
30
31         dma_buf_put(dmabuf);
32         return 0;
33 }
34
35 static int igt_dmabuf_import_self(void *arg)
36 {
37         struct drm_i915_private *i915 = arg;
38         struct drm_i915_gem_object *obj, *import_obj;
39         struct drm_gem_object *import;
40         struct dma_buf *dmabuf;
41         int err;
42
43         obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
44         if (IS_ERR(obj))
45                 return PTR_ERR(obj);
46
47         dmabuf = i915_gem_prime_export(&obj->base, 0);
48         if (IS_ERR(dmabuf)) {
49                 pr_err("i915_gem_prime_export failed with err=%d\n",
50                        (int)PTR_ERR(dmabuf));
51                 err = PTR_ERR(dmabuf);
52                 goto out;
53         }
54
55         import = i915_gem_prime_import(&i915->drm, dmabuf);
56         if (IS_ERR(import)) {
57                 pr_err("i915_gem_prime_import failed with err=%d\n",
58                        (int)PTR_ERR(import));
59                 err = PTR_ERR(import);
60                 goto out_dmabuf;
61         }
62
63         if (import != &obj->base) {
64                 pr_err("i915_gem_prime_import created a new object!\n");
65                 err = -EINVAL;
66                 goto out_import;
67         }
68         import_obj = to_intel_bo(import);
69
70         i915_gem_object_lock(import_obj, NULL);
71         err = __i915_gem_object_get_pages(import_obj);
72         i915_gem_object_unlock(import_obj);
73         if (err) {
74                 pr_err("Same object dma-buf get_pages failed!\n");
75                 goto out_import;
76         }
77
78         err = 0;
79 out_import:
80         i915_gem_object_put(import_obj);
81 out_dmabuf:
82         dma_buf_put(dmabuf);
83 out:
84         i915_gem_object_put(obj);
85         return err;
86 }
87
88 static int igt_dmabuf_import_same_driver_lmem(void *arg)
89 {
90         struct drm_i915_private *i915 = arg;
91         struct intel_memory_region *lmem = i915->mm.regions[INTEL_REGION_LMEM];
92         struct drm_i915_gem_object *obj;
93         struct drm_gem_object *import;
94         struct dma_buf *dmabuf;
95         int err;
96
97         if (!lmem)
98                 return 0;
99
100         force_different_devices = true;
101
102         obj = __i915_gem_object_create_user(i915, PAGE_SIZE, &lmem, 1);
103         if (IS_ERR(obj)) {
104                 pr_err("__i915_gem_object_create_user failed with err=%ld\n",
105                        PTR_ERR(dmabuf));
106                 err = PTR_ERR(obj);
107                 goto out_ret;
108         }
109
110         dmabuf = i915_gem_prime_export(&obj->base, 0);
111         if (IS_ERR(dmabuf)) {
112                 pr_err("i915_gem_prime_export failed with err=%ld\n",
113                        PTR_ERR(dmabuf));
114                 err = PTR_ERR(dmabuf);
115                 goto out;
116         }
117
118         /*
119          * We expect an import of an LMEM-only object to fail with
120          * -EOPNOTSUPP because it can't be migrated to SMEM.
121          */
122         import = i915_gem_prime_import(&i915->drm, dmabuf);
123         if (!IS_ERR(import)) {
124                 drm_gem_object_put(import);
125                 pr_err("i915_gem_prime_import succeeded when it shouldn't have\n");
126                 err = -EINVAL;
127         } else if (PTR_ERR(import) != -EOPNOTSUPP) {
128                 pr_err("i915_gem_prime_import failed with the wrong err=%ld\n",
129                        PTR_ERR(import));
130                 err = PTR_ERR(import);
131         }
132
133         dma_buf_put(dmabuf);
134 out:
135         i915_gem_object_put(obj);
136 out_ret:
137         force_different_devices = false;
138         return err;
139 }
140
141 static int igt_dmabuf_import_same_driver(struct drm_i915_private *i915,
142                                          struct intel_memory_region **regions,
143                                          unsigned int num_regions)
144 {
145         struct drm_i915_gem_object *obj, *import_obj;
146         struct drm_gem_object *import;
147         struct dma_buf *dmabuf;
148         struct dma_buf_attachment *import_attach;
149         struct sg_table *st;
150         long timeout;
151         int err;
152
153         force_different_devices = true;
154
155         obj = __i915_gem_object_create_user(i915, PAGE_SIZE,
156                                             regions, num_regions);
157         if (IS_ERR(obj)) {
158                 pr_err("__i915_gem_object_create_user failed with err=%ld\n",
159                        PTR_ERR(dmabuf));
160                 err = PTR_ERR(obj);
161                 goto out_ret;
162         }
163
164         dmabuf = i915_gem_prime_export(&obj->base, 0);
165         if (IS_ERR(dmabuf)) {
166                 pr_err("i915_gem_prime_export failed with err=%ld\n",
167                        PTR_ERR(dmabuf));
168                 err = PTR_ERR(dmabuf);
169                 goto out;
170         }
171
172         import = i915_gem_prime_import(&i915->drm, dmabuf);
173         if (IS_ERR(import)) {
174                 pr_err("i915_gem_prime_import failed with err=%ld\n",
175                        PTR_ERR(import));
176                 err = PTR_ERR(import);
177                 goto out_dmabuf;
178         }
179
180         if (import == &obj->base) {
181                 pr_err("i915_gem_prime_import reused gem object!\n");
182                 err = -EINVAL;
183                 goto out_import;
184         }
185
186         import_obj = to_intel_bo(import);
187
188         i915_gem_object_lock(import_obj, NULL);
189         err = __i915_gem_object_get_pages(import_obj);
190         if (err) {
191                 pr_err("Different objects dma-buf get_pages failed!\n");
192                 i915_gem_object_unlock(import_obj);
193                 goto out_import;
194         }
195
196         /*
197          * If the exported object is not in system memory, something
198          * weird is going on. TODO: When p2p is supported, this is no
199          * longer considered weird.
200          */
201         if (obj->mm.region != i915->mm.regions[INTEL_REGION_SMEM]) {
202                 pr_err("Exported dma-buf is not in system memory\n");
203                 err = -EINVAL;
204         }
205
206         i915_gem_object_unlock(import_obj);
207
208         /* Now try a fake an importer */
209         import_attach = dma_buf_attach(dmabuf, obj->base.dev->dev);
210         if (IS_ERR(import_attach)) {
211                 err = PTR_ERR(import_attach);
212                 goto out_import;
213         }
214
215         st = dma_buf_map_attachment(import_attach, DMA_BIDIRECTIONAL);
216         if (IS_ERR(st)) {
217                 err = PTR_ERR(st);
218                 goto out_detach;
219         }
220
221         timeout = dma_resv_wait_timeout(dmabuf->resv, false, true, 5 * HZ);
222         if (!timeout) {
223                 pr_err("dmabuf wait for exclusive fence timed out.\n");
224                 timeout = -ETIME;
225         }
226         err = timeout > 0 ? 0 : timeout;
227         dma_buf_unmap_attachment(import_attach, st, DMA_BIDIRECTIONAL);
228 out_detach:
229         dma_buf_detach(dmabuf, import_attach);
230 out_import:
231         i915_gem_object_put(import_obj);
232 out_dmabuf:
233         dma_buf_put(dmabuf);
234 out:
235         i915_gem_object_put(obj);
236 out_ret:
237         force_different_devices = false;
238         return err;
239 }
240
241 static int igt_dmabuf_import_same_driver_smem(void *arg)
242 {
243         struct drm_i915_private *i915 = arg;
244         struct intel_memory_region *smem = i915->mm.regions[INTEL_REGION_SMEM];
245
246         return igt_dmabuf_import_same_driver(i915, &smem, 1);
247 }
248
249 static int igt_dmabuf_import_same_driver_lmem_smem(void *arg)
250 {
251         struct drm_i915_private *i915 = arg;
252         struct intel_memory_region *regions[2];
253
254         if (!i915->mm.regions[INTEL_REGION_LMEM])
255                 return 0;
256
257         regions[0] = i915->mm.regions[INTEL_REGION_LMEM];
258         regions[1] = i915->mm.regions[INTEL_REGION_SMEM];
259         return igt_dmabuf_import_same_driver(i915, regions, 2);
260 }
261
262 static int igt_dmabuf_import(void *arg)
263 {
264         struct drm_i915_private *i915 = arg;
265         struct drm_i915_gem_object *obj;
266         struct dma_buf *dmabuf;
267         void *obj_map, *dma_map;
268         struct dma_buf_map map;
269         u32 pattern[] = { 0, 0xaa, 0xcc, 0x55, 0xff };
270         int err, i;
271
272         dmabuf = mock_dmabuf(1);
273         if (IS_ERR(dmabuf))
274                 return PTR_ERR(dmabuf);
275
276         obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf));
277         if (IS_ERR(obj)) {
278                 pr_err("i915_gem_prime_import failed with err=%d\n",
279                        (int)PTR_ERR(obj));
280                 err = PTR_ERR(obj);
281                 goto out_dmabuf;
282         }
283
284         if (obj->base.dev != &i915->drm) {
285                 pr_err("i915_gem_prime_import created a non-i915 object!\n");
286                 err = -EINVAL;
287                 goto out_obj;
288         }
289
290         if (obj->base.size != PAGE_SIZE) {
291                 pr_err("i915_gem_prime_import is wrong size found %lld, expected %ld\n",
292                        (long long)obj->base.size, PAGE_SIZE);
293                 err = -EINVAL;
294                 goto out_obj;
295         }
296
297         err = dma_buf_vmap(dmabuf, &map);
298         dma_map = err ? NULL : map.vaddr;
299         if (!dma_map) {
300                 pr_err("dma_buf_vmap failed\n");
301                 err = -ENOMEM;
302                 goto out_obj;
303         }
304
305         if (0) { /* Can not yet map dmabuf */
306                 obj_map = i915_gem_object_pin_map(obj, I915_MAP_WB);
307                 if (IS_ERR(obj_map)) {
308                         err = PTR_ERR(obj_map);
309                         pr_err("i915_gem_object_pin_map failed with err=%d\n", err);
310                         goto out_dma_map;
311                 }
312
313                 for (i = 0; i < ARRAY_SIZE(pattern); i++) {
314                         memset(dma_map, pattern[i], PAGE_SIZE);
315                         if (memchr_inv(obj_map, pattern[i], PAGE_SIZE)) {
316                                 err = -EINVAL;
317                                 pr_err("imported vmap not all set to %x!\n", pattern[i]);
318                                 i915_gem_object_unpin_map(obj);
319                                 goto out_dma_map;
320                         }
321                 }
322
323                 for (i = 0; i < ARRAY_SIZE(pattern); i++) {
324                         memset(obj_map, pattern[i], PAGE_SIZE);
325                         if (memchr_inv(dma_map, pattern[i], PAGE_SIZE)) {
326                                 err = -EINVAL;
327                                 pr_err("exported vmap not all set to %x!\n", pattern[i]);
328                                 i915_gem_object_unpin_map(obj);
329                                 goto out_dma_map;
330                         }
331                 }
332
333                 i915_gem_object_unpin_map(obj);
334         }
335
336         err = 0;
337 out_dma_map:
338         dma_buf_vunmap(dmabuf, &map);
339 out_obj:
340         i915_gem_object_put(obj);
341 out_dmabuf:
342         dma_buf_put(dmabuf);
343         return err;
344 }
345
346 static int igt_dmabuf_import_ownership(void *arg)
347 {
348         struct drm_i915_private *i915 = arg;
349         struct drm_i915_gem_object *obj;
350         struct dma_buf *dmabuf;
351         struct dma_buf_map map;
352         void *ptr;
353         int err;
354
355         dmabuf = mock_dmabuf(1);
356         if (IS_ERR(dmabuf))
357                 return PTR_ERR(dmabuf);
358
359         err = dma_buf_vmap(dmabuf, &map);
360         ptr = err ? NULL : map.vaddr;
361         if (!ptr) {
362                 pr_err("dma_buf_vmap failed\n");
363                 err = -ENOMEM;
364                 goto err_dmabuf;
365         }
366
367         memset(ptr, 0xc5, PAGE_SIZE);
368         dma_buf_vunmap(dmabuf, &map);
369
370         obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf));
371         if (IS_ERR(obj)) {
372                 pr_err("i915_gem_prime_import failed with err=%d\n",
373                        (int)PTR_ERR(obj));
374                 err = PTR_ERR(obj);
375                 goto err_dmabuf;
376         }
377
378         dma_buf_put(dmabuf);
379
380         err = i915_gem_object_pin_pages_unlocked(obj);
381         if (err) {
382                 pr_err("i915_gem_object_pin_pages failed with err=%d\n", err);
383                 goto out_obj;
384         }
385
386         err = 0;
387         i915_gem_object_unpin_pages(obj);
388 out_obj:
389         i915_gem_object_put(obj);
390         return err;
391
392 err_dmabuf:
393         dma_buf_put(dmabuf);
394         return err;
395 }
396
397 static int igt_dmabuf_export_vmap(void *arg)
398 {
399         struct drm_i915_private *i915 = arg;
400         struct drm_i915_gem_object *obj;
401         struct dma_buf *dmabuf;
402         struct dma_buf_map map;
403         void *ptr;
404         int err;
405
406         obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
407         if (IS_ERR(obj))
408                 return PTR_ERR(obj);
409
410         dmabuf = i915_gem_prime_export(&obj->base, 0);
411         if (IS_ERR(dmabuf)) {
412                 pr_err("i915_gem_prime_export failed with err=%d\n",
413                        (int)PTR_ERR(dmabuf));
414                 err = PTR_ERR(dmabuf);
415                 goto err_obj;
416         }
417         i915_gem_object_put(obj);
418
419         err = dma_buf_vmap(dmabuf, &map);
420         ptr = err ? NULL : map.vaddr;
421         if (!ptr) {
422                 pr_err("dma_buf_vmap failed\n");
423                 err = -ENOMEM;
424                 goto out;
425         }
426
427         if (memchr_inv(ptr, 0, dmabuf->size)) {
428                 pr_err("Exported object not initialiased to zero!\n");
429                 err = -EINVAL;
430                 goto out;
431         }
432
433         memset(ptr, 0xc5, dmabuf->size);
434
435         err = 0;
436         dma_buf_vunmap(dmabuf, &map);
437 out:
438         dma_buf_put(dmabuf);
439         return err;
440
441 err_obj:
442         i915_gem_object_put(obj);
443         return err;
444 }
445
446 int i915_gem_dmabuf_mock_selftests(void)
447 {
448         static const struct i915_subtest tests[] = {
449                 SUBTEST(igt_dmabuf_export),
450                 SUBTEST(igt_dmabuf_import_self),
451                 SUBTEST(igt_dmabuf_import),
452                 SUBTEST(igt_dmabuf_import_ownership),
453                 SUBTEST(igt_dmabuf_export_vmap),
454         };
455         struct drm_i915_private *i915;
456         int err;
457
458         i915 = mock_gem_device();
459         if (!i915)
460                 return -ENOMEM;
461
462         err = i915_subtests(tests, i915);
463
464         mock_destroy_device(i915);
465         return err;
466 }
467
468 int i915_gem_dmabuf_live_selftests(struct drm_i915_private *i915)
469 {
470         static const struct i915_subtest tests[] = {
471                 SUBTEST(igt_dmabuf_export),
472                 SUBTEST(igt_dmabuf_import_same_driver_lmem),
473                 SUBTEST(igt_dmabuf_import_same_driver_smem),
474                 SUBTEST(igt_dmabuf_import_same_driver_lmem_smem),
475         };
476
477         return i915_subtests(tests, i915);
478 }