Skip to content

Commit 4178b5a

Browse files
icklejlahtine-intel
authored andcommitted
drm/i915/gt: Prevent timeslicing into unpreemptable requests
We have a I915_REQUEST_NOPREEMPT flag that we set when we must prevent the HW from preempting during the course of this request. We need to honour this flag and protect the HW even if we have a heartbeat request, or other maximum priority barrier, pending. As such, restrict the timeslicing check to avoid preempting into the topmost priority band, leaving the unpreemptable requests in blissful peace running uninterrupted on the HW. v2: Set the I915_PRIORITY_BARRIER to be less than I915_PRIORITY_UNPREEMPTABLE so that we never submit a request (heartbeat or barrier) that can legitimately preempt the current non-premptable request. Fixes: 2a98f4e ("drm/i915: add infrastructure to hold off preemption on a request") Signed-off-by: Chris Wilson <[email protected]> Cc: Tvrtko Ursulin <[email protected]> Reviewed-by: Tvrtko Ursulin <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] (cherry picked from commit b72f02d) Signed-off-by: Joonas Lahtinen <[email protected]>
1 parent 3ffbe35 commit 4178b5a

File tree

3 files changed

+119
-2
lines changed

3 files changed

+119
-2
lines changed

drivers/gpu/drm/i915/gt/intel_lrc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1925,6 +1925,7 @@ need_timeslice(const struct intel_engine_cs *engine,
19251925
if (!list_is_last(&rq->sched.link, &engine->active.requests))
19261926
hint = max(hint, rq_prio(list_next_entry(rq, sched.link)));
19271927

1928+
GEM_BUG_ON(hint >= I915_PRIORITY_UNPREEMPTABLE);
19281929
return hint >= effective_prio(rq);
19291930
}
19301931

drivers/gpu/drm/i915/gt/selftest_lrc.c

Lines changed: 117 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,7 @@ slice_semaphore_queue(struct intel_engine_cs *outer,
823823
}
824824
}
825825

826-
err = release_queue(outer, vma, n, INT_MAX);
826+
err = release_queue(outer, vma, n, I915_PRIORITY_BARRIER);
827827
if (err)
828828
goto out;
829829

@@ -1289,6 +1289,121 @@ static int live_timeslice_queue(void *arg)
12891289
return err;
12901290
}
12911291

1292+
static int live_timeslice_nopreempt(void *arg)
1293+
{
1294+
struct intel_gt *gt = arg;
1295+
struct intel_engine_cs *engine;
1296+
enum intel_engine_id id;
1297+
struct igt_spinner spin;
1298+
int err = 0;
1299+
1300+
/*
1301+
* We should not timeslice into a request that is marked with
1302+
* I915_REQUEST_NOPREEMPT.
1303+
*/
1304+
if (!IS_ACTIVE(CONFIG_DRM_I915_TIMESLICE_DURATION))
1305+
return 0;
1306+
1307+
if (igt_spinner_init(&spin, gt))
1308+
return -ENOMEM;
1309+
1310+
for_each_engine(engine, gt, id) {
1311+
struct intel_context *ce;
1312+
struct i915_request *rq;
1313+
unsigned long timeslice;
1314+
1315+
if (!intel_engine_has_preemption(engine))
1316+
continue;
1317+
1318+
ce = intel_context_create(engine);
1319+
if (IS_ERR(ce)) {
1320+
err = PTR_ERR(ce);
1321+
break;
1322+
}
1323+
1324+
engine_heartbeat_disable(engine);
1325+
timeslice = xchg(&engine->props.timeslice_duration_ms, 1);
1326+
1327+
/* Create an unpreemptible spinner */
1328+
1329+
rq = igt_spinner_create_request(&spin, ce, MI_ARB_CHECK);
1330+
intel_context_put(ce);
1331+
if (IS_ERR(rq)) {
1332+
err = PTR_ERR(rq);
1333+
goto out_heartbeat;
1334+
}
1335+
1336+
i915_request_get(rq);
1337+
i915_request_add(rq);
1338+
1339+
if (!igt_wait_for_spinner(&spin, rq)) {
1340+
i915_request_put(rq);
1341+
err = -ETIME;
1342+
goto out_spin;
1343+
}
1344+
1345+
set_bit(I915_FENCE_FLAG_NOPREEMPT, &rq->fence.flags);
1346+
i915_request_put(rq);
1347+
1348+
/* Followed by a maximum priority barrier (heartbeat) */
1349+
1350+
ce = intel_context_create(engine);
1351+
if (IS_ERR(ce)) {
1352+
err = PTR_ERR(rq);
1353+
goto out_spin;
1354+
}
1355+
1356+
rq = intel_context_create_request(ce);
1357+
intel_context_put(ce);
1358+
if (IS_ERR(rq)) {
1359+
err = PTR_ERR(rq);
1360+
goto out_spin;
1361+
}
1362+
1363+
rq->sched.attr.priority = I915_PRIORITY_BARRIER;
1364+
i915_request_get(rq);
1365+
i915_request_add(rq);
1366+
1367+
/*
1368+
* Wait until the barrier is in ELSP, and we know timeslicing
1369+
* will have been activated.
1370+
*/
1371+
if (wait_for_submit(engine, rq, HZ / 2)) {
1372+
i915_request_put(rq);
1373+
err = -ETIME;
1374+
goto out_spin;
1375+
}
1376+
1377+
/*
1378+
* Since the ELSP[0] request is unpreemptible, it should not
1379+
* allow the maximum priority barrier through. Wait long
1380+
* enough to see if it is timesliced in by mistake.
1381+
*/
1382+
if (i915_request_wait(rq, 0, timeslice_threshold(engine)) >= 0) {
1383+
pr_err("%s: I915_PRIORITY_BARRIER request completed, bypassing no-preempt request\n",
1384+
engine->name);
1385+
err = -EINVAL;
1386+
}
1387+
i915_request_put(rq);
1388+
1389+
out_spin:
1390+
igt_spinner_end(&spin);
1391+
out_heartbeat:
1392+
xchg(&engine->props.timeslice_duration_ms, timeslice);
1393+
engine_heartbeat_enable(engine);
1394+
if (err)
1395+
break;
1396+
1397+
if (igt_flush_test(gt->i915)) {
1398+
err = -EIO;
1399+
break;
1400+
}
1401+
}
1402+
1403+
igt_spinner_fini(&spin);
1404+
return err;
1405+
}
1406+
12921407
static int live_busywait_preempt(void *arg)
12931408
{
12941409
struct intel_gt *gt = arg;
@@ -4296,6 +4411,7 @@ int intel_execlists_live_selftests(struct drm_i915_private *i915)
42964411
SUBTEST(live_timeslice_preempt),
42974412
SUBTEST(live_timeslice_rewind),
42984413
SUBTEST(live_timeslice_queue),
4414+
SUBTEST(live_timeslice_nopreempt),
42994415
SUBTEST(live_busywait_preempt),
43004416
SUBTEST(live_preempt),
43014417
SUBTEST(live_late_preempt),

drivers/gpu/drm/i915/i915_priolist_types.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ enum {
4242
* active request.
4343
*/
4444
#define I915_PRIORITY_UNPREEMPTABLE INT_MAX
45-
#define I915_PRIORITY_BARRIER INT_MAX
45+
#define I915_PRIORITY_BARRIER (I915_PRIORITY_UNPREEMPTABLE - 1)
4646

4747
struct i915_priolist {
4848
struct list_head requests[I915_PRIORITY_COUNT];

0 commit comments

Comments
 (0)