Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/i915: Pin timeline map after first timeline pin, v4.

We're starting to require the reservation lock for pinning,
so wait until we have that.

Update the selftests to handle this correctly, and ensure pin is
called in live_hwsp_rollover_user() and mock_hwsp_freelist().

Changes since v1:
- Fix NULL + XX arithmatic, use casts. (kbuild)
Changes since v2:
- Clear entire cacheline when pinning.
Changes since v3:
- CACHELINE_BYTES -> TIMELINE_SEQNO_BYTES. (jekstrand)

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Reported-by: kernel test robot <lkp@intel.com>
Reviewed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/20210323155059.628690-3-maarten.lankhorst@linux.intel.com

authored by

Maarten Lankhorst and committed by
Daniel Vetter
2c8ab333 12ca695d

+83 -44
+28 -12
drivers/gpu/drm/i915/gt/intel_timeline.c
··· 53 53 return 0; 54 54 } 55 55 56 + I915_SELFTEST_EXPORT int 57 + intel_timeline_pin_map(struct intel_timeline *timeline) 58 + { 59 + struct drm_i915_gem_object *obj = timeline->hwsp_ggtt->obj; 60 + u32 ofs = offset_in_page(timeline->hwsp_offset); 61 + void *vaddr; 62 + 63 + vaddr = i915_gem_object_pin_map(obj, I915_MAP_WB); 64 + if (IS_ERR(vaddr)) 65 + return PTR_ERR(vaddr); 66 + 67 + timeline->hwsp_map = vaddr; 68 + timeline->hwsp_seqno = memset(vaddr + ofs, 0, TIMELINE_SEQNO_BYTES); 69 + clflush(vaddr + ofs); 70 + 71 + return 0; 72 + } 73 + 56 74 static int intel_timeline_init(struct intel_timeline *timeline, 57 75 struct intel_gt *gt, 58 76 struct i915_vma *hwsp, 59 77 unsigned int offset) 60 78 { 61 - void *vaddr; 62 - u32 *seqno; 63 - 64 79 kref_init(&timeline->kref); 65 80 atomic_set(&timeline->pin_count, 0); 66 81 ··· 92 77 timeline->hwsp_ggtt = hwsp; 93 78 } 94 79 95 - vaddr = i915_gem_object_pin_map(hwsp->obj, I915_MAP_WB); 96 - if (IS_ERR(vaddr)) 97 - return PTR_ERR(vaddr); 98 - 99 - timeline->hwsp_map = vaddr; 100 - seqno = vaddr + timeline->hwsp_offset; 101 - WRITE_ONCE(*seqno, 0); 102 - timeline->hwsp_seqno = seqno; 80 + timeline->hwsp_map = NULL; 81 + timeline->hwsp_seqno = (void *)(long)timeline->hwsp_offset; 103 82 104 83 GEM_BUG_ON(timeline->hwsp_offset >= hwsp->size); 105 84 ··· 123 114 struct intel_timeline *timeline = 124 115 container_of(rcu, struct intel_timeline, rcu); 125 116 126 - i915_gem_object_unpin_map(timeline->hwsp_ggtt->obj); 117 + if (timeline->hwsp_map) 118 + i915_gem_object_unpin_map(timeline->hwsp_ggtt->obj); 127 119 128 120 i915_vma_put(timeline->hwsp_ggtt); 129 121 i915_active_fini(&timeline->active); ··· 183 173 184 174 if (atomic_add_unless(&tl->pin_count, 1, 0)) 185 175 return 0; 176 + 177 + if (!tl->hwsp_map) { 178 + err = intel_timeline_pin_map(tl); 179 + if (err) 180 + return err; 181 + } 186 182 187 183 err = i915_ggtt_pin(tl->hwsp_ggtt, ww, 0, PIN_HIGH); 188 184 if (err)
+2
drivers/gpu/drm/i915/gt/intel_timeline.h
··· 117 117 return list_is_last_rcu(&rq->link, &tl->requests); 118 118 } 119 119 120 + I915_SELFTEST_DECLARE(int intel_timeline_pin_map(struct intel_timeline *tl)); 121 + 120 122 #endif
+20 -2
drivers/gpu/drm/i915/gt/mock_engine.c
··· 32 32 #include "mock_engine.h" 33 33 #include "selftests/mock_request.h" 34 34 35 - static void mock_timeline_pin(struct intel_timeline *tl) 35 + static int mock_timeline_pin(struct intel_timeline *tl) 36 36 { 37 + int err; 38 + 39 + if (WARN_ON(!i915_gem_object_trylock(tl->hwsp_ggtt->obj))) 40 + return -EBUSY; 41 + 42 + err = intel_timeline_pin_map(tl); 43 + i915_gem_object_unlock(tl->hwsp_ggtt->obj); 44 + if (err) 45 + return err; 46 + 37 47 atomic_inc(&tl->pin_count); 48 + return 0; 38 49 } 39 50 40 51 static void mock_timeline_unpin(struct intel_timeline *tl) ··· 163 152 164 153 static int mock_context_alloc(struct intel_context *ce) 165 154 { 155 + int err; 156 + 166 157 ce->ring = mock_ring(ce->engine); 167 158 if (!ce->ring) 168 159 return -ENOMEM; ··· 175 162 return PTR_ERR(ce->timeline); 176 163 } 177 164 178 - mock_timeline_pin(ce->timeline); 165 + err = mock_timeline_pin(ce->timeline); 166 + if (err) { 167 + intel_timeline_put(ce->timeline); 168 + ce->timeline = NULL; 169 + return err; 170 + } 179 171 180 172 return 0; 181 173 }
+31 -30
drivers/gpu/drm/i915/gt/selftest_timeline.c
··· 60 60 tl = xchg(&state->history[idx], tl); 61 61 if (tl) { 62 62 radix_tree_delete(&state->cachelines, hwsp_cacheline(tl)); 63 + intel_timeline_unpin(tl); 63 64 intel_timeline_put(tl); 64 65 } 65 66 } ··· 80 79 if (IS_ERR(tl)) 81 80 return PTR_ERR(tl); 82 81 82 + err = intel_timeline_pin(tl, NULL); 83 + if (err) { 84 + intel_timeline_put(tl); 85 + return err; 86 + } 87 + 83 88 cacheline = hwsp_cacheline(tl); 84 89 err = radix_tree_insert(&state->cachelines, cacheline, tl); 85 90 if (err) { ··· 93 86 pr_err("HWSP cacheline %lu already used; duplicate allocation!\n", 94 87 cacheline); 95 88 } 89 + intel_timeline_unpin(tl); 96 90 intel_timeline_put(tl); 97 91 return err; 98 92 } ··· 461 453 } 462 454 463 455 static struct i915_request * 464 - tl_write(struct intel_timeline *tl, struct intel_engine_cs *engine, u32 value) 456 + checked_tl_write(struct intel_timeline *tl, struct intel_engine_cs *engine, u32 value) 465 457 { 466 458 struct i915_request *rq; 467 459 int err; ··· 470 462 if (err) { 471 463 rq = ERR_PTR(err); 472 464 goto out; 465 + } 466 + 467 + if (READ_ONCE(*tl->hwsp_seqno) != tl->seqno) { 468 + pr_err("Timeline created with incorrect breadcrumb, found %x, expected %x\n", 469 + *tl->hwsp_seqno, tl->seqno); 470 + intel_timeline_unpin(tl); 471 + return ERR_PTR(-EINVAL); 473 472 } 474 473 475 474 rq = intel_engine_create_kernel_request(engine); ··· 498 483 if (IS_ERR(rq)) 499 484 pr_err("Failed to write to timeline!\n"); 500 485 return rq; 501 - } 502 - 503 - static struct intel_timeline * 504 - checked_intel_timeline_create(struct intel_gt *gt) 505 - { 506 - struct intel_timeline *tl; 507 - 508 - tl = intel_timeline_create(gt); 509 - if (IS_ERR(tl)) 510 - return tl; 511 - 512 - if (READ_ONCE(*tl->hwsp_seqno) != tl->seqno) { 513 - pr_err("Timeline created with incorrect breadcrumb, found %x, expected %x\n", 514 - *tl->hwsp_seqno, tl->seqno); 515 - intel_timeline_put(tl); 516 - return ERR_PTR(-EINVAL); 517 - } 518 - 519 - return tl; 520 486 } 521 487 522 488 static int live_hwsp_engine(void *arg) ··· 532 536 struct intel_timeline *tl; 533 537 struct i915_request *rq; 534 538 535 - tl = checked_intel_timeline_create(gt); 539 + tl = intel_timeline_create(gt); 536 540 if (IS_ERR(tl)) { 537 541 err = PTR_ERR(tl); 538 542 break; 539 543 } 540 544 541 - rq = tl_write(tl, engine, count); 545 + rq = checked_tl_write(tl, engine, count); 542 546 if (IS_ERR(rq)) { 543 547 intel_timeline_put(tl); 544 548 err = PTR_ERR(rq); ··· 605 609 if (!intel_engine_can_store_dword(engine)) 606 610 continue; 607 611 608 - tl = checked_intel_timeline_create(gt); 612 + tl = intel_timeline_create(gt); 609 613 if (IS_ERR(tl)) { 610 614 err = PTR_ERR(tl); 611 615 goto out; 612 616 } 613 617 614 618 intel_engine_pm_get(engine); 615 - rq = tl_write(tl, engine, count); 619 + rq = checked_tl_write(tl, engine, count); 616 620 intel_engine_pm_put(engine); 617 621 if (IS_ERR(rq)) { 618 622 intel_timeline_put(tl); ··· 1255 1259 if (!tl->has_initial_breadcrumb) 1256 1260 goto out; 1257 1261 1262 + err = intel_context_pin(ce); 1263 + if (err) 1264 + goto out; 1265 + 1258 1266 tl->seqno = -4u; 1259 1267 WRITE_ONCE(*(u32 *)tl->hwsp_seqno, tl->seqno); 1260 1268 ··· 1268 1268 this = intel_context_create_request(ce); 1269 1269 if (IS_ERR(this)) { 1270 1270 err = PTR_ERR(this); 1271 - goto out; 1271 + goto out_unpin; 1272 1272 } 1273 1273 1274 1274 pr_debug("%s: create fence.seqnp:%d\n", ··· 1287 1287 if (i915_request_wait(rq[2], 0, HZ / 5) < 0) { 1288 1288 pr_err("Wait for timeline wrap timed out!\n"); 1289 1289 err = -EIO; 1290 - goto out; 1290 + goto out_unpin; 1291 1291 } 1292 1292 1293 1293 for (i = 0; i < ARRAY_SIZE(rq); i++) { 1294 1294 if (!i915_request_completed(rq[i])) { 1295 1295 pr_err("Pre-wrap request not completed!\n"); 1296 1296 err = -EINVAL; 1297 - goto out; 1297 + goto out_unpin; 1298 1298 } 1299 1299 } 1300 - 1300 + out_unpin: 1301 + intel_context_unpin(ce); 1301 1302 out: 1302 1303 for (i = 0; i < ARRAY_SIZE(rq); i++) 1303 1304 i915_request_put(rq[i]); ··· 1340 1339 struct intel_timeline *tl; 1341 1340 struct i915_request *rq; 1342 1341 1343 - tl = checked_intel_timeline_create(gt); 1342 + tl = intel_timeline_create(gt); 1344 1343 if (IS_ERR(tl)) { 1345 1344 err = PTR_ERR(tl); 1346 1345 break; 1347 1346 } 1348 1347 1349 - rq = tl_write(tl, engine, count); 1348 + rq = checked_tl_write(tl, engine, count); 1350 1349 if (IS_ERR(rq)) { 1351 1350 intel_timeline_put(tl); 1352 1351 err = PTR_ERR(rq);
+2
drivers/gpu/drm/i915/i915_selftest.h
··· 107 107 108 108 #define I915_SELFTEST_DECLARE(x) x 109 109 #define I915_SELFTEST_ONLY(x) unlikely(x) 110 + #define I915_SELFTEST_EXPORT 110 111 111 112 #else /* !IS_ENABLED(CONFIG_DRM_I915_SELFTEST) */ 112 113 ··· 117 116 118 117 #define I915_SELFTEST_DECLARE(x) 119 118 #define I915_SELFTEST_ONLY(x) 0 119 + #define I915_SELFTEST_EXPORT static 120 120 121 121 #endif 122 122