diff options
Diffstat (limited to 'drivers/gpu/drm/i915/selftests/i915_vma.c')
| -rw-r--r-- | drivers/gpu/drm/i915/selftests/i915_vma.c | 343 |
1 files changed, 233 insertions, 110 deletions
diff --git a/drivers/gpu/drm/i915/selftests/i915_vma.c b/drivers/gpu/drm/i915/selftests/i915_vma.c index af89c7fc8f59..7c4111e60f2e 100644 --- a/drivers/gpu/drm/i915/selftests/i915_vma.c +++ b/drivers/gpu/drm/i915/selftests/i915_vma.c @@ -25,6 +25,7 @@ #include <linux/prime_numbers.h> #include "gem/i915_gem_context.h" +#include "gem/i915_gem_internal.h" #include "gem/selftests/mock_context.h" #include "i915_scatterlist.h" @@ -39,7 +40,7 @@ static bool assert_vma(struct i915_vma *vma, { bool ok = true; - if (vma->vm != rcu_access_pointer(ctx->vm)) { + if (vma->vm != ctx->vm) { pr_err("VMA created with wrong VM\n"); ok = false; } @@ -50,9 +51,9 @@ static bool assert_vma(struct i915_vma *vma, ok = false; } - if (vma->ggtt_view.type != I915_GGTT_VIEW_NORMAL) { + if (vma->gtt_view.type != I915_GTT_VIEW_NORMAL) { pr_err("VMA created with wrong type [%d]\n", - vma->ggtt_view.type); + vma->gtt_view.type); ok = false; } @@ -62,7 +63,7 @@ static bool assert_vma(struct i915_vma *vma, static struct i915_vma * checked_vma_instance(struct drm_i915_gem_object *obj, struct i915_address_space *vm, - const struct i915_ggtt_view *view) + const struct i915_gtt_view *view) { struct i915_vma *vma; bool ok = true; @@ -90,7 +91,7 @@ checked_vma_instance(struct drm_i915_gem_object *obj, } if (i915_vma_compare(vma, vma->vm, - i915_vma_is_ggtt(vma) ? &vma->ggtt_view : NULL)) { + i915_vma_is_ggtt(vma) ? &vma->gtt_view : NULL)) { pr_err("i915_vma_compare failed with itself\n"); return ERR_PTR(-EINVAL); } @@ -118,7 +119,7 @@ static int create_vmas(struct drm_i915_private *i915, struct i915_vma *vma; int err; - vm = i915_gem_context_get_vm_rcu(ctx); + vm = i915_gem_context_get_eb_vm(ctx); vma = checked_vma_instance(obj, vm, NULL); i915_vm_put(vm); if (IS_ERR(vma)) @@ -158,7 +159,8 @@ static int igt_vma_create(void *arg) LIST_HEAD(objects); int err = -ENOMEM; - /* Exercise creating many vma amonst many objections, checking the + /* + * Exercise creating many vma amongst many objections, checking the * vma creation and lookup routines. */ @@ -291,7 +293,8 @@ static int igt_vma_pin1(void *arg) VALID(8192, PIN_GLOBAL | PIN_OFFSET_BIAS | (ggtt->mappable_end - 4096)), #if !IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM) - /* Misusing BIAS is a programming error (it is not controllable + /* + * Misusing BIAS is a programming error (it is not controllable * from userspace) so when debugging is enabled, it explodes. * However, the tests are still quite interesting for checking * variable start, end and size. @@ -311,7 +314,8 @@ static int igt_vma_pin1(void *arg) struct i915_vma *vma; int err = -EINVAL; - /* Exercise all the weird and wonderful i915_vma_pin requests, + /* + * Exercise all the weird and wonderful i915_vma_pin requests, * focusing on error handling of boundary conditions. */ @@ -340,7 +344,7 @@ static int igt_vma_pin1(void *arg) if (!err) { i915_vma_unpin(vma); - err = i915_vma_unbind(vma); + err = i915_vma_unbind_unlocked(vma); if (err) { pr_err("Failed to unbind single page from GGTT, err=%d\n", err); goto out; @@ -361,7 +365,7 @@ static unsigned long rotated_index(const struct intel_rotation_info *r, unsigned int x, unsigned int y) { - return (r->plane[n].stride * (r->plane[n].height - y - 1) + + return (r->plane[n].src_stride * (r->plane[n].height - y - 1) + r->plane[n].offset + x); } @@ -373,6 +377,8 @@ assert_rotated(struct drm_i915_gem_object *obj, unsigned int x, y; for (x = 0; x < r->plane[n].width; x++) { + unsigned int left; + for (y = 0; y < r->plane[n].height; y++) { unsigned long src_idx; dma_addr_t src; @@ -401,6 +407,31 @@ assert_rotated(struct drm_i915_gem_object *obj, sg = sg_next(sg); } + + left = (r->plane[n].dst_stride - y) * PAGE_SIZE; + + if (!left) + continue; + + if (!sg) { + pr_err("Invalid sg table: too short at plane %d, (%d, %d)!\n", + n, x, y); + return ERR_PTR(-EINVAL); + } + + if (sg_dma_len(sg) != left) { + pr_err("Invalid sg.length, found %d, expected %u for rotated page (%d, %d)\n", + sg_dma_len(sg), left, x, y); + return ERR_PTR(-EINVAL); + } + + if (sg_dma_address(sg) != 0) { + pr_err("Invalid address, found %pad, expected 0 for remapped page (%d, %d)\n", + &sg_dma_address(sg), x, y); + return ERR_PTR(-EINVAL); + } + + sg = sg_next(sg); } return sg; @@ -411,7 +442,7 @@ static unsigned long remapped_index(const struct intel_remapped_info *r, unsigned int x, unsigned int y) { - return (r->plane[n].stride * y + + return (r->plane[n].src_stride * y + r->plane[n].offset + x); } @@ -462,15 +493,55 @@ assert_remapped(struct drm_i915_gem_object *obj, if (!left) sg = sg_next(sg); } + + if (left) { + pr_err("Unexpected sg tail with %d size for remapped page (%d, %d)\n", + left, + x, y); + return ERR_PTR(-EINVAL); + } + + left = (r->plane[n].dst_stride - r->plane[n].width) * PAGE_SIZE; + + if (!left) + continue; + + if (!sg) { + pr_err("Invalid sg table: too short at plane %d, (%d, %d)!\n", + n, x, y); + return ERR_PTR(-EINVAL); + } + + if (sg_dma_len(sg) != left) { + pr_err("Invalid sg.length, found %u, expected %u for remapped page (%d, %d)\n", + sg_dma_len(sg), left, + x, y); + return ERR_PTR(-EINVAL); + } + + if (sg_dma_address(sg) != 0) { + pr_err("Invalid address, found %pad, expected 0 for remapped page (%d, %d)\n", + &sg_dma_address(sg), + x, y); + return ERR_PTR(-EINVAL); + } + + sg = sg_next(sg); + left = 0; } return sg; } -static unsigned int rotated_size(const struct intel_remapped_plane_info *a, - const struct intel_remapped_plane_info *b) +static unsigned int remapped_size(enum i915_gtt_view_type view_type, + const struct intel_remapped_plane_info *a, + const struct intel_remapped_plane_info *b) { - return a->width * a->height + b->width * b->height; + + if (view_type == I915_GTT_VIEW_ROTATED) + return a->dst_stride * a->width + b->dst_stride * b->width; + else + return a->dst_stride * a->height + b->dst_stride * b->height; } static int igt_vma_rotate_remap(void *arg) @@ -479,32 +550,38 @@ static int igt_vma_rotate_remap(void *arg) struct i915_address_space *vm = &ggtt->vm; struct drm_i915_gem_object *obj; const struct intel_remapped_plane_info planes[] = { - { .width = 1, .height = 1, .stride = 1 }, - { .width = 2, .height = 2, .stride = 2 }, - { .width = 4, .height = 4, .stride = 4 }, - { .width = 8, .height = 8, .stride = 8 }, + { .width = 1, .height = 1, .src_stride = 1 }, + { .width = 2, .height = 2, .src_stride = 2 }, + { .width = 4, .height = 4, .src_stride = 4 }, + { .width = 8, .height = 8, .src_stride = 8 }, + + { .width = 3, .height = 5, .src_stride = 3 }, + { .width = 3, .height = 5, .src_stride = 4 }, + { .width = 3, .height = 5, .src_stride = 5 }, - { .width = 3, .height = 5, .stride = 3 }, - { .width = 3, .height = 5, .stride = 4 }, - { .width = 3, .height = 5, .stride = 5 }, + { .width = 5, .height = 3, .src_stride = 5 }, + { .width = 5, .height = 3, .src_stride = 7 }, + { .width = 5, .height = 3, .src_stride = 9 }, - { .width = 5, .height = 3, .stride = 5 }, - { .width = 5, .height = 3, .stride = 7 }, - { .width = 5, .height = 3, .stride = 9 }, + { .width = 4, .height = 6, .src_stride = 6 }, + { .width = 6, .height = 4, .src_stride = 6 }, + + { .width = 2, .height = 2, .src_stride = 2, .dst_stride = 2 }, + { .width = 3, .height = 3, .src_stride = 3, .dst_stride = 4 }, + { .width = 5, .height = 6, .src_stride = 7, .dst_stride = 8 }, - { .width = 4, .height = 6, .stride = 6 }, - { .width = 6, .height = 4, .stride = 6 }, { } }, *a, *b; - enum i915_ggtt_view_type types[] = { - I915_GGTT_VIEW_ROTATED, - I915_GGTT_VIEW_REMAPPED, + enum i915_gtt_view_type types[] = { + I915_GTT_VIEW_ROTATED, + I915_GTT_VIEW_REMAPPED, 0, }, *t; const unsigned int max_pages = 64; int err = -ENOMEM; - /* Create VMA for many different combinations of planes and check + /* + * Create VMA for many different combinations of planes and check * that the page layout within the rotated VMA match our expectations. */ @@ -515,22 +592,33 @@ static int igt_vma_rotate_remap(void *arg) for (t = types; *t; t++) { for (a = planes; a->width; a++) { for (b = planes + ARRAY_SIZE(planes); b-- != planes; ) { - struct i915_ggtt_view view; + struct i915_gtt_view view = { + .type = *t, + .remapped.plane[0] = *a, + .remapped.plane[1] = *b, + }; + struct intel_remapped_plane_info *plane_info = view.remapped.plane; unsigned int n, max_offset; - max_offset = max(a->stride * a->height, - b->stride * b->height); + max_offset = max(plane_info[0].src_stride * plane_info[0].height, + plane_info[1].src_stride * plane_info[1].height); GEM_BUG_ON(max_offset > max_pages); max_offset = max_pages - max_offset; - view.type = *t; - view.rotated.plane[0] = *a; - view.rotated.plane[1] = *b; - - for_each_prime_number_from(view.rotated.plane[0].offset, 0, max_offset) { - for_each_prime_number_from(view.rotated.plane[1].offset, 0, max_offset) { + if (!plane_info[0].dst_stride) + plane_info[0].dst_stride = view.type == I915_GTT_VIEW_ROTATED ? + plane_info[0].height : + plane_info[0].width; + if (!plane_info[1].dst_stride) + plane_info[1].dst_stride = view.type == I915_GTT_VIEW_ROTATED ? + plane_info[1].height : + plane_info[1].width; + + for_each_prime_number_from(plane_info[0].offset, 0, max_offset) { + for_each_prime_number_from(plane_info[1].offset, 0, max_offset) { struct scatterlist *sg; struct i915_vma *vma; + unsigned int expected_pages; vma = checked_vma_instance(obj, vm, &view); if (IS_ERR(vma)) { @@ -544,25 +632,27 @@ static int igt_vma_rotate_remap(void *arg) goto out_object; } - if (view.type == I915_GGTT_VIEW_ROTATED && - vma->size != rotated_size(a, b) * PAGE_SIZE) { + expected_pages = remapped_size(view.type, &plane_info[0], &plane_info[1]); + + if (view.type == I915_GTT_VIEW_ROTATED && + vma->size != expected_pages * PAGE_SIZE) { pr_err("VMA is wrong size, expected %lu, found %llu\n", - PAGE_SIZE * rotated_size(a, b), vma->size); + PAGE_SIZE * expected_pages, vma->size); err = -EINVAL; goto out_object; } - if (view.type == I915_GGTT_VIEW_REMAPPED && - vma->size > rotated_size(a, b) * PAGE_SIZE) { + if (view.type == I915_GTT_VIEW_REMAPPED && + vma->size > expected_pages * PAGE_SIZE) { pr_err("VMA is wrong size, expected %lu, found %llu\n", - PAGE_SIZE * rotated_size(a, b), vma->size); + PAGE_SIZE * expected_pages, vma->size); err = -EINVAL; goto out_object; } - if (vma->pages->nents > rotated_size(a, b)) { + if (vma->pages->nents > expected_pages) { pr_err("sg table is wrong sizeo, expected %u, found %u nents\n", - rotated_size(a, b), vma->pages->nents); + expected_pages, vma->pages->nents); err = -EINVAL; goto out_object; } @@ -582,29 +672,35 @@ static int igt_vma_rotate_remap(void *arg) sg = vma->pages->sgl; for (n = 0; n < ARRAY_SIZE(view.rotated.plane); n++) { - if (view.type == I915_GGTT_VIEW_ROTATED) + if (view.type == I915_GTT_VIEW_ROTATED) sg = assert_rotated(obj, &view.rotated, n, sg); else sg = assert_remapped(obj, &view.remapped, n, sg); if (IS_ERR(sg)) { - pr_err("Inconsistent %s VMA pages for plane %d: [(%d, %d, %d, %d), (%d, %d, %d, %d)]\n", - view.type == I915_GGTT_VIEW_ROTATED ? + pr_err("Inconsistent %s VMA pages for plane %d: [(%d, %d, %d, %d, %d), (%d, %d, %d, %d, %d)]\n", + view.type == I915_GTT_VIEW_ROTATED ? "rotated" : "remapped", n, - view.rotated.plane[0].width, - view.rotated.plane[0].height, - view.rotated.plane[0].stride, - view.rotated.plane[0].offset, - view.rotated.plane[1].width, - view.rotated.plane[1].height, - view.rotated.plane[1].stride, - view.rotated.plane[1].offset); + plane_info[0].width, + plane_info[0].height, + plane_info[0].src_stride, + plane_info[0].dst_stride, + plane_info[0].offset, + plane_info[1].width, + plane_info[1].height, + plane_info[1].src_stride, + plane_info[1].dst_stride, + plane_info[1].offset); err = -EINVAL; goto out_object; } } i915_vma_unpin(vma); - + err = i915_vma_unbind_unlocked(vma); + if (err) { + pr_err("Unbinding returned %i\n", err); + goto out_object; + } cond_resched(); } } @@ -649,7 +745,7 @@ static bool assert_partial(struct drm_i915_gem_object *obj, } static bool assert_pin(struct i915_vma *vma, - struct i915_ggtt_view *view, + struct i915_gtt_view *view, u64 size, const char *name) { @@ -667,8 +763,8 @@ static bool assert_pin(struct i915_vma *vma, ok = false; } - if (view && view->type != I915_GGTT_VIEW_NORMAL) { - if (memcmp(&vma->ggtt_view, view, sizeof(*view))) { + if (view && view->type != I915_GTT_VIEW_NORMAL) { + if (memcmp(&vma->gtt_view, view, sizeof(*view))) { pr_err("(%s) VMA mismatch upon creation!\n", name); ok = false; @@ -680,9 +776,9 @@ static bool assert_pin(struct i915_vma *vma, ok = false; } } else { - if (vma->ggtt_view.type != I915_GGTT_VIEW_NORMAL) { + if (vma->gtt_view.type != I915_GTT_VIEW_NORMAL) { pr_err("Not the normal ggtt view! Found %d\n", - vma->ggtt_view.type); + vma->gtt_view.type); ok = false; } @@ -712,7 +808,8 @@ static int igt_vma_partial(void *arg) struct i915_vma *vma; int err = -ENOMEM; - /* Create lots of different VMA for the object and check that + /* + * Create lots of different VMA for the object and check that * we are returned the same VMA when we later request the same range. */ @@ -726,14 +823,14 @@ static int igt_vma_partial(void *arg) nvma = 0; for_each_prime_number_from(sz, 1, npages) { for_each_prime_number_from(offset, 0, npages - sz) { - struct i915_ggtt_view view; + struct i915_gtt_view view; - view.type = I915_GGTT_VIEW_PARTIAL; + view.type = I915_GTT_VIEW_PARTIAL; view.partial.offset = offset; view.partial.size = sz; if (sz == npages) - view.type = I915_GGTT_VIEW_NORMAL; + view.type = I915_GTT_VIEW_NORMAL; vma = checked_vma_instance(obj, vm, &view); if (IS_ERR(vma)) { @@ -761,6 +858,11 @@ static int igt_vma_partial(void *arg) i915_vma_unpin(vma); nvma++; + err = i915_vma_unbind_unlocked(vma); + if (err) { + pr_err("Unbinding returned %i\n", err); + goto out_object; + } cond_resched(); } @@ -795,6 +897,12 @@ static int igt_vma_partial(void *arg) i915_vma_unpin(vma); + err = i915_vma_unbind_unlocked(vma); + if (err) { + pr_err("Unbinding returned %i\n", err); + goto out_object; + } + count = 0; list_for_each_entry(vma, &obj->vma.list, obj_link) count++; @@ -820,28 +928,30 @@ int i915_vma_mock_selftests(void) SUBTEST(igt_vma_partial), }; struct drm_i915_private *i915; - struct i915_ggtt *ggtt; + struct intel_gt *gt; int err; i915 = mock_gem_device(); if (!i915) return -ENOMEM; - ggtt = kmalloc(sizeof(*ggtt), GFP_KERNEL); - if (!ggtt) { - err = -ENOMEM; + /* allocate the ggtt */ + err = intel_gt_assign_ggtt(to_gt(i915)); + if (err) goto out_put; - } - mock_init_ggtt(i915, ggtt); - err = i915_subtests(tests, ggtt); + gt = to_gt(i915); + + mock_init_ggtt(gt); + + err = i915_subtests(tests, gt->ggtt); mock_device_flush(i915); i915_gem_drain_freed_objects(i915); - mock_fini_ggtt(ggtt); - kfree(ggtt); + mock_fini_ggtt(gt->ggtt); + out_put: - drm_dev_put(&i915->drm); + mock_destroy_device(i915); return err; } @@ -849,32 +959,40 @@ static int igt_vma_remapped_gtt(void *arg) { struct drm_i915_private *i915 = arg; const struct intel_remapped_plane_info planes[] = { - { .width = 1, .height = 1, .stride = 1 }, - { .width = 2, .height = 2, .stride = 2 }, - { .width = 4, .height = 4, .stride = 4 }, - { .width = 8, .height = 8, .stride = 8 }, + { .width = 1, .height = 1, .src_stride = 1 }, + { .width = 2, .height = 2, .src_stride = 2 }, + { .width = 4, .height = 4, .src_stride = 4 }, + { .width = 8, .height = 8, .src_stride = 8 }, - { .width = 3, .height = 5, .stride = 3 }, - { .width = 3, .height = 5, .stride = 4 }, - { .width = 3, .height = 5, .stride = 5 }, + { .width = 3, .height = 5, .src_stride = 3 }, + { .width = 3, .height = 5, .src_stride = 4 }, + { .width = 3, .height = 5, .src_stride = 5 }, - { .width = 5, .height = 3, .stride = 5 }, - { .width = 5, .height = 3, .stride = 7 }, - { .width = 5, .height = 3, .stride = 9 }, + { .width = 5, .height = 3, .src_stride = 5 }, + { .width = 5, .height = 3, .src_stride = 7 }, + { .width = 5, .height = 3, .src_stride = 9 }, + + { .width = 4, .height = 6, .src_stride = 6 }, + { .width = 6, .height = 4, .src_stride = 6 }, + + { .width = 2, .height = 2, .src_stride = 2, .dst_stride = 2 }, + { .width = 3, .height = 3, .src_stride = 3, .dst_stride = 4 }, + { .width = 5, .height = 6, .src_stride = 7, .dst_stride = 8 }, - { .width = 4, .height = 6, .stride = 6 }, - { .width = 6, .height = 4, .stride = 6 }, { } }, *p; - enum i915_ggtt_view_type types[] = { - I915_GGTT_VIEW_ROTATED, - I915_GGTT_VIEW_REMAPPED, + enum i915_gtt_view_type types[] = { + I915_GTT_VIEW_ROTATED, + I915_GTT_VIEW_REMAPPED, 0, }, *t; struct drm_i915_gem_object *obj; intel_wakeref_t wakeref; int err = 0; + if (!i915_ggtt_has_aperture(to_gt(i915)->ggtt)) + return 0; + obj = i915_gem_object_create_internal(i915, 10 * 10 * PAGE_SIZE); if (IS_ERR(obj)) return PTR_ERR(obj); @@ -883,28 +1001,32 @@ static int igt_vma_remapped_gtt(void *arg) for (t = types; *t; t++) { for (p = planes; p->width; p++) { - struct i915_ggtt_view view = { + struct i915_gtt_view view = { .type = *t, .rotated.plane[0] = *p, }; + struct intel_remapped_plane_info *plane_info = view.rotated.plane; struct i915_vma *vma; u32 __iomem *map; unsigned int x, y; - int err; - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); err = i915_gem_object_set_to_gtt_domain(obj, true); i915_gem_object_unlock(obj); if (err) goto out; + if (!plane_info[0].dst_stride) + plane_info[0].dst_stride = *t == I915_GTT_VIEW_ROTATED ? + p->height : p->width; + vma = i915_gem_object_ggtt_pin(obj, &view, 0, 0, PIN_MAPPABLE); if (IS_ERR(vma)) { err = PTR_ERR(vma); goto out; } - GEM_BUG_ON(vma->ggtt_view.type != *t); + GEM_BUG_ON(vma->gtt_view.type != *t); map = i915_vma_pin_iomap(vma); i915_vma_unpin(vma); @@ -913,15 +1035,15 @@ static int igt_vma_remapped_gtt(void *arg) goto out; } - for (y = 0 ; y < p->height; y++) { - for (x = 0 ; x < p->width; x++) { + for (y = 0 ; y < plane_info[0].height; y++) { + for (x = 0 ; x < plane_info[0].width; x++) { unsigned int offset; u32 val = y << 16 | x; - if (*t == I915_GGTT_VIEW_ROTATED) - offset = (x * p->height + y) * PAGE_SIZE; + if (*t == I915_GTT_VIEW_ROTATED) + offset = (x * plane_info[0].dst_stride + y) * PAGE_SIZE; else - offset = (y * p->width + x) * PAGE_SIZE; + offset = (y * plane_info[0].dst_stride + x) * PAGE_SIZE; iowrite32(val, &map[offset / sizeof(*map)]); } @@ -935,7 +1057,7 @@ static int igt_vma_remapped_gtt(void *arg) goto out; } - GEM_BUG_ON(vma->ggtt_view.type != I915_GGTT_VIEW_NORMAL); + GEM_BUG_ON(vma->gtt_view.type != I915_GTT_VIEW_NORMAL); map = i915_vma_pin_iomap(vma); i915_vma_unpin(vma); @@ -944,13 +1066,13 @@ static int igt_vma_remapped_gtt(void *arg) goto out; } - for (y = 0 ; y < p->height; y++) { - for (x = 0 ; x < p->width; x++) { + for (y = 0 ; y < plane_info[0].height; y++) { + for (x = 0 ; x < plane_info[0].width; x++) { unsigned int offset, src_idx; u32 exp = y << 16 | x; u32 val; - if (*t == I915_GGTT_VIEW_ROTATED) + if (*t == I915_GTT_VIEW_ROTATED) src_idx = rotated_index(&view.rotated, 0, x, y); else src_idx = remapped_index(&view.remapped, 0, x, y); @@ -959,9 +1081,10 @@ static int igt_vma_remapped_gtt(void *arg) val = ioread32(&map[offset / sizeof(*map)]); if (val != exp) { pr_err("%s VMA write test failed, expected 0x%x, found 0x%x\n", - *t == I915_GGTT_VIEW_ROTATED ? "Rotated" : "Remapped", - val, exp); + *t == I915_GTT_VIEW_ROTATED ? "Rotated" : "Remapped", + exp, val); i915_vma_unpin_iomap(vma); + err = -EINVAL; goto out; } } @@ -985,5 +1108,5 @@ int i915_vma_live_selftests(struct drm_i915_private *i915) SUBTEST(igt_vma_remapped_gtt), }; - return i915_subtests(tests, i915); + return i915_live_subtests(tests, i915); } |
