linux/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
<<
>>
Prefs
   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
  13static 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(&i915->drm, &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
  35static int igt_dmabuf_import_self(void *arg)
  36{
  37        struct drm_i915_private *i915 = arg;
  38        struct drm_i915_gem_object *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(&i915->drm, &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
  69        err = 0;
  70out_import:
  71        i915_gem_object_put(to_intel_bo(import));
  72out_dmabuf:
  73        dma_buf_put(dmabuf);
  74out:
  75        i915_gem_object_put(obj);
  76        return err;
  77}
  78
  79static int igt_dmabuf_import(void *arg)
  80{
  81        struct drm_i915_private *i915 = arg;
  82        struct drm_i915_gem_object *obj;
  83        struct dma_buf *dmabuf;
  84        void *obj_map, *dma_map;
  85        u32 pattern[] = { 0, 0xaa, 0xcc, 0x55, 0xff };
  86        int err, i;
  87
  88        dmabuf = mock_dmabuf(1);
  89        if (IS_ERR(dmabuf))
  90                return PTR_ERR(dmabuf);
  91
  92        obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf));
  93        if (IS_ERR(obj)) {
  94                pr_err("i915_gem_prime_import failed with err=%d\n",
  95                       (int)PTR_ERR(obj));
  96                err = PTR_ERR(obj);
  97                goto out_dmabuf;
  98        }
  99
 100        if (obj->base.dev != &i915->drm) {
 101                pr_err("i915_gem_prime_import created a non-i915 object!\n");
 102                err = -EINVAL;
 103                goto out_obj;
 104        }
 105
 106        if (obj->base.size != PAGE_SIZE) {
 107                pr_err("i915_gem_prime_import is wrong size found %lld, expected %ld\n",
 108                       (long long)obj->base.size, PAGE_SIZE);
 109                err = -EINVAL;
 110                goto out_obj;
 111        }
 112
 113        dma_map = dma_buf_vmap(dmabuf);
 114        if (!dma_map) {
 115                pr_err("dma_buf_vmap failed\n");
 116                err = -ENOMEM;
 117                goto out_obj;
 118        }
 119
 120        if (0) { /* Can not yet map dmabuf */
 121                obj_map = i915_gem_object_pin_map(obj, I915_MAP_WB);
 122                if (IS_ERR(obj_map)) {
 123                        err = PTR_ERR(obj_map);
 124                        pr_err("i915_gem_object_pin_map failed with err=%d\n", err);
 125                        goto out_dma_map;
 126                }
 127
 128                for (i = 0; i < ARRAY_SIZE(pattern); i++) {
 129                        memset(dma_map, pattern[i], PAGE_SIZE);
 130                        if (memchr_inv(obj_map, pattern[i], PAGE_SIZE)) {
 131                                err = -EINVAL;
 132                                pr_err("imported vmap not all set to %x!\n", pattern[i]);
 133                                i915_gem_object_unpin_map(obj);
 134                                goto out_dma_map;
 135                        }
 136                }
 137
 138                for (i = 0; i < ARRAY_SIZE(pattern); i++) {
 139                        memset(obj_map, pattern[i], PAGE_SIZE);
 140                        if (memchr_inv(dma_map, pattern[i], PAGE_SIZE)) {
 141                                err = -EINVAL;
 142                                pr_err("exported vmap not all set to %x!\n", pattern[i]);
 143                                i915_gem_object_unpin_map(obj);
 144                                goto out_dma_map;
 145                        }
 146                }
 147
 148                i915_gem_object_unpin_map(obj);
 149        }
 150
 151        err = 0;
 152out_dma_map:
 153        dma_buf_vunmap(dmabuf, dma_map);
 154out_obj:
 155        i915_gem_object_put(obj);
 156out_dmabuf:
 157        dma_buf_put(dmabuf);
 158        return err;
 159}
 160
 161static int igt_dmabuf_import_ownership(void *arg)
 162{
 163        struct drm_i915_private *i915 = arg;
 164        struct drm_i915_gem_object *obj;
 165        struct dma_buf *dmabuf;
 166        void *ptr;
 167        int err;
 168
 169        dmabuf = mock_dmabuf(1);
 170        if (IS_ERR(dmabuf))
 171                return PTR_ERR(dmabuf);
 172
 173        ptr = dma_buf_vmap(dmabuf);
 174        if (!ptr) {
 175                pr_err("dma_buf_vmap failed\n");
 176                err = -ENOMEM;
 177                goto err_dmabuf;
 178        }
 179
 180        memset(ptr, 0xc5, PAGE_SIZE);
 181        dma_buf_vunmap(dmabuf, ptr);
 182
 183        obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf));
 184        if (IS_ERR(obj)) {
 185                pr_err("i915_gem_prime_import failed with err=%d\n",
 186                       (int)PTR_ERR(obj));
 187                err = PTR_ERR(obj);
 188                goto err_dmabuf;
 189        }
 190
 191        dma_buf_put(dmabuf);
 192
 193        err = i915_gem_object_pin_pages(obj);
 194        if (err) {
 195                pr_err("i915_gem_object_pin_pages failed with err=%d\n", err);
 196                goto out_obj;
 197        }
 198
 199        err = 0;
 200        i915_gem_object_unpin_pages(obj);
 201out_obj:
 202        i915_gem_object_put(obj);
 203        return err;
 204
 205err_dmabuf:
 206        dma_buf_put(dmabuf);
 207        return err;
 208}
 209
 210static int igt_dmabuf_export_vmap(void *arg)
 211{
 212        struct drm_i915_private *i915 = arg;
 213        struct drm_i915_gem_object *obj;
 214        struct dma_buf *dmabuf;
 215        void *ptr;
 216        int err;
 217
 218        obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
 219        if (IS_ERR(obj))
 220                return PTR_ERR(obj);
 221
 222        dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0);
 223        if (IS_ERR(dmabuf)) {
 224                pr_err("i915_gem_prime_export failed with err=%d\n",
 225                       (int)PTR_ERR(dmabuf));
 226                err = PTR_ERR(dmabuf);
 227                goto err_obj;
 228        }
 229        i915_gem_object_put(obj);
 230
 231        ptr = dma_buf_vmap(dmabuf);
 232        if (!ptr) {
 233                pr_err("dma_buf_vmap failed\n");
 234                err = -ENOMEM;
 235                goto out;
 236        }
 237
 238        if (memchr_inv(ptr, 0, dmabuf->size)) {
 239                pr_err("Exported object not initialiased to zero!\n");
 240                err = -EINVAL;
 241                goto out;
 242        }
 243
 244        memset(ptr, 0xc5, dmabuf->size);
 245
 246        err = 0;
 247        dma_buf_vunmap(dmabuf, ptr);
 248out:
 249        dma_buf_put(dmabuf);
 250        return err;
 251
 252err_obj:
 253        i915_gem_object_put(obj);
 254        return err;
 255}
 256
 257static int igt_dmabuf_export_kmap(void *arg)
 258{
 259        struct drm_i915_private *i915 = arg;
 260        struct drm_i915_gem_object *obj;
 261        struct dma_buf *dmabuf;
 262        void *ptr;
 263        int err;
 264
 265        obj = i915_gem_object_create_shmem(i915, 2 * PAGE_SIZE);
 266        if (IS_ERR(obj))
 267                return PTR_ERR(obj);
 268
 269        dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0);
 270        i915_gem_object_put(obj);
 271        if (IS_ERR(dmabuf)) {
 272                err = PTR_ERR(dmabuf);
 273                pr_err("i915_gem_prime_export failed with err=%d\n", err);
 274                return err;
 275        }
 276
 277        ptr = dma_buf_kmap(dmabuf, 0);
 278        if (!ptr) {
 279                pr_err("dma_buf_kmap failed\n");
 280                err = -ENOMEM;
 281                goto err;
 282        }
 283
 284        if (memchr_inv(ptr, 0, PAGE_SIZE)) {
 285                dma_buf_kunmap(dmabuf, 0, ptr);
 286                pr_err("Exported page[0] not initialiased to zero!\n");
 287                err = -EINVAL;
 288                goto err;
 289        }
 290
 291        memset(ptr, 0xc5, PAGE_SIZE);
 292        dma_buf_kunmap(dmabuf, 0, ptr);
 293
 294        ptr = i915_gem_object_pin_map(obj, I915_MAP_WB);
 295        if (IS_ERR(ptr)) {
 296                err = PTR_ERR(ptr);
 297                pr_err("i915_gem_object_pin_map failed with err=%d\n", err);
 298                goto err;
 299        }
 300        memset(ptr + PAGE_SIZE, 0xaa, PAGE_SIZE);
 301        i915_gem_object_flush_map(obj);
 302        i915_gem_object_unpin_map(obj);
 303
 304        ptr = dma_buf_kmap(dmabuf, 1);
 305        if (!ptr) {
 306                pr_err("dma_buf_kmap failed\n");
 307                err = -ENOMEM;
 308                goto err;
 309        }
 310
 311        if (memchr_inv(ptr, 0xaa, PAGE_SIZE)) {
 312                dma_buf_kunmap(dmabuf, 1, ptr);
 313                pr_err("Exported page[1] not set to 0xaa!\n");
 314                err = -EINVAL;
 315                goto err;
 316        }
 317
 318        memset(ptr, 0xc5, PAGE_SIZE);
 319        dma_buf_kunmap(dmabuf, 1, ptr);
 320
 321        ptr = dma_buf_kmap(dmabuf, 0);
 322        if (!ptr) {
 323                pr_err("dma_buf_kmap failed\n");
 324                err = -ENOMEM;
 325                goto err;
 326        }
 327        if (memchr_inv(ptr, 0xc5, PAGE_SIZE)) {
 328                dma_buf_kunmap(dmabuf, 0, ptr);
 329                pr_err("Exported page[0] did not retain 0xc5!\n");
 330                err = -EINVAL;
 331                goto err;
 332        }
 333        dma_buf_kunmap(dmabuf, 0, ptr);
 334
 335        ptr = dma_buf_kmap(dmabuf, 2);
 336        if (ptr) {
 337                pr_err("Erroneously kmapped beyond the end of the object!\n");
 338                dma_buf_kunmap(dmabuf, 2, ptr);
 339                err = -EINVAL;
 340                goto err;
 341        }
 342
 343        ptr = dma_buf_kmap(dmabuf, -1);
 344        if (ptr) {
 345                pr_err("Erroneously kmapped before the start of the object!\n");
 346                dma_buf_kunmap(dmabuf, -1, ptr);
 347                err = -EINVAL;
 348                goto err;
 349        }
 350
 351        err = 0;
 352err:
 353        dma_buf_put(dmabuf);
 354        return err;
 355}
 356
 357int i915_gem_dmabuf_mock_selftests(void)
 358{
 359        static const struct i915_subtest tests[] = {
 360                SUBTEST(igt_dmabuf_export),
 361                SUBTEST(igt_dmabuf_import_self),
 362                SUBTEST(igt_dmabuf_import),
 363                SUBTEST(igt_dmabuf_import_ownership),
 364                SUBTEST(igt_dmabuf_export_vmap),
 365                SUBTEST(igt_dmabuf_export_kmap),
 366        };
 367        struct drm_i915_private *i915;
 368        int err;
 369
 370        i915 = mock_gem_device();
 371        if (!i915)
 372                return -ENOMEM;
 373
 374        err = i915_subtests(tests, i915);
 375
 376        drm_dev_put(&i915->drm);
 377        return err;
 378}
 379
 380int i915_gem_dmabuf_live_selftests(struct drm_i915_private *i915)
 381{
 382        static const struct i915_subtest tests[] = {
 383                SUBTEST(igt_dmabuf_export),
 384        };
 385
 386        return i915_subtests(tests, i915);
 387}
 388