diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2016-10-28 08:58:58 -0400 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2016-10-28 15:53:57 -0400 |
commit | 80b204bce8f27b52cd65839e0e6144b4452ae3de (patch) | |
tree | 081a0a9a239818514c977fe00e469e9a3d0adf42 /drivers/gpu/drm | |
parent | f2d13290e3275df34c0cd625fbc665965af08c67 (diff) |
drm/i915: Enable multiple timelines
With the infrastructure converted over to tracking multiple timelines in
the GEM API whilst preserving the efficiency of using a single execution
timeline internally, we can now assign a separate timeline to every
context with full-ppgtt.
v2: Add a comment to indicate the xfer between timelines upon submission.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20161028125858.23563-35-chris@chris-wilson.co.uk
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_context.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_evict.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_gtt.c | 19 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_gtt.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_request.c | 61 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_timeline.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_timeline.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.h | 5 |
10 files changed, 77 insertions, 51 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index eacb144af29e..42a499681966 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -3549,6 +3549,16 @@ static inline void i915_gem_context_put(struct i915_gem_context *ctx) | |||
3549 | kref_put(&ctx->ref, i915_gem_context_free); | 3549 | kref_put(&ctx->ref, i915_gem_context_free); |
3550 | } | 3550 | } |
3551 | 3551 | ||
3552 | static inline struct intel_timeline * | ||
3553 | i915_gem_context_lookup_timeline(struct i915_gem_context *ctx, | ||
3554 | struct intel_engine_cs *engine) | ||
3555 | { | ||
3556 | struct i915_address_space *vm; | ||
3557 | |||
3558 | vm = ctx->ppgtt ? &ctx->ppgtt->base : &ctx->i915->ggtt.base; | ||
3559 | return &vm->timeline.engine[engine->id]; | ||
3560 | } | ||
3561 | |||
3552 | static inline bool i915_gem_context_is_default(const struct i915_gem_context *c) | 3562 | static inline bool i915_gem_context_is_default(const struct i915_gem_context *c) |
3553 | { | 3563 | { |
3554 | return c->user_handle == DEFAULT_CONTEXT_HANDLE; | 3564 | return c->user_handle == DEFAULT_CONTEXT_HANDLE; |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 8a5d20715e5f..1e5d2bf777e4 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -2564,12 +2564,9 @@ i915_gem_find_active_request(struct intel_engine_cs *engine) | |||
2564 | * not need an engine->irq_seqno_barrier() before the seqno reads. | 2564 | * not need an engine->irq_seqno_barrier() before the seqno reads. |
2565 | */ | 2565 | */ |
2566 | list_for_each_entry(request, &engine->timeline->requests, link) { | 2566 | list_for_each_entry(request, &engine->timeline->requests, link) { |
2567 | if (i915_gem_request_completed(request)) | 2567 | if (__i915_gem_request_completed(request)) |
2568 | continue; | 2568 | continue; |
2569 | 2569 | ||
2570 | if (!i915_sw_fence_done(&request->submit)) | ||
2571 | break; | ||
2572 | |||
2573 | return request; | 2570 | return request; |
2574 | } | 2571 | } |
2575 | 2572 | ||
@@ -2597,6 +2594,7 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine) | |||
2597 | { | 2594 | { |
2598 | struct drm_i915_gem_request *request; | 2595 | struct drm_i915_gem_request *request; |
2599 | struct i915_gem_context *incomplete_ctx; | 2596 | struct i915_gem_context *incomplete_ctx; |
2597 | struct intel_timeline *timeline; | ||
2600 | bool ring_hung; | 2598 | bool ring_hung; |
2601 | 2599 | ||
2602 | if (engine->irq_seqno_barrier) | 2600 | if (engine->irq_seqno_barrier) |
@@ -2635,6 +2633,10 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine) | |||
2635 | list_for_each_entry_continue(request, &engine->timeline->requests, link) | 2633 | list_for_each_entry_continue(request, &engine->timeline->requests, link) |
2636 | if (request->ctx == incomplete_ctx) | 2634 | if (request->ctx == incomplete_ctx) |
2637 | reset_request(request); | 2635 | reset_request(request); |
2636 | |||
2637 | timeline = i915_gem_context_lookup_timeline(incomplete_ctx, engine); | ||
2638 | list_for_each_entry(request, &timeline->requests, link) | ||
2639 | reset_request(request); | ||
2638 | } | 2640 | } |
2639 | 2641 | ||
2640 | void i915_gem_reset(struct drm_i915_private *dev_priv) | 2642 | void i915_gem_reset(struct drm_i915_private *dev_priv) |
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index d3118db244c4..461aece6c5bd 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c | |||
@@ -365,9 +365,9 @@ i915_gem_create_context(struct drm_device *dev, | |||
365 | return ctx; | 365 | return ctx; |
366 | 366 | ||
367 | if (USES_FULL_PPGTT(dev)) { | 367 | if (USES_FULL_PPGTT(dev)) { |
368 | struct i915_hw_ppgtt *ppgtt = | 368 | struct i915_hw_ppgtt *ppgtt; |
369 | i915_ppgtt_create(to_i915(dev), file_priv); | ||
370 | 369 | ||
370 | ppgtt = i915_ppgtt_create(to_i915(dev), file_priv, ctx->name); | ||
371 | if (IS_ERR(ppgtt)) { | 371 | if (IS_ERR(ppgtt)) { |
372 | DRM_DEBUG_DRIVER("PPGTT setup failed (%ld)\n", | 372 | DRM_DEBUG_DRIVER("PPGTT setup failed (%ld)\n", |
373 | PTR_ERR(ppgtt)); | 373 | PTR_ERR(ppgtt)); |
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index 79b964152cd9..bd08814b015c 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c | |||
@@ -33,14 +33,17 @@ | |||
33 | #include "intel_drv.h" | 33 | #include "intel_drv.h" |
34 | #include "i915_trace.h" | 34 | #include "i915_trace.h" |
35 | 35 | ||
36 | static bool | 36 | static bool ggtt_is_idle(struct drm_i915_private *dev_priv) |
37 | gpu_is_idle(struct drm_i915_private *dev_priv) | ||
38 | { | 37 | { |
38 | struct i915_ggtt *ggtt = &dev_priv->ggtt; | ||
39 | struct intel_engine_cs *engine; | 39 | struct intel_engine_cs *engine; |
40 | enum intel_engine_id id; | 40 | enum intel_engine_id id; |
41 | 41 | ||
42 | for_each_engine(engine, dev_priv, id) { | 42 | for_each_engine(engine, dev_priv, id) { |
43 | if (intel_engine_is_active(engine)) | 43 | struct intel_timeline *tl; |
44 | |||
45 | tl = &ggtt->base.timeline.engine[engine->id]; | ||
46 | if (i915_gem_active_isset(&tl->last_request)) | ||
44 | return false; | 47 | return false; |
45 | } | 48 | } |
46 | 49 | ||
@@ -154,7 +157,7 @@ search_again: | |||
154 | if (!i915_is_ggtt(vm) || flags & PIN_NONBLOCK) | 157 | if (!i915_is_ggtt(vm) || flags & PIN_NONBLOCK) |
155 | return -ENOSPC; | 158 | return -ENOSPC; |
156 | 159 | ||
157 | if (gpu_is_idle(dev_priv)) { | 160 | if (ggtt_is_idle(dev_priv)) { |
158 | /* If we still have pending pageflip completions, drop | 161 | /* If we still have pending pageflip completions, drop |
159 | * back to userspace to give our workqueues time to | 162 | * back to userspace to give our workqueues time to |
160 | * acquire our locks and unpin the old scanouts. | 163 | * acquire our locks and unpin the old scanouts. |
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 1b1a459e2b68..e7afad585929 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c | |||
@@ -2185,8 +2185,10 @@ static int __hw_ppgtt_init(struct i915_hw_ppgtt *ppgtt, | |||
2185 | } | 2185 | } |
2186 | 2186 | ||
2187 | static void i915_address_space_init(struct i915_address_space *vm, | 2187 | static void i915_address_space_init(struct i915_address_space *vm, |
2188 | struct drm_i915_private *dev_priv) | 2188 | struct drm_i915_private *dev_priv, |
2189 | const char *name) | ||
2189 | { | 2190 | { |
2191 | i915_gem_timeline_init(dev_priv, &vm->timeline, name); | ||
2190 | drm_mm_init(&vm->mm, vm->start, vm->total); | 2192 | drm_mm_init(&vm->mm, vm->start, vm->total); |
2191 | INIT_LIST_HEAD(&vm->active_list); | 2193 | INIT_LIST_HEAD(&vm->active_list); |
2192 | INIT_LIST_HEAD(&vm->inactive_list); | 2194 | INIT_LIST_HEAD(&vm->inactive_list); |
@@ -2215,14 +2217,15 @@ static void gtt_write_workarounds(struct drm_device *dev) | |||
2215 | 2217 | ||
2216 | static int i915_ppgtt_init(struct i915_hw_ppgtt *ppgtt, | 2218 | static int i915_ppgtt_init(struct i915_hw_ppgtt *ppgtt, |
2217 | struct drm_i915_private *dev_priv, | 2219 | struct drm_i915_private *dev_priv, |
2218 | struct drm_i915_file_private *file_priv) | 2220 | struct drm_i915_file_private *file_priv, |
2221 | const char *name) | ||
2219 | { | 2222 | { |
2220 | int ret; | 2223 | int ret; |
2221 | 2224 | ||
2222 | ret = __hw_ppgtt_init(ppgtt, dev_priv); | 2225 | ret = __hw_ppgtt_init(ppgtt, dev_priv); |
2223 | if (ret == 0) { | 2226 | if (ret == 0) { |
2224 | kref_init(&ppgtt->ref); | 2227 | kref_init(&ppgtt->ref); |
2225 | i915_address_space_init(&ppgtt->base, dev_priv); | 2228 | i915_address_space_init(&ppgtt->base, dev_priv, name); |
2226 | ppgtt->base.file = file_priv; | 2229 | ppgtt->base.file = file_priv; |
2227 | } | 2230 | } |
2228 | 2231 | ||
@@ -2258,7 +2261,8 @@ int i915_ppgtt_init_hw(struct drm_device *dev) | |||
2258 | 2261 | ||
2259 | struct i915_hw_ppgtt * | 2262 | struct i915_hw_ppgtt * |
2260 | i915_ppgtt_create(struct drm_i915_private *dev_priv, | 2263 | i915_ppgtt_create(struct drm_i915_private *dev_priv, |
2261 | struct drm_i915_file_private *fpriv) | 2264 | struct drm_i915_file_private *fpriv, |
2265 | const char *name) | ||
2262 | { | 2266 | { |
2263 | struct i915_hw_ppgtt *ppgtt; | 2267 | struct i915_hw_ppgtt *ppgtt; |
2264 | int ret; | 2268 | int ret; |
@@ -2267,7 +2271,7 @@ i915_ppgtt_create(struct drm_i915_private *dev_priv, | |||
2267 | if (!ppgtt) | 2271 | if (!ppgtt) |
2268 | return ERR_PTR(-ENOMEM); | 2272 | return ERR_PTR(-ENOMEM); |
2269 | 2273 | ||
2270 | ret = i915_ppgtt_init(ppgtt, dev_priv, fpriv); | 2274 | ret = i915_ppgtt_init(ppgtt, dev_priv, fpriv, name); |
2271 | if (ret) { | 2275 | if (ret) { |
2272 | kfree(ppgtt); | 2276 | kfree(ppgtt); |
2273 | return ERR_PTR(ret); | 2277 | return ERR_PTR(ret); |
@@ -2290,6 +2294,7 @@ void i915_ppgtt_release(struct kref *kref) | |||
2290 | WARN_ON(!list_empty(&ppgtt->base.inactive_list)); | 2294 | WARN_ON(!list_empty(&ppgtt->base.inactive_list)); |
2291 | WARN_ON(!list_empty(&ppgtt->base.unbound_list)); | 2295 | WARN_ON(!list_empty(&ppgtt->base.unbound_list)); |
2292 | 2296 | ||
2297 | i915_gem_timeline_fini(&ppgtt->base.timeline); | ||
2293 | list_del(&ppgtt->base.global_link); | 2298 | list_del(&ppgtt->base.global_link); |
2294 | drm_mm_takedown(&ppgtt->base.mm); | 2299 | drm_mm_takedown(&ppgtt->base.mm); |
2295 | 2300 | ||
@@ -3232,11 +3237,13 @@ int i915_ggtt_init_hw(struct drm_i915_private *dev_priv) | |||
3232 | /* Subtract the guard page before address space initialization to | 3237 | /* Subtract the guard page before address space initialization to |
3233 | * shrink the range used by drm_mm. | 3238 | * shrink the range used by drm_mm. |
3234 | */ | 3239 | */ |
3240 | mutex_lock(&dev_priv->drm.struct_mutex); | ||
3235 | ggtt->base.total -= PAGE_SIZE; | 3241 | ggtt->base.total -= PAGE_SIZE; |
3236 | i915_address_space_init(&ggtt->base, dev_priv); | 3242 | i915_address_space_init(&ggtt->base, dev_priv, "[global]"); |
3237 | ggtt->base.total += PAGE_SIZE; | 3243 | ggtt->base.total += PAGE_SIZE; |
3238 | if (!HAS_LLC(dev_priv)) | 3244 | if (!HAS_LLC(dev_priv)) |
3239 | ggtt->base.mm.color_adjust = i915_gtt_color_adjust; | 3245 | ggtt->base.mm.color_adjust = i915_gtt_color_adjust; |
3246 | mutex_unlock(&dev_priv->drm.struct_mutex); | ||
3240 | 3247 | ||
3241 | if (!io_mapping_init_wc(&dev_priv->ggtt.mappable, | 3248 | if (!io_mapping_init_wc(&dev_priv->ggtt.mappable, |
3242 | dev_priv->ggtt.mappable_base, | 3249 | dev_priv->ggtt.mappable_base, |
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 9f0327e5176a..518e75b64290 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h | |||
@@ -342,6 +342,7 @@ struct i915_pml4 { | |||
342 | 342 | ||
343 | struct i915_address_space { | 343 | struct i915_address_space { |
344 | struct drm_mm mm; | 344 | struct drm_mm mm; |
345 | struct i915_gem_timeline timeline; | ||
345 | struct drm_device *dev; | 346 | struct drm_device *dev; |
346 | /* Every address space belongs to a struct file - except for the global | 347 | /* Every address space belongs to a struct file - except for the global |
347 | * GTT that is owned by the driver (and so @file is set to NULL). In | 348 | * GTT that is owned by the driver (and so @file is set to NULL). In |
@@ -613,7 +614,8 @@ void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv); | |||
613 | int i915_ppgtt_init_hw(struct drm_device *dev); | 614 | int i915_ppgtt_init_hw(struct drm_device *dev); |
614 | void i915_ppgtt_release(struct kref *kref); | 615 | void i915_ppgtt_release(struct kref *kref); |
615 | struct i915_hw_ppgtt *i915_ppgtt_create(struct drm_i915_private *dev_priv, | 616 | struct i915_hw_ppgtt *i915_ppgtt_create(struct drm_i915_private *dev_priv, |
616 | struct drm_i915_file_private *fpriv); | 617 | struct drm_i915_file_private *fpriv, |
618 | const char *name); | ||
617 | static inline void i915_ppgtt_get(struct i915_hw_ppgtt *ppgtt) | 619 | static inline void i915_ppgtt_get(struct i915_hw_ppgtt *ppgtt) |
618 | { | 620 | { |
619 | if (ppgtt) | 621 | if (ppgtt) |
diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 7499e3b205c6..79b0046d9a57 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c | |||
@@ -34,12 +34,6 @@ static const char *i915_fence_get_driver_name(struct dma_fence *fence) | |||
34 | 34 | ||
35 | static const char *i915_fence_get_timeline_name(struct dma_fence *fence) | 35 | static const char *i915_fence_get_timeline_name(struct dma_fence *fence) |
36 | { | 36 | { |
37 | /* Timelines are bound by eviction to a VM. However, since | ||
38 | * we only have a global seqno at the moment, we only have | ||
39 | * a single timeline. Note that each timeline will have | ||
40 | * multiple execution contexts (fence contexts) as we allow | ||
41 | * engines within a single timeline to execute in parallel. | ||
42 | */ | ||
43 | return to_request(fence)->timeline->common->name; | 37 | return to_request(fence)->timeline->common->name; |
44 | } | 38 | } |
45 | 39 | ||
@@ -64,18 +58,6 @@ static signed long i915_fence_wait(struct dma_fence *fence, | |||
64 | return i915_wait_request(to_request(fence), interruptible, timeout); | 58 | return i915_wait_request(to_request(fence), interruptible, timeout); |
65 | } | 59 | } |
66 | 60 | ||
67 | static void i915_fence_value_str(struct dma_fence *fence, char *str, int size) | ||
68 | { | ||
69 | snprintf(str, size, "%u", fence->seqno); | ||
70 | } | ||
71 | |||
72 | static void i915_fence_timeline_value_str(struct dma_fence *fence, char *str, | ||
73 | int size) | ||
74 | { | ||
75 | snprintf(str, size, "%u", | ||
76 | intel_engine_get_seqno(to_request(fence)->engine)); | ||
77 | } | ||
78 | |||
79 | static void i915_fence_release(struct dma_fence *fence) | 61 | static void i915_fence_release(struct dma_fence *fence) |
80 | { | 62 | { |
81 | struct drm_i915_gem_request *req = to_request(fence); | 63 | struct drm_i915_gem_request *req = to_request(fence); |
@@ -90,8 +72,6 @@ const struct dma_fence_ops i915_fence_ops = { | |||
90 | .signaled = i915_fence_signaled, | 72 | .signaled = i915_fence_signaled, |
91 | .wait = i915_fence_wait, | 73 | .wait = i915_fence_wait, |
92 | .release = i915_fence_release, | 74 | .release = i915_fence_release, |
93 | .fence_value_str = i915_fence_value_str, | ||
94 | .timeline_value_str = i915_fence_timeline_value_str, | ||
95 | }; | 75 | }; |
96 | 76 | ||
97 | int i915_gem_request_add_to_client(struct drm_i915_gem_request *req, | 77 | int i915_gem_request_add_to_client(struct drm_i915_gem_request *req, |
@@ -147,7 +127,10 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request) | |||
147 | GEM_BUG_ON(!i915_gem_request_completed(request)); | 127 | GEM_BUG_ON(!i915_gem_request_completed(request)); |
148 | 128 | ||
149 | trace_i915_gem_request_retire(request); | 129 | trace_i915_gem_request_retire(request); |
130 | |||
131 | spin_lock_irq(&request->engine->timeline->lock); | ||
150 | list_del_init(&request->link); | 132 | list_del_init(&request->link); |
133 | spin_unlock_irq(&request->engine->timeline->lock); | ||
151 | 134 | ||
152 | /* We know the GPU must have read the request to have | 135 | /* We know the GPU must have read the request to have |
153 | * sent us the seqno + interrupt, so use the position | 136 | * sent us the seqno + interrupt, so use the position |
@@ -313,6 +296,12 @@ static int reserve_global_seqno(struct drm_i915_private *i915) | |||
313 | return 0; | 296 | return 0; |
314 | } | 297 | } |
315 | 298 | ||
299 | static u32 __timeline_get_seqno(struct i915_gem_timeline *tl) | ||
300 | { | ||
301 | /* next_seqno only incremented under a mutex */ | ||
302 | return ++tl->next_seqno.counter; | ||
303 | } | ||
304 | |||
316 | static u32 timeline_get_seqno(struct i915_gem_timeline *tl) | 305 | static u32 timeline_get_seqno(struct i915_gem_timeline *tl) |
317 | { | 306 | { |
318 | return atomic_inc_return(&tl->next_seqno); | 307 | return atomic_inc_return(&tl->next_seqno); |
@@ -325,16 +314,20 @@ submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) | |||
325 | container_of(fence, typeof(*request), submit); | 314 | container_of(fence, typeof(*request), submit); |
326 | struct intel_engine_cs *engine = request->engine; | 315 | struct intel_engine_cs *engine = request->engine; |
327 | struct intel_timeline *timeline; | 316 | struct intel_timeline *timeline; |
317 | unsigned long flags; | ||
328 | u32 seqno; | 318 | u32 seqno; |
329 | 319 | ||
330 | if (state != FENCE_COMPLETE) | 320 | if (state != FENCE_COMPLETE) |
331 | return NOTIFY_DONE; | 321 | return NOTIFY_DONE; |
332 | 322 | ||
333 | /* Will be called from irq-context when using foreign DMA fences */ | 323 | /* Transfer from per-context onto the global per-engine timeline */ |
324 | timeline = engine->timeline; | ||
325 | GEM_BUG_ON(timeline == request->timeline); | ||
334 | 326 | ||
335 | timeline = request->timeline; | 327 | /* Will be called from irq-context when using foreign DMA fences */ |
328 | spin_lock_irqsave(&timeline->lock, flags); | ||
336 | 329 | ||
337 | seqno = request->fence.seqno; | 330 | seqno = timeline_get_seqno(timeline->common); |
338 | GEM_BUG_ON(!seqno); | 331 | GEM_BUG_ON(!seqno); |
339 | GEM_BUG_ON(i915_seqno_passed(intel_engine_get_seqno(engine), seqno)); | 332 | GEM_BUG_ON(i915_seqno_passed(intel_engine_get_seqno(engine), seqno)); |
340 | 333 | ||
@@ -354,6 +347,12 @@ submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) | |||
354 | request->ring->vaddr + request->postfix); | 347 | request->ring->vaddr + request->postfix); |
355 | engine->submit_request(request); | 348 | engine->submit_request(request); |
356 | 349 | ||
350 | spin_lock_nested(&request->timeline->lock, SINGLE_DEPTH_NESTING); | ||
351 | list_move_tail(&request->link, &timeline->requests); | ||
352 | spin_unlock(&request->timeline->lock); | ||
353 | |||
354 | spin_unlock_irqrestore(&timeline->lock, flags); | ||
355 | |||
357 | return NOTIFY_DONE; | 356 | return NOTIFY_DONE; |
358 | } | 357 | } |
359 | 358 | ||
@@ -394,7 +393,7 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, | |||
394 | /* Move the oldest request to the slab-cache (if not in use!) */ | 393 | /* Move the oldest request to the slab-cache (if not in use!) */ |
395 | req = list_first_entry_or_null(&engine->timeline->requests, | 394 | req = list_first_entry_or_null(&engine->timeline->requests, |
396 | typeof(*req), link); | 395 | typeof(*req), link); |
397 | if (req && i915_gem_request_completed(req)) | 396 | if (req && __i915_gem_request_completed(req)) |
398 | i915_gem_request_retire(req); | 397 | i915_gem_request_retire(req); |
399 | 398 | ||
400 | /* Beware: Dragons be flying overhead. | 399 | /* Beware: Dragons be flying overhead. |
@@ -431,14 +430,15 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, | |||
431 | goto err_unreserve; | 430 | goto err_unreserve; |
432 | } | 431 | } |
433 | 432 | ||
434 | req->timeline = engine->timeline; | 433 | req->timeline = i915_gem_context_lookup_timeline(ctx, engine); |
434 | GEM_BUG_ON(req->timeline == engine->timeline); | ||
435 | 435 | ||
436 | spin_lock_init(&req->lock); | 436 | spin_lock_init(&req->lock); |
437 | dma_fence_init(&req->fence, | 437 | dma_fence_init(&req->fence, |
438 | &i915_fence_ops, | 438 | &i915_fence_ops, |
439 | &req->lock, | 439 | &req->lock, |
440 | req->timeline->fence_context, | 440 | req->timeline->fence_context, |
441 | timeline_get_seqno(req->timeline->common)); | 441 | __timeline_get_seqno(req->timeline->common)); |
442 | 442 | ||
443 | i915_sw_fence_init(&req->submit, submit_notify); | 443 | i915_sw_fence_init(&req->submit, submit_notify); |
444 | 444 | ||
@@ -722,9 +722,14 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) | |||
722 | i915_sw_fence_await_sw_fence(&request->submit, &prev->submit, | 722 | i915_sw_fence_await_sw_fence(&request->submit, &prev->submit, |
723 | &request->submitq); | 723 | &request->submitq); |
724 | 724 | ||
725 | spin_lock_irq(&timeline->lock); | ||
725 | list_add_tail(&request->link, &timeline->requests); | 726 | list_add_tail(&request->link, &timeline->requests); |
727 | spin_unlock_irq(&timeline->lock); | ||
728 | |||
729 | GEM_BUG_ON(i915_seqno_passed(timeline->last_submitted_seqno, | ||
730 | request->fence.seqno)); | ||
726 | 731 | ||
727 | timeline->last_pending_seqno = request->fence.seqno; | 732 | timeline->last_submitted_seqno = request->fence.seqno; |
728 | i915_gem_active_set(&timeline->last_request, request); | 733 | i915_gem_active_set(&timeline->last_request, request); |
729 | 734 | ||
730 | list_add_tail(&request->ring_link, &ring->request_list); | 735 | list_add_tail(&request->ring_link, &ring->request_list); |
@@ -991,7 +996,7 @@ static void engine_retire_requests(struct intel_engine_cs *engine) | |||
991 | 996 | ||
992 | list_for_each_entry_safe(request, next, | 997 | list_for_each_entry_safe(request, next, |
993 | &engine->timeline->requests, link) { | 998 | &engine->timeline->requests, link) { |
994 | if (!i915_gem_request_completed(request)) | 999 | if (!__i915_gem_request_completed(request)) |
995 | return; | 1000 | return; |
996 | 1001 | ||
997 | i915_gem_request_retire(request); | 1002 | i915_gem_request_retire(request); |
diff --git a/drivers/gpu/drm/i915/i915_gem_timeline.c b/drivers/gpu/drm/i915/i915_gem_timeline.c index a1bd03d10852..fc8f13a79f8f 100644 --- a/drivers/gpu/drm/i915/i915_gem_timeline.c +++ b/drivers/gpu/drm/i915/i915_gem_timeline.c | |||
@@ -48,6 +48,7 @@ int i915_gem_timeline_init(struct drm_i915_private *i915, | |||
48 | tl->fence_context = fences++; | 48 | tl->fence_context = fences++; |
49 | tl->common = timeline; | 49 | tl->common = timeline; |
50 | 50 | ||
51 | spin_lock_init(&tl->lock); | ||
51 | init_request_active(&tl->last_request, NULL); | 52 | init_request_active(&tl->last_request, NULL); |
52 | INIT_LIST_HEAD(&tl->requests); | 53 | INIT_LIST_HEAD(&tl->requests); |
53 | } | 54 | } |
diff --git a/drivers/gpu/drm/i915/i915_gem_timeline.h b/drivers/gpu/drm/i915/i915_gem_timeline.h index 18e603980dd9..f2bf7b1d49a1 100644 --- a/drivers/gpu/drm/i915/i915_gem_timeline.h +++ b/drivers/gpu/drm/i915/i915_gem_timeline.h | |||
@@ -34,7 +34,8 @@ struct i915_gem_timeline; | |||
34 | struct intel_timeline { | 34 | struct intel_timeline { |
35 | u64 fence_context; | 35 | u64 fence_context; |
36 | u32 last_submitted_seqno; | 36 | u32 last_submitted_seqno; |
37 | u32 last_pending_seqno; | 37 | |
38 | spinlock_t lock; | ||
38 | 39 | ||
39 | /** | 40 | /** |
40 | * List of breadcrumbs associated with GPU requests currently | 41 | * List of breadcrumbs associated with GPU requests currently |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index d16c74ae8f54..43f61aa24ed7 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h | |||
@@ -569,9 +569,4 @@ void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine); | |||
569 | unsigned int intel_kick_waiters(struct drm_i915_private *i915); | 569 | unsigned int intel_kick_waiters(struct drm_i915_private *i915); |
570 | unsigned int intel_kick_signalers(struct drm_i915_private *i915); | 570 | unsigned int intel_kick_signalers(struct drm_i915_private *i915); |
571 | 571 | ||
572 | static inline bool intel_engine_is_active(struct intel_engine_cs *engine) | ||
573 | { | ||
574 | return i915_gem_active_isset(&engine->timeline->last_request); | ||
575 | } | ||
576 | |||
577 | #endif /* _INTEL_RINGBUFFER_H_ */ | 572 | #endif /* _INTEL_RINGBUFFER_H_ */ |