Skip to content

Commit 65fcb80

Browse files
committed
drm/i915: Move timeline from GTT to ring
In the future, we want to move a request between engines. To achieve this, we first realise that we have two timelines in effect here. The first runs through the GTT is required for ordering vma access, which is tracked currently by engine. The second is implied by sequential execution of commands inside the ringbuffer. This timeline is one that maps to userspace's expectations when submitting requests (i.e. given the same context, batch A is executed before batch B). As the rings's timelines map to userspace and the GTT timeline an implementation detail, move the timeline from the GTT into the ring itself (per-context in logical-ring-contexts/execlists, or a global per-engine timeline for the shared ringbuffers in legacy submission. The two timelines are still assumed to be equivalent at the moment (no migrating requests between engines yet) and so we can simply move from one to the other without adding extra ordering. v2: Reinforce that one isn't allowed to mix the engine execution timeline with the client timeline from userspace (on the ring). 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]
1 parent 81cf8b7 commit 65fcb80

17 files changed

+115
-41
lines changed

drivers/gpu/drm/i915/i915_drv.h

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2059,7 +2059,8 @@ struct drm_i915_private {
20592059
void (*resume)(struct drm_i915_private *);
20602060
void (*cleanup_engine)(struct intel_engine_cs *engine);
20612061

2062-
struct i915_gem_timeline global_timeline;
2062+
struct i915_gem_timeline execution_timeline;
2063+
struct i915_gem_timeline legacy_timeline;
20632064
struct list_head timelines;
20642065

20652066
struct list_head active_rings;
@@ -3235,16 +3236,6 @@ i915_gem_context_lookup(struct drm_i915_file_private *file_priv, u32 id)
32353236
return ctx;
32363237
}
32373238

3238-
static inline struct intel_timeline *
3239-
i915_gem_context_lookup_timeline(struct i915_gem_context *ctx,
3240-
struct intel_engine_cs *engine)
3241-
{
3242-
struct i915_address_space *vm;
3243-
3244-
vm = ctx->ppgtt ? &ctx->ppgtt->base : &ctx->i915->ggtt.base;
3245-
return &vm->timeline.engine[engine->id];
3246-
}
3247-
32483239
int i915_perf_open_ioctl(struct drm_device *dev, void *data,
32493240
struct drm_file *file);
32503241
int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,

drivers/gpu/drm/i915/i915_gem.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3110,10 +3110,10 @@ static void engine_skip_context(struct i915_request *request)
31103110
{
31113111
struct intel_engine_cs *engine = request->engine;
31123112
struct i915_gem_context *hung_ctx = request->ctx;
3113-
struct intel_timeline *timeline;
3113+
struct intel_timeline *timeline = request->timeline;
31143114
unsigned long flags;
31153115

3116-
timeline = i915_gem_context_lookup_timeline(hung_ctx, engine);
3116+
GEM_BUG_ON(timeline == engine->timeline);
31173117

31183118
spin_lock_irqsave(&engine->timeline->lock, flags);
31193119
spin_lock(&timeline->lock);
@@ -3782,7 +3782,7 @@ int i915_gem_wait_for_idle(struct drm_i915_private *i915, unsigned int flags)
37823782

37833783
ret = wait_for_engines(i915);
37843784
} else {
3785-
ret = wait_for_timeline(&i915->gt.global_timeline, flags);
3785+
ret = wait_for_timeline(&i915->gt.execution_timeline, flags);
37863786
}
37873787

37883788
return ret;
@@ -5652,7 +5652,8 @@ void i915_gem_cleanup_early(struct drm_i915_private *dev_priv)
56525652
WARN_ON(dev_priv->mm.object_count);
56535653

56545654
mutex_lock(&dev_priv->drm.struct_mutex);
5655-
i915_gem_timeline_fini(&dev_priv->gt.global_timeline);
5655+
i915_gem_timeline_fini(&dev_priv->gt.legacy_timeline);
5656+
i915_gem_timeline_fini(&dev_priv->gt.execution_timeline);
56565657
WARN_ON(!list_empty(&dev_priv->gt.timelines));
56575658
mutex_unlock(&dev_priv->drm.struct_mutex);
56585659

drivers/gpu/drm/i915/i915_gem_context.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ static void i915_gem_context_free(struct i915_gem_context *ctx)
122122
lockdep_assert_held(&ctx->i915->drm.struct_mutex);
123123
GEM_BUG_ON(!i915_gem_context_is_closed(ctx));
124124

125+
i915_gem_timeline_free(ctx->timeline);
125126
i915_ppgtt_put(ctx->ppgtt);
126127

127128
for (n = 0; n < ARRAY_SIZE(ctx->__engine); n++) {
@@ -376,6 +377,18 @@ i915_gem_create_context(struct drm_i915_private *dev_priv,
376377
ctx->desc_template = default_desc_template(dev_priv, ppgtt);
377378
}
378379

380+
if (HAS_EXECLISTS(dev_priv)) {
381+
struct i915_gem_timeline *timeline;
382+
383+
timeline = i915_gem_timeline_create(dev_priv, ctx->name);
384+
if (IS_ERR(timeline)) {
385+
__destroy_hw_context(ctx, file_priv);
386+
return ERR_CAST(timeline);
387+
}
388+
389+
ctx->timeline = timeline;
390+
}
391+
379392
trace_i915_context_create(ctx);
380393

381394
return ctx;
@@ -584,7 +597,7 @@ static bool engine_has_idle_kernel_context(struct intel_engine_cs *engine)
584597
list_for_each_entry(timeline, &engine->i915->gt.timelines, link) {
585598
struct intel_timeline *tl;
586599

587-
if (timeline == &engine->i915->gt.global_timeline)
600+
if (timeline == &engine->i915->gt.execution_timeline)
588601
continue;
589602

590603
tl = &timeline->engine[engine->id];

drivers/gpu/drm/i915/i915_gem_context.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ struct i915_gem_context {
5858
/** file_priv: owning file descriptor */
5959
struct drm_i915_file_private *file_priv;
6060

61+
struct i915_gem_timeline *timeline;
62+
6163
/**
6264
* @ppgtt: unique address space (GTT)
6365
*

drivers/gpu/drm/i915/i915_gem_gtt.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2111,8 +2111,6 @@ static void i915_address_space_init(struct i915_address_space *vm,
21112111
struct drm_i915_private *dev_priv,
21122112
const char *name)
21132113
{
2114-
i915_gem_timeline_init(dev_priv, &vm->timeline, name);
2115-
21162114
drm_mm_init(&vm->mm, 0, vm->total);
21172115
vm->mm.head_node.color = I915_COLOR_UNEVICTABLE;
21182116

@@ -2129,7 +2127,6 @@ static void i915_address_space_fini(struct i915_address_space *vm)
21292127
if (pagevec_count(&vm->free_pages))
21302128
vm_free_pages_release(vm, true);
21312129

2132-
i915_gem_timeline_fini(&vm->timeline);
21332130
drm_mm_takedown(&vm->mm);
21342131
list_del(&vm->global_link);
21352132
}

drivers/gpu/drm/i915/i915_gem_gtt.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,6 @@ struct i915_pml4 {
257257

258258
struct i915_address_space {
259259
struct drm_mm mm;
260-
struct i915_gem_timeline timeline;
261260
struct drm_i915_private *i915;
262261
struct device *dma;
263262
/* Every address space belongs to a struct file - except for the global

drivers/gpu/drm/i915/i915_gem_timeline.c

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,28 @@ int i915_gem_timeline_init(struct drm_i915_private *i915,
9595

9696
int i915_gem_timeline_init__global(struct drm_i915_private *i915)
9797
{
98-
static struct lock_class_key class;
98+
static struct lock_class_key class1, class2;
99+
int err;
100+
101+
err = __i915_gem_timeline_init(i915,
102+
&i915->gt.execution_timeline,
103+
"[execution]", &class1,
104+
"i915_execution_timeline");
105+
if (err)
106+
return err;
107+
108+
err = __i915_gem_timeline_init(i915,
109+
&i915->gt.legacy_timeline,
110+
"[global]", &class2,
111+
"i915_global_timeline");
112+
if (err)
113+
goto err_exec_timeline;
114+
115+
return 0;
99116

100-
return __i915_gem_timeline_init(i915,
101-
&i915->gt.global_timeline,
102-
"[execution]",
103-
&class, "&global_timeline->lock");
117+
err_exec_timeline:
118+
i915_gem_timeline_fini(&i915->gt.execution_timeline);
119+
return err;
104120
}
105121

106122
/**
@@ -148,6 +164,34 @@ void i915_gem_timeline_fini(struct i915_gem_timeline *timeline)
148164
kfree(timeline->name);
149165
}
150166

167+
struct i915_gem_timeline *
168+
i915_gem_timeline_create(struct drm_i915_private *i915, const char *name)
169+
{
170+
struct i915_gem_timeline *timeline;
171+
int err;
172+
173+
timeline = kzalloc(sizeof(*timeline), GFP_KERNEL);
174+
if (!timeline)
175+
return ERR_PTR(-ENOMEM);
176+
177+
err = i915_gem_timeline_init(i915, timeline, name);
178+
if (err) {
179+
kfree(timeline);
180+
return ERR_PTR(err);
181+
}
182+
183+
return timeline;
184+
}
185+
186+
void i915_gem_timeline_free(struct i915_gem_timeline *timeline)
187+
{
188+
if (!timeline)
189+
return;
190+
191+
i915_gem_timeline_fini(timeline);
192+
kfree(timeline);
193+
}
194+
151195
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
152196
#include "selftests/mock_timeline.c"
153197
#include "selftests/i915_gem_timeline.c"

drivers/gpu/drm/i915/i915_gem_timeline.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ int i915_gem_timeline_init__global(struct drm_i915_private *i915);
9090
void i915_gem_timelines_park(struct drm_i915_private *i915);
9191
void i915_gem_timeline_fini(struct i915_gem_timeline *tl);
9292

93+
struct i915_gem_timeline *
94+
i915_gem_timeline_create(struct drm_i915_private *i915, const char *name);
95+
void i915_gem_timeline_free(struct i915_gem_timeline *timeline);
96+
9397
static inline int __intel_timeline_sync_set(struct intel_timeline *tl,
9498
u64 context, u32 seqno)
9599
{

drivers/gpu/drm/i915/i915_request.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,12 @@ i915_request_alloc(struct intel_engine_cs *engine, struct i915_gem_context *ctx)
758758
}
759759
}
760760

761-
rq->timeline = i915_gem_context_lookup_timeline(ctx, engine);
761+
INIT_LIST_HEAD(&rq->active_list);
762+
rq->i915 = i915;
763+
rq->engine = engine;
764+
rq->ctx = ctx;
765+
rq->ring = ring;
766+
rq->timeline = ring->timeline;
762767
GEM_BUG_ON(rq->timeline == engine->timeline);
763768

764769
spin_lock_init(&rq->lock);
@@ -774,12 +779,6 @@ i915_request_alloc(struct intel_engine_cs *engine, struct i915_gem_context *ctx)
774779

775780
i915_sched_node_init(&rq->sched);
776781

777-
INIT_LIST_HEAD(&rq->active_list);
778-
rq->i915 = i915;
779-
rq->engine = engine;
780-
rq->ctx = ctx;
781-
rq->ring = ring;
782-
783782
/* No zalloc, must clear what we need by hand */
784783
rq->global_seqno = 0;
785784
rq->signaling.wait.seqno = 0;

drivers/gpu/drm/i915/intel_engine_cs.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,8 @@ void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno)
453453

454454
static void intel_engine_init_timeline(struct intel_engine_cs *engine)
455455
{
456-
engine->timeline = &engine->i915->gt.global_timeline.engine[engine->id];
456+
engine->timeline =
457+
&engine->i915->gt.execution_timeline.engine[engine->id];
457458
}
458459

459460
static void intel_engine_init_batch_pool(struct intel_engine_cs *engine)

drivers/gpu/drm/i915/intel_lrc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2624,7 +2624,7 @@ static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
26242624
goto error_deref_obj;
26252625
}
26262626

2627-
ring = intel_engine_create_ring(engine, ctx->ring_size);
2627+
ring = intel_engine_create_ring(engine, ctx->timeline, ctx->ring_size);
26282628
if (IS_ERR(ring)) {
26292629
ret = PTR_ERR(ring);
26302630
goto error_deref_obj;

drivers/gpu/drm/i915/intel_ringbuffer.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,20 +1117,24 @@ intel_ring_create_vma(struct drm_i915_private *dev_priv, int size)
11171117
}
11181118

11191119
struct intel_ring *
1120-
intel_engine_create_ring(struct intel_engine_cs *engine, int size)
1120+
intel_engine_create_ring(struct intel_engine_cs *engine,
1121+
struct i915_gem_timeline *timeline,
1122+
int size)
11211123
{
11221124
struct intel_ring *ring;
11231125
struct i915_vma *vma;
11241126

11251127
GEM_BUG_ON(!is_power_of_2(size));
11261128
GEM_BUG_ON(RING_CTL_SIZE(size) & ~RING_NR_PAGES);
1129+
GEM_BUG_ON(&timeline->engine[engine->id] == engine->timeline);
11271130
lockdep_assert_held(&engine->i915->drm.struct_mutex);
11281131

11291132
ring = kzalloc(sizeof(*ring), GFP_KERNEL);
11301133
if (!ring)
11311134
return ERR_PTR(-ENOMEM);
11321135

11331136
INIT_LIST_HEAD(&ring->request_list);
1137+
ring->timeline = &timeline->engine[engine->id];
11341138

11351139
ring->size = size;
11361140
/* Workaround an erratum on the i830 which causes a hang if
@@ -1327,7 +1331,9 @@ static int intel_init_ring_buffer(struct intel_engine_cs *engine)
13271331
if (err)
13281332
goto err;
13291333

1330-
ring = intel_engine_create_ring(engine, 32 * PAGE_SIZE);
1334+
ring = intel_engine_create_ring(engine,
1335+
&engine->i915->gt.legacy_timeline,
1336+
32 * PAGE_SIZE);
13311337
if (IS_ERR(ring)) {
13321338
err = PTR_ERR(ring);
13331339
goto err;

drivers/gpu/drm/i915/intel_ringbuffer.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ struct intel_ring {
129129
struct i915_vma *vma;
130130
void *vaddr;
131131

132+
struct intel_timeline *timeline;
132133
struct list_head request_list;
133134
struct list_head active_link;
134135

@@ -768,7 +769,9 @@ intel_write_status_page(struct intel_engine_cs *engine, int reg, u32 value)
768769
#define CNL_HWS_CSB_WRITE_INDEX 0x2f
769770

770771
struct intel_ring *
771-
intel_engine_create_ring(struct intel_engine_cs *engine, int size);
772+
intel_engine_create_ring(struct intel_engine_cs *engine,
773+
struct i915_gem_timeline *timeline,
774+
int size);
772775
int intel_ring_pin(struct intel_ring *ring,
773776
struct drm_i915_private *i915,
774777
unsigned int offset_bias);

drivers/gpu/drm/i915/selftests/i915_gem_context.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,18 @@ static int igt_ctx_exec(void *arg)
355355

356356
if (first_shared_gtt) {
357357
ctx = __create_hw_context(i915, file->driver_priv);
358+
if (!IS_ERR(ctx) && HAS_EXECLISTS(i915)) {
359+
struct i915_gem_timeline *timeline;
360+
361+
timeline = i915_gem_timeline_create(i915, ctx->name);
362+
if (IS_ERR(timeline)) {
363+
__destroy_hw_context(ctx, file->driver_priv);
364+
ctx = ERR_CAST(timeline);
365+
} else {
366+
ctx->timeline = timeline;
367+
}
368+
}
369+
358370
first_shared_gtt = false;
359371
} else {
360372
ctx = i915_gem_create_context(i915, file->driver_priv);

drivers/gpu/drm/i915/selftests/mock_engine.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ static struct intel_ring *mock_ring(struct intel_engine_cs *engine)
140140
if (!ring)
141141
return NULL;
142142

143+
ring->timeline = &engine->i915->gt.legacy_timeline.engine[engine->id];
144+
143145
ring->size = sz;
144146
ring->effective_size = sz;
145147
ring->vaddr = (void *)(ring + 1);
@@ -180,8 +182,7 @@ struct intel_engine_cs *mock_engine(struct drm_i915_private *i915,
180182
engine->base.emit_breadcrumb = mock_emit_breadcrumb;
181183
engine->base.submit_request = mock_submit_request;
182184

183-
engine->base.timeline =
184-
&i915->gt.global_timeline.engine[engine->base.id];
185+
intel_engine_init_timeline(&engine->base);
185186

186187
intel_engine_init_breadcrumbs(&engine->base);
187188
engine->base.breadcrumbs.mock = true; /* prevent touching HW for irqs */

drivers/gpu/drm/i915/selftests/mock_gem_device.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@ static void mock_device_release(struct drm_device *dev)
7373

7474
mutex_lock(&i915->drm.struct_mutex);
7575
mock_fini_ggtt(i915);
76-
i915_gem_timeline_fini(&i915->gt.global_timeline);
76+
i915_gem_timeline_fini(&i915->gt.legacy_timeline);
77+
i915_gem_timeline_fini(&i915->gt.execution_timeline);
78+
WARN_ON(!list_empty(&i915->gt.timelines));
7779
mutex_unlock(&i915->drm.struct_mutex);
7880

7981
destroy_workqueue(i915->wq);

drivers/gpu/drm/i915/selftests/mock_gtt.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ mock_ppgtt(struct drm_i915_private *i915,
7676

7777
INIT_LIST_HEAD(&ppgtt->base.global_link);
7878
drm_mm_init(&ppgtt->base.mm, 0, ppgtt->base.total);
79-
i915_gem_timeline_init(i915, &ppgtt->base.timeline, name);
8079

8180
ppgtt->base.clear_range = nop_clear_range;
8281
ppgtt->base.insert_page = mock_insert_page;

0 commit comments

Comments
 (0)