| .. | .. |
|---|
| 24 | 24 | |
|---|
| 25 | 25 | #include <linux/prime_numbers.h> |
|---|
| 26 | 26 | |
|---|
| 27 | | -#include "../i915_selftest.h" |
|---|
| 27 | +#include "gem/i915_gem_context.h" |
|---|
| 28 | +#include "gem/selftests/mock_context.h" |
|---|
| 29 | + |
|---|
| 30 | +#include "i915_scatterlist.h" |
|---|
| 31 | +#include "i915_selftest.h" |
|---|
| 28 | 32 | |
|---|
| 29 | 33 | #include "mock_gem_device.h" |
|---|
| 30 | | -#include "mock_context.h" |
|---|
| 34 | +#include "mock_gtt.h" |
|---|
| 31 | 35 | |
|---|
| 32 | 36 | static bool assert_vma(struct i915_vma *vma, |
|---|
| 33 | 37 | struct drm_i915_gem_object *obj, |
|---|
| .. | .. |
|---|
| 35 | 39 | { |
|---|
| 36 | 40 | bool ok = true; |
|---|
| 37 | 41 | |
|---|
| 38 | | - if (vma->vm != &ctx->ppgtt->vm) { |
|---|
| 42 | + if (vma->vm != rcu_access_pointer(ctx->vm)) { |
|---|
| 39 | 43 | pr_err("VMA created with wrong VM\n"); |
|---|
| 40 | 44 | ok = false; |
|---|
| 41 | 45 | } |
|---|
| .. | .. |
|---|
| 58 | 62 | static struct i915_vma * |
|---|
| 59 | 63 | checked_vma_instance(struct drm_i915_gem_object *obj, |
|---|
| 60 | 64 | struct i915_address_space *vm, |
|---|
| 61 | | - struct i915_ggtt_view *view) |
|---|
| 65 | + const struct i915_ggtt_view *view) |
|---|
| 62 | 66 | { |
|---|
| 63 | 67 | struct i915_vma *vma; |
|---|
| 64 | 68 | bool ok = true; |
|---|
| .. | .. |
|---|
| 110 | 114 | list_for_each_entry(obj, objects, st_link) { |
|---|
| 111 | 115 | for (pinned = 0; pinned <= 1; pinned++) { |
|---|
| 112 | 116 | list_for_each_entry(ctx, contexts, link) { |
|---|
| 113 | | - struct i915_address_space *vm = &ctx->ppgtt->vm; |
|---|
| 117 | + struct i915_address_space *vm; |
|---|
| 114 | 118 | struct i915_vma *vma; |
|---|
| 115 | 119 | int err; |
|---|
| 116 | 120 | |
|---|
| 121 | + vm = i915_gem_context_get_vm_rcu(ctx); |
|---|
| 117 | 122 | vma = checked_vma_instance(obj, vm, NULL); |
|---|
| 123 | + i915_vm_put(vm); |
|---|
| 118 | 124 | if (IS_ERR(vma)) |
|---|
| 119 | 125 | return PTR_ERR(vma); |
|---|
| 120 | 126 | |
|---|
| .. | .. |
|---|
| 141 | 147 | |
|---|
| 142 | 148 | static int igt_vma_create(void *arg) |
|---|
| 143 | 149 | { |
|---|
| 144 | | - struct drm_i915_private *i915 = arg; |
|---|
| 150 | + struct i915_ggtt *ggtt = arg; |
|---|
| 151 | + struct drm_i915_private *i915 = ggtt->vm.i915; |
|---|
| 145 | 152 | struct drm_i915_gem_object *obj, *on; |
|---|
| 146 | 153 | struct i915_gem_context *ctx, *cn; |
|---|
| 147 | 154 | unsigned long num_obj, num_ctx; |
|---|
| .. | .. |
|---|
| 166 | 173 | } |
|---|
| 167 | 174 | |
|---|
| 168 | 175 | nc = 0; |
|---|
| 169 | | - for_each_prime_number(num_ctx, MAX_CONTEXT_HW_ID) { |
|---|
| 176 | + for_each_prime_number(num_ctx, 2 * BITS_PER_LONG) { |
|---|
| 170 | 177 | for (; nc < num_ctx; nc++) { |
|---|
| 171 | 178 | ctx = mock_context(i915, "mock"); |
|---|
| 172 | 179 | if (!ctx) |
|---|
| .. | .. |
|---|
| 189 | 196 | list_del_init(&ctx->link); |
|---|
| 190 | 197 | mock_context_close(ctx); |
|---|
| 191 | 198 | } |
|---|
| 199 | + |
|---|
| 200 | + cond_resched(); |
|---|
| 192 | 201 | } |
|---|
| 193 | 202 | |
|---|
| 194 | 203 | end: |
|---|
| .. | .. |
|---|
| 245 | 254 | |
|---|
| 246 | 255 | static int igt_vma_pin1(void *arg) |
|---|
| 247 | 256 | { |
|---|
| 248 | | - struct drm_i915_private *i915 = arg; |
|---|
| 257 | + struct i915_ggtt *ggtt = arg; |
|---|
| 249 | 258 | const struct pin_mode modes[] = { |
|---|
| 250 | 259 | #define VALID(sz, fl) { .size = (sz), .flags = (fl), .assert = assert_pin_valid, .string = #sz ", " #fl ", (valid) " } |
|---|
| 251 | 260 | #define __INVALID(sz, fl, check, eval) { .size = (sz), .flags = (fl), .assert = (check), .string = #sz ", " #fl ", (invalid " #eval ")" } |
|---|
| .. | .. |
|---|
| 256 | 265 | |
|---|
| 257 | 266 | VALID(0, PIN_GLOBAL | PIN_OFFSET_BIAS | 4096), |
|---|
| 258 | 267 | VALID(0, PIN_GLOBAL | PIN_OFFSET_BIAS | 8192), |
|---|
| 259 | | - VALID(0, PIN_GLOBAL | PIN_OFFSET_BIAS | (i915->ggtt.mappable_end - 4096)), |
|---|
| 260 | | - VALID(0, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_BIAS | (i915->ggtt.mappable_end - 4096)), |
|---|
| 261 | | - VALID(0, PIN_GLOBAL | PIN_OFFSET_BIAS | (i915->ggtt.vm.total - 4096)), |
|---|
| 268 | + VALID(0, PIN_GLOBAL | PIN_OFFSET_BIAS | (ggtt->mappable_end - 4096)), |
|---|
| 269 | + VALID(0, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_BIAS | (ggtt->mappable_end - 4096)), |
|---|
| 270 | + VALID(0, PIN_GLOBAL | PIN_OFFSET_BIAS | (ggtt->vm.total - 4096)), |
|---|
| 262 | 271 | |
|---|
| 263 | | - VALID(0, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_FIXED | (i915->ggtt.mappable_end - 4096)), |
|---|
| 264 | | - INVALID(0, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_FIXED | i915->ggtt.mappable_end), |
|---|
| 265 | | - VALID(0, PIN_GLOBAL | PIN_OFFSET_FIXED | (i915->ggtt.vm.total - 4096)), |
|---|
| 266 | | - INVALID(0, PIN_GLOBAL | PIN_OFFSET_FIXED | i915->ggtt.vm.total), |
|---|
| 272 | + VALID(0, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_FIXED | (ggtt->mappable_end - 4096)), |
|---|
| 273 | + INVALID(0, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_FIXED | ggtt->mappable_end), |
|---|
| 274 | + VALID(0, PIN_GLOBAL | PIN_OFFSET_FIXED | (ggtt->vm.total - 4096)), |
|---|
| 275 | + INVALID(0, PIN_GLOBAL | PIN_OFFSET_FIXED | ggtt->vm.total), |
|---|
| 267 | 276 | INVALID(0, PIN_GLOBAL | PIN_OFFSET_FIXED | round_down(U64_MAX, PAGE_SIZE)), |
|---|
| 268 | 277 | |
|---|
| 269 | 278 | VALID(4096, PIN_GLOBAL), |
|---|
| 270 | 279 | VALID(8192, PIN_GLOBAL), |
|---|
| 271 | | - VALID(i915->ggtt.mappable_end - 4096, PIN_GLOBAL | PIN_MAPPABLE), |
|---|
| 272 | | - VALID(i915->ggtt.mappable_end, PIN_GLOBAL | PIN_MAPPABLE), |
|---|
| 273 | | - NOSPACE(i915->ggtt.mappable_end + 4096, PIN_GLOBAL | PIN_MAPPABLE), |
|---|
| 274 | | - VALID(i915->ggtt.vm.total - 4096, PIN_GLOBAL), |
|---|
| 275 | | - VALID(i915->ggtt.vm.total, PIN_GLOBAL), |
|---|
| 276 | | - NOSPACE(i915->ggtt.vm.total + 4096, PIN_GLOBAL), |
|---|
| 280 | + VALID(ggtt->mappable_end - 4096, PIN_GLOBAL | PIN_MAPPABLE), |
|---|
| 281 | + VALID(ggtt->mappable_end, PIN_GLOBAL | PIN_MAPPABLE), |
|---|
| 282 | + NOSPACE(ggtt->mappable_end + 4096, PIN_GLOBAL | PIN_MAPPABLE), |
|---|
| 283 | + VALID(ggtt->vm.total - 4096, PIN_GLOBAL), |
|---|
| 284 | + VALID(ggtt->vm.total, PIN_GLOBAL), |
|---|
| 285 | + NOSPACE(ggtt->vm.total + 4096, PIN_GLOBAL), |
|---|
| 277 | 286 | NOSPACE(round_down(U64_MAX, PAGE_SIZE), PIN_GLOBAL), |
|---|
| 278 | | - INVALID(8192, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_FIXED | (i915->ggtt.mappable_end - 4096)), |
|---|
| 279 | | - INVALID(8192, PIN_GLOBAL | PIN_OFFSET_FIXED | (i915->ggtt.vm.total - 4096)), |
|---|
| 287 | + INVALID(8192, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_FIXED | (ggtt->mappable_end - 4096)), |
|---|
| 288 | + INVALID(8192, PIN_GLOBAL | PIN_OFFSET_FIXED | (ggtt->vm.total - 4096)), |
|---|
| 280 | 289 | INVALID(8192, PIN_GLOBAL | PIN_OFFSET_FIXED | (round_down(U64_MAX, PAGE_SIZE) - 4096)), |
|---|
| 281 | 290 | |
|---|
| 282 | | - VALID(8192, PIN_GLOBAL | PIN_OFFSET_BIAS | (i915->ggtt.mappable_end - 4096)), |
|---|
| 291 | + VALID(8192, PIN_GLOBAL | PIN_OFFSET_BIAS | (ggtt->mappable_end - 4096)), |
|---|
| 283 | 292 | |
|---|
| 284 | 293 | #if !IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM) |
|---|
| 285 | 294 | /* Misusing BIAS is a programming error (it is not controllable |
|---|
| .. | .. |
|---|
| 287 | 296 | * However, the tests are still quite interesting for checking |
|---|
| 288 | 297 | * variable start, end and size. |
|---|
| 289 | 298 | */ |
|---|
| 290 | | - NOSPACE(0, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_BIAS | i915->ggtt.mappable_end), |
|---|
| 291 | | - NOSPACE(0, PIN_GLOBAL | PIN_OFFSET_BIAS | i915->ggtt.vm.total), |
|---|
| 292 | | - NOSPACE(8192, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_BIAS | (i915->ggtt.mappable_end - 4096)), |
|---|
| 293 | | - NOSPACE(8192, PIN_GLOBAL | PIN_OFFSET_BIAS | (i915->ggtt.vm.total - 4096)), |
|---|
| 299 | + NOSPACE(0, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_BIAS | ggtt->mappable_end), |
|---|
| 300 | + NOSPACE(0, PIN_GLOBAL | PIN_OFFSET_BIAS | ggtt->vm.total), |
|---|
| 301 | + NOSPACE(8192, PIN_GLOBAL | PIN_MAPPABLE | PIN_OFFSET_BIAS | (ggtt->mappable_end - 4096)), |
|---|
| 302 | + NOSPACE(8192, PIN_GLOBAL | PIN_OFFSET_BIAS | (ggtt->vm.total - 4096)), |
|---|
| 294 | 303 | #endif |
|---|
| 295 | 304 | { }, |
|---|
| 296 | 305 | #undef NOSPACE |
|---|
| .. | .. |
|---|
| 306 | 315 | * focusing on error handling of boundary conditions. |
|---|
| 307 | 316 | */ |
|---|
| 308 | 317 | |
|---|
| 309 | | - GEM_BUG_ON(!drm_mm_clean(&i915->ggtt.vm.mm)); |
|---|
| 318 | + GEM_BUG_ON(!drm_mm_clean(&ggtt->vm.mm)); |
|---|
| 310 | 319 | |
|---|
| 311 | | - obj = i915_gem_object_create_internal(i915, PAGE_SIZE); |
|---|
| 320 | + obj = i915_gem_object_create_internal(ggtt->vm.i915, PAGE_SIZE); |
|---|
| 312 | 321 | if (IS_ERR(obj)) |
|---|
| 313 | 322 | return PTR_ERR(obj); |
|---|
| 314 | 323 | |
|---|
| 315 | | - vma = checked_vma_instance(obj, &i915->ggtt.vm, NULL); |
|---|
| 324 | + vma = checked_vma_instance(obj, &ggtt->vm, NULL); |
|---|
| 316 | 325 | if (IS_ERR(vma)) |
|---|
| 317 | 326 | goto out; |
|---|
| 318 | 327 | |
|---|
| .. | .. |
|---|
| 337 | 346 | goto out; |
|---|
| 338 | 347 | } |
|---|
| 339 | 348 | } |
|---|
| 349 | + |
|---|
| 350 | + cond_resched(); |
|---|
| 340 | 351 | } |
|---|
| 341 | 352 | |
|---|
| 342 | 353 | err = 0; |
|---|
| .. | .. |
|---|
| 395 | 406 | return sg; |
|---|
| 396 | 407 | } |
|---|
| 397 | 408 | |
|---|
| 398 | | -static unsigned int rotated_size(const struct intel_rotation_plane_info *a, |
|---|
| 399 | | - const struct intel_rotation_plane_info *b) |
|---|
| 409 | +static unsigned long remapped_index(const struct intel_remapped_info *r, |
|---|
| 410 | + unsigned int n, |
|---|
| 411 | + unsigned int x, |
|---|
| 412 | + unsigned int y) |
|---|
| 413 | +{ |
|---|
| 414 | + return (r->plane[n].stride * y + |
|---|
| 415 | + r->plane[n].offset + x); |
|---|
| 416 | +} |
|---|
| 417 | + |
|---|
| 418 | +static struct scatterlist * |
|---|
| 419 | +assert_remapped(struct drm_i915_gem_object *obj, |
|---|
| 420 | + const struct intel_remapped_info *r, unsigned int n, |
|---|
| 421 | + struct scatterlist *sg) |
|---|
| 422 | +{ |
|---|
| 423 | + unsigned int x, y; |
|---|
| 424 | + unsigned int left = 0; |
|---|
| 425 | + unsigned int offset; |
|---|
| 426 | + |
|---|
| 427 | + for (y = 0; y < r->plane[n].height; y++) { |
|---|
| 428 | + for (x = 0; x < r->plane[n].width; x++) { |
|---|
| 429 | + unsigned long src_idx; |
|---|
| 430 | + dma_addr_t src; |
|---|
| 431 | + |
|---|
| 432 | + if (!sg) { |
|---|
| 433 | + pr_err("Invalid sg table: too short at plane %d, (%d, %d)!\n", |
|---|
| 434 | + n, x, y); |
|---|
| 435 | + return ERR_PTR(-EINVAL); |
|---|
| 436 | + } |
|---|
| 437 | + if (!left) { |
|---|
| 438 | + offset = 0; |
|---|
| 439 | + left = sg_dma_len(sg); |
|---|
| 440 | + } |
|---|
| 441 | + |
|---|
| 442 | + src_idx = remapped_index(r, n, x, y); |
|---|
| 443 | + src = i915_gem_object_get_dma_address(obj, src_idx); |
|---|
| 444 | + |
|---|
| 445 | + if (left < PAGE_SIZE || left & (PAGE_SIZE-1)) { |
|---|
| 446 | + pr_err("Invalid sg.length, found %d, expected %lu for remapped page (%d, %d) [src index %lu]\n", |
|---|
| 447 | + sg_dma_len(sg), PAGE_SIZE, |
|---|
| 448 | + x, y, src_idx); |
|---|
| 449 | + return ERR_PTR(-EINVAL); |
|---|
| 450 | + } |
|---|
| 451 | + |
|---|
| 452 | + if (sg_dma_address(sg) + offset != src) { |
|---|
| 453 | + pr_err("Invalid address for remapped page (%d, %d) [src index %lu]\n", |
|---|
| 454 | + x, y, src_idx); |
|---|
| 455 | + return ERR_PTR(-EINVAL); |
|---|
| 456 | + } |
|---|
| 457 | + |
|---|
| 458 | + left -= PAGE_SIZE; |
|---|
| 459 | + offset += PAGE_SIZE; |
|---|
| 460 | + |
|---|
| 461 | + |
|---|
| 462 | + if (!left) |
|---|
| 463 | + sg = sg_next(sg); |
|---|
| 464 | + } |
|---|
| 465 | + } |
|---|
| 466 | + |
|---|
| 467 | + return sg; |
|---|
| 468 | +} |
|---|
| 469 | + |
|---|
| 470 | +static unsigned int rotated_size(const struct intel_remapped_plane_info *a, |
|---|
| 471 | + const struct intel_remapped_plane_info *b) |
|---|
| 400 | 472 | { |
|---|
| 401 | 473 | return a->width * a->height + b->width * b->height; |
|---|
| 402 | 474 | } |
|---|
| 403 | 475 | |
|---|
| 404 | | -static int igt_vma_rotate(void *arg) |
|---|
| 476 | +static int igt_vma_rotate_remap(void *arg) |
|---|
| 405 | 477 | { |
|---|
| 406 | | - struct drm_i915_private *i915 = arg; |
|---|
| 407 | | - struct i915_address_space *vm = &i915->ggtt.vm; |
|---|
| 478 | + struct i915_ggtt *ggtt = arg; |
|---|
| 479 | + struct i915_address_space *vm = &ggtt->vm; |
|---|
| 408 | 480 | struct drm_i915_gem_object *obj; |
|---|
| 409 | | - const struct intel_rotation_plane_info planes[] = { |
|---|
| 481 | + const struct intel_remapped_plane_info planes[] = { |
|---|
| 410 | 482 | { .width = 1, .height = 1, .stride = 1 }, |
|---|
| 411 | 483 | { .width = 2, .height = 2, .stride = 2 }, |
|---|
| 412 | 484 | { .width = 4, .height = 4, .stride = 4 }, |
|---|
| .. | .. |
|---|
| 424 | 496 | { .width = 6, .height = 4, .stride = 6 }, |
|---|
| 425 | 497 | { } |
|---|
| 426 | 498 | }, *a, *b; |
|---|
| 499 | + enum i915_ggtt_view_type types[] = { |
|---|
| 500 | + I915_GGTT_VIEW_ROTATED, |
|---|
| 501 | + I915_GGTT_VIEW_REMAPPED, |
|---|
| 502 | + 0, |
|---|
| 503 | + }, *t; |
|---|
| 427 | 504 | const unsigned int max_pages = 64; |
|---|
| 428 | 505 | int err = -ENOMEM; |
|---|
| 429 | 506 | |
|---|
| .. | .. |
|---|
| 431 | 508 | * that the page layout within the rotated VMA match our expectations. |
|---|
| 432 | 509 | */ |
|---|
| 433 | 510 | |
|---|
| 434 | | - obj = i915_gem_object_create_internal(i915, max_pages * PAGE_SIZE); |
|---|
| 511 | + obj = i915_gem_object_create_internal(vm->i915, max_pages * PAGE_SIZE); |
|---|
| 435 | 512 | if (IS_ERR(obj)) |
|---|
| 436 | 513 | goto out; |
|---|
| 437 | 514 | |
|---|
| 515 | + for (t = types; *t; t++) { |
|---|
| 438 | 516 | for (a = planes; a->width; a++) { |
|---|
| 439 | 517 | for (b = planes + ARRAY_SIZE(planes); b-- != planes; ) { |
|---|
| 440 | 518 | struct i915_ggtt_view view; |
|---|
| .. | .. |
|---|
| 445 | 523 | GEM_BUG_ON(max_offset > max_pages); |
|---|
| 446 | 524 | max_offset = max_pages - max_offset; |
|---|
| 447 | 525 | |
|---|
| 448 | | - view.type = I915_GGTT_VIEW_ROTATED; |
|---|
| 526 | + view.type = *t; |
|---|
| 449 | 527 | view.rotated.plane[0] = *a; |
|---|
| 450 | 528 | view.rotated.plane[1] = *b; |
|---|
| 451 | 529 | |
|---|
| .. | .. |
|---|
| 466 | 544 | goto out_object; |
|---|
| 467 | 545 | } |
|---|
| 468 | 546 | |
|---|
| 469 | | - if (vma->size != rotated_size(a, b) * PAGE_SIZE) { |
|---|
| 547 | + if (view.type == I915_GGTT_VIEW_ROTATED && |
|---|
| 548 | + vma->size != rotated_size(a, b) * PAGE_SIZE) { |
|---|
| 470 | 549 | pr_err("VMA is wrong size, expected %lu, found %llu\n", |
|---|
| 471 | 550 | PAGE_SIZE * rotated_size(a, b), vma->size); |
|---|
| 472 | 551 | err = -EINVAL; |
|---|
| 473 | 552 | goto out_object; |
|---|
| 474 | 553 | } |
|---|
| 475 | 554 | |
|---|
| 476 | | - if (vma->pages->nents != rotated_size(a, b)) { |
|---|
| 555 | + if (view.type == I915_GGTT_VIEW_REMAPPED && |
|---|
| 556 | + vma->size > rotated_size(a, b) * PAGE_SIZE) { |
|---|
| 557 | + pr_err("VMA is wrong size, expected %lu, found %llu\n", |
|---|
| 558 | + PAGE_SIZE * rotated_size(a, b), vma->size); |
|---|
| 559 | + err = -EINVAL; |
|---|
| 560 | + goto out_object; |
|---|
| 561 | + } |
|---|
| 562 | + |
|---|
| 563 | + if (vma->pages->nents > rotated_size(a, b)) { |
|---|
| 477 | 564 | pr_err("sg table is wrong sizeo, expected %u, found %u nents\n", |
|---|
| 478 | 565 | rotated_size(a, b), vma->pages->nents); |
|---|
| 479 | 566 | err = -EINVAL; |
|---|
| .. | .. |
|---|
| 495 | 582 | |
|---|
| 496 | 583 | sg = vma->pages->sgl; |
|---|
| 497 | 584 | for (n = 0; n < ARRAY_SIZE(view.rotated.plane); n++) { |
|---|
| 498 | | - sg = assert_rotated(obj, &view.rotated, n, sg); |
|---|
| 585 | + if (view.type == I915_GGTT_VIEW_ROTATED) |
|---|
| 586 | + sg = assert_rotated(obj, &view.rotated, n, sg); |
|---|
| 587 | + else |
|---|
| 588 | + sg = assert_remapped(obj, &view.remapped, n, sg); |
|---|
| 499 | 589 | if (IS_ERR(sg)) { |
|---|
| 500 | | - pr_err("Inconsistent VMA pages for plane %d: [(%d, %d, %d, %d), (%d, %d, %d, %d)]\n", n, |
|---|
| 590 | + pr_err("Inconsistent %s VMA pages for plane %d: [(%d, %d, %d, %d), (%d, %d, %d, %d)]\n", |
|---|
| 591 | + view.type == I915_GGTT_VIEW_ROTATED ? |
|---|
| 592 | + "rotated" : "remapped", n, |
|---|
| 501 | 593 | view.rotated.plane[0].width, |
|---|
| 502 | 594 | view.rotated.plane[0].height, |
|---|
| 503 | 595 | view.rotated.plane[0].stride, |
|---|
| .. | .. |
|---|
| 512 | 604 | } |
|---|
| 513 | 605 | |
|---|
| 514 | 606 | i915_vma_unpin(vma); |
|---|
| 607 | + |
|---|
| 608 | + cond_resched(); |
|---|
| 515 | 609 | } |
|---|
| 516 | 610 | } |
|---|
| 517 | 611 | } |
|---|
| 612 | + } |
|---|
| 518 | 613 | } |
|---|
| 519 | 614 | |
|---|
| 520 | 615 | out_object: |
|---|
| .. | .. |
|---|
| 531 | 626 | struct sgt_iter sgt; |
|---|
| 532 | 627 | dma_addr_t dma; |
|---|
| 533 | 628 | |
|---|
| 534 | | - for_each_sgt_dma(dma, sgt, vma->pages) { |
|---|
| 629 | + for_each_sgt_daddr(dma, sgt, vma->pages) { |
|---|
| 535 | 630 | dma_addr_t src; |
|---|
| 536 | 631 | |
|---|
| 537 | 632 | if (!size) { |
|---|
| .. | .. |
|---|
| 602 | 697 | |
|---|
| 603 | 698 | static int igt_vma_partial(void *arg) |
|---|
| 604 | 699 | { |
|---|
| 605 | | - struct drm_i915_private *i915 = arg; |
|---|
| 606 | | - struct i915_address_space *vm = &i915->ggtt.vm; |
|---|
| 700 | + struct i915_ggtt *ggtt = arg; |
|---|
| 701 | + struct i915_address_space *vm = &ggtt->vm; |
|---|
| 607 | 702 | const unsigned int npages = 1021; /* prime! */ |
|---|
| 608 | 703 | struct drm_i915_gem_object *obj; |
|---|
| 609 | 704 | const struct phase { |
|---|
| .. | .. |
|---|
| 621 | 716 | * we are returned the same VMA when we later request the same range. |
|---|
| 622 | 717 | */ |
|---|
| 623 | 718 | |
|---|
| 624 | | - obj = i915_gem_object_create_internal(i915, npages*PAGE_SIZE); |
|---|
| 719 | + obj = i915_gem_object_create_internal(vm->i915, npages * PAGE_SIZE); |
|---|
| 625 | 720 | if (IS_ERR(obj)) |
|---|
| 626 | 721 | goto out; |
|---|
| 627 | 722 | |
|---|
| .. | .. |
|---|
| 666 | 761 | |
|---|
| 667 | 762 | i915_vma_unpin(vma); |
|---|
| 668 | 763 | nvma++; |
|---|
| 764 | + |
|---|
| 765 | + cond_resched(); |
|---|
| 669 | 766 | } |
|---|
| 670 | 767 | } |
|---|
| 671 | 768 | |
|---|
| 672 | 769 | count = 0; |
|---|
| 673 | | - list_for_each_entry(vma, &obj->vma_list, obj_link) |
|---|
| 770 | + list_for_each_entry(vma, &obj->vma.list, obj_link) |
|---|
| 674 | 771 | count++; |
|---|
| 675 | 772 | if (count != nvma) { |
|---|
| 676 | 773 | pr_err("(%s) All partial vma were not recorded on the obj->vma_list: found %u, expected %u\n", |
|---|
| .. | .. |
|---|
| 699 | 796 | i915_vma_unpin(vma); |
|---|
| 700 | 797 | |
|---|
| 701 | 798 | count = 0; |
|---|
| 702 | | - list_for_each_entry(vma, &obj->vma_list, obj_link) |
|---|
| 799 | + list_for_each_entry(vma, &obj->vma.list, obj_link) |
|---|
| 703 | 800 | count++; |
|---|
| 704 | 801 | if (count != nvma) { |
|---|
| 705 | 802 | pr_err("(%s) allocated an extra full vma!\n", p->name); |
|---|
| .. | .. |
|---|
| 719 | 816 | static const struct i915_subtest tests[] = { |
|---|
| 720 | 817 | SUBTEST(igt_vma_create), |
|---|
| 721 | 818 | SUBTEST(igt_vma_pin1), |
|---|
| 722 | | - SUBTEST(igt_vma_rotate), |
|---|
| 819 | + SUBTEST(igt_vma_rotate_remap), |
|---|
| 723 | 820 | SUBTEST(igt_vma_partial), |
|---|
| 724 | 821 | }; |
|---|
| 725 | 822 | struct drm_i915_private *i915; |
|---|
| 823 | + struct i915_ggtt *ggtt; |
|---|
| 726 | 824 | int err; |
|---|
| 727 | 825 | |
|---|
| 728 | 826 | i915 = mock_gem_device(); |
|---|
| 729 | 827 | if (!i915) |
|---|
| 730 | 828 | return -ENOMEM; |
|---|
| 731 | 829 | |
|---|
| 732 | | - mutex_lock(&i915->drm.struct_mutex); |
|---|
| 733 | | - err = i915_subtests(tests, i915); |
|---|
| 734 | | - mutex_unlock(&i915->drm.struct_mutex); |
|---|
| 830 | + ggtt = kmalloc(sizeof(*ggtt), GFP_KERNEL); |
|---|
| 831 | + if (!ggtt) { |
|---|
| 832 | + err = -ENOMEM; |
|---|
| 833 | + goto out_put; |
|---|
| 834 | + } |
|---|
| 835 | + mock_init_ggtt(i915, ggtt); |
|---|
| 735 | 836 | |
|---|
| 736 | | - drm_dev_put(&i915->drm); |
|---|
| 837 | + err = i915_subtests(tests, ggtt); |
|---|
| 838 | + |
|---|
| 839 | + mock_device_flush(i915); |
|---|
| 840 | + i915_gem_drain_freed_objects(i915); |
|---|
| 841 | + mock_fini_ggtt(ggtt); |
|---|
| 842 | + kfree(ggtt); |
|---|
| 843 | +out_put: |
|---|
| 844 | + mock_destroy_device(i915); |
|---|
| 737 | 845 | return err; |
|---|
| 738 | 846 | } |
|---|
| 739 | 847 | |
|---|
| 848 | +static int igt_vma_remapped_gtt(void *arg) |
|---|
| 849 | +{ |
|---|
| 850 | + struct drm_i915_private *i915 = arg; |
|---|
| 851 | + const struct intel_remapped_plane_info planes[] = { |
|---|
| 852 | + { .width = 1, .height = 1, .stride = 1 }, |
|---|
| 853 | + { .width = 2, .height = 2, .stride = 2 }, |
|---|
| 854 | + { .width = 4, .height = 4, .stride = 4 }, |
|---|
| 855 | + { .width = 8, .height = 8, .stride = 8 }, |
|---|
| 856 | + |
|---|
| 857 | + { .width = 3, .height = 5, .stride = 3 }, |
|---|
| 858 | + { .width = 3, .height = 5, .stride = 4 }, |
|---|
| 859 | + { .width = 3, .height = 5, .stride = 5 }, |
|---|
| 860 | + |
|---|
| 861 | + { .width = 5, .height = 3, .stride = 5 }, |
|---|
| 862 | + { .width = 5, .height = 3, .stride = 7 }, |
|---|
| 863 | + { .width = 5, .height = 3, .stride = 9 }, |
|---|
| 864 | + |
|---|
| 865 | + { .width = 4, .height = 6, .stride = 6 }, |
|---|
| 866 | + { .width = 6, .height = 4, .stride = 6 }, |
|---|
| 867 | + { } |
|---|
| 868 | + }, *p; |
|---|
| 869 | + enum i915_ggtt_view_type types[] = { |
|---|
| 870 | + I915_GGTT_VIEW_ROTATED, |
|---|
| 871 | + I915_GGTT_VIEW_REMAPPED, |
|---|
| 872 | + 0, |
|---|
| 873 | + }, *t; |
|---|
| 874 | + struct drm_i915_gem_object *obj; |
|---|
| 875 | + intel_wakeref_t wakeref; |
|---|
| 876 | + int err = 0; |
|---|
| 877 | + |
|---|
| 878 | + obj = i915_gem_object_create_internal(i915, 10 * 10 * PAGE_SIZE); |
|---|
| 879 | + if (IS_ERR(obj)) |
|---|
| 880 | + return PTR_ERR(obj); |
|---|
| 881 | + |
|---|
| 882 | + wakeref = intel_runtime_pm_get(&i915->runtime_pm); |
|---|
| 883 | + |
|---|
| 884 | + for (t = types; *t; t++) { |
|---|
| 885 | + for (p = planes; p->width; p++) { |
|---|
| 886 | + struct i915_ggtt_view view = { |
|---|
| 887 | + .type = *t, |
|---|
| 888 | + .rotated.plane[0] = *p, |
|---|
| 889 | + }; |
|---|
| 890 | + struct i915_vma *vma; |
|---|
| 891 | + u32 __iomem *map; |
|---|
| 892 | + unsigned int x, y; |
|---|
| 893 | + int err; |
|---|
| 894 | + |
|---|
| 895 | + i915_gem_object_lock(obj, NULL); |
|---|
| 896 | + err = i915_gem_object_set_to_gtt_domain(obj, true); |
|---|
| 897 | + i915_gem_object_unlock(obj); |
|---|
| 898 | + if (err) |
|---|
| 899 | + goto out; |
|---|
| 900 | + |
|---|
| 901 | + vma = i915_gem_object_ggtt_pin(obj, &view, 0, 0, PIN_MAPPABLE); |
|---|
| 902 | + if (IS_ERR(vma)) { |
|---|
| 903 | + err = PTR_ERR(vma); |
|---|
| 904 | + goto out; |
|---|
| 905 | + } |
|---|
| 906 | + |
|---|
| 907 | + GEM_BUG_ON(vma->ggtt_view.type != *t); |
|---|
| 908 | + |
|---|
| 909 | + map = i915_vma_pin_iomap(vma); |
|---|
| 910 | + i915_vma_unpin(vma); |
|---|
| 911 | + if (IS_ERR(map)) { |
|---|
| 912 | + err = PTR_ERR(map); |
|---|
| 913 | + goto out; |
|---|
| 914 | + } |
|---|
| 915 | + |
|---|
| 916 | + for (y = 0 ; y < p->height; y++) { |
|---|
| 917 | + for (x = 0 ; x < p->width; x++) { |
|---|
| 918 | + unsigned int offset; |
|---|
| 919 | + u32 val = y << 16 | x; |
|---|
| 920 | + |
|---|
| 921 | + if (*t == I915_GGTT_VIEW_ROTATED) |
|---|
| 922 | + offset = (x * p->height + y) * PAGE_SIZE; |
|---|
| 923 | + else |
|---|
| 924 | + offset = (y * p->width + x) * PAGE_SIZE; |
|---|
| 925 | + |
|---|
| 926 | + iowrite32(val, &map[offset / sizeof(*map)]); |
|---|
| 927 | + } |
|---|
| 928 | + } |
|---|
| 929 | + |
|---|
| 930 | + i915_vma_unpin_iomap(vma); |
|---|
| 931 | + |
|---|
| 932 | + vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, PIN_MAPPABLE); |
|---|
| 933 | + if (IS_ERR(vma)) { |
|---|
| 934 | + err = PTR_ERR(vma); |
|---|
| 935 | + goto out; |
|---|
| 936 | + } |
|---|
| 937 | + |
|---|
| 938 | + GEM_BUG_ON(vma->ggtt_view.type != I915_GGTT_VIEW_NORMAL); |
|---|
| 939 | + |
|---|
| 940 | + map = i915_vma_pin_iomap(vma); |
|---|
| 941 | + i915_vma_unpin(vma); |
|---|
| 942 | + if (IS_ERR(map)) { |
|---|
| 943 | + err = PTR_ERR(map); |
|---|
| 944 | + goto out; |
|---|
| 945 | + } |
|---|
| 946 | + |
|---|
| 947 | + for (y = 0 ; y < p->height; y++) { |
|---|
| 948 | + for (x = 0 ; x < p->width; x++) { |
|---|
| 949 | + unsigned int offset, src_idx; |
|---|
| 950 | + u32 exp = y << 16 | x; |
|---|
| 951 | + u32 val; |
|---|
| 952 | + |
|---|
| 953 | + if (*t == I915_GGTT_VIEW_ROTATED) |
|---|
| 954 | + src_idx = rotated_index(&view.rotated, 0, x, y); |
|---|
| 955 | + else |
|---|
| 956 | + src_idx = remapped_index(&view.remapped, 0, x, y); |
|---|
| 957 | + offset = src_idx * PAGE_SIZE; |
|---|
| 958 | + |
|---|
| 959 | + val = ioread32(&map[offset / sizeof(*map)]); |
|---|
| 960 | + if (val != exp) { |
|---|
| 961 | + pr_err("%s VMA write test failed, expected 0x%x, found 0x%x\n", |
|---|
| 962 | + *t == I915_GGTT_VIEW_ROTATED ? "Rotated" : "Remapped", |
|---|
| 963 | + val, exp); |
|---|
| 964 | + i915_vma_unpin_iomap(vma); |
|---|
| 965 | + goto out; |
|---|
| 966 | + } |
|---|
| 967 | + } |
|---|
| 968 | + } |
|---|
| 969 | + i915_vma_unpin_iomap(vma); |
|---|
| 970 | + |
|---|
| 971 | + cond_resched(); |
|---|
| 972 | + } |
|---|
| 973 | + } |
|---|
| 974 | + |
|---|
| 975 | +out: |
|---|
| 976 | + intel_runtime_pm_put(&i915->runtime_pm, wakeref); |
|---|
| 977 | + i915_gem_object_put(obj); |
|---|
| 978 | + |
|---|
| 979 | + return err; |
|---|
| 980 | +} |
|---|
| 981 | + |
|---|
| 982 | +int i915_vma_live_selftests(struct drm_i915_private *i915) |
|---|
| 983 | +{ |
|---|
| 984 | + static const struct i915_subtest tests[] = { |
|---|
| 985 | + SUBTEST(igt_vma_remapped_gtt), |
|---|
| 986 | + }; |
|---|
| 987 | + |
|---|
| 988 | + return i915_subtests(tests, i915); |
|---|
| 989 | +} |
|---|