[PATCH 12/12] sync-cleanup-signaler
Chris Wilson
chris at chris-wilson.co.uk
Tue Jan 2 08:38:37 UTC 2018
---
drivers/gpu/drm/i915/i915_gem_request.c | 6 +-
drivers/gpu/drm/i915/intel_breadcrumbs.c | 102 +++++++++++++++----------------
2 files changed, 53 insertions(+), 55 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c
index a24c6a87953c..af2493164686 100644
--- a/drivers/gpu/drm/i915/i915_gem_request.c
+++ b/drivers/gpu/drm/i915/i915_gem_request.c
@@ -441,7 +441,10 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request)
spin_lock_irq(&request->lock);
if (request->waitboost)
atomic_dec(&request->i915->gt_pm.rps.num_waiters);
- dma_fence_signal_locked(&request->fence);
+ if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &request->fence.flags))
+ dma_fence_signal_locked(&request->fence);
+ if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &request->fence.flags))
+ intel_engine_cancel_signaling(request);
spin_unlock_irq(&request->lock);
i915_priotree_fini(request->i915, &request->priotree);
@@ -730,6 +733,7 @@ i915_gem_request_alloc(struct intel_engine_cs *engine,
/* No zalloc, must clear what we need by hand */
req->global_seqno = 0;
+ req->signaling.wait.seqno = 0;
req->file_priv = NULL;
req->batch = NULL;
req->capture_list = NULL;
diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c
index 58c624f982d9..010d8da5121d 100644
--- a/drivers/gpu/drm/i915/intel_breadcrumbs.c
+++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c
@@ -642,6 +642,38 @@ static void signaler_set_rtpriority(void)
sched_setscheduler_nocheck(current, SCHED_FIFO, ¶m);
}
+static void __intel_engine_remove_signal(struct intel_engine_cs *engine,
+ struct drm_i915_gem_request *request)
+{
+ struct intel_breadcrumbs *b = &engine->breadcrumbs;
+
+ lockdep_assert_held(&b->rb_lock);
+
+ /*
+ * Wake up all other completed waiters and select the
+ * next bottom-half for the next user interrupt.
+ */
+ __intel_engine_remove_wait(engine, &request->signaling.wait);
+
+ /*
+ * Find the next oldest signal. Note that as we have
+ * not been holding the lock, another client may
+ * have installed an even older signal than the one
+ * we just completed - so double check we are still
+ * the oldest before picking the next one.
+ */
+ if (request->signaling.wait.seqno) {
+ if (request == rcu_access_pointer(b->first_signal)) {
+ struct rb_node *rb = rb_next(&request->signaling.node);
+ rcu_assign_pointer(b->first_signal,
+ rb ? to_signaler(rb) : NULL);
+ }
+
+ rb_erase(&request->signaling.node, &b->signals);
+ request->signaling.wait.seqno = 0;
+ }
+}
+
static int intel_breadcrumbs_signaler(void *arg)
{
struct intel_engine_cs *engine = arg;
@@ -674,32 +706,11 @@ static int intel_breadcrumbs_signaler(void *arg)
dma_fence_signal(&request->fence);
local_bh_enable(); /* kick start the tasklets */
- spin_lock_irq(&b->rb_lock);
-
- /* Wake up all other completed waiters and select the
- * next bottom-half for the next user interrupt.
- */
- __intel_engine_remove_wait(engine,
- &request->signaling.wait);
-
- /* Find the next oldest signal. Note that as we have
- * not been holding the lock, another client may
- * have installed an even older signal than the one
- * we just completed - so double check we are still
- * the oldest before picking the next one.
- */
- if (request == rcu_access_pointer(b->first_signal)) {
- struct rb_node *rb =
- rb_next(&request->signaling.node);
- rcu_assign_pointer(b->first_signal,
- rb ? to_signaler(rb) : NULL);
+ if (request->signaling.wait.seqno) {
+ spin_lock_irq(&b->rb_lock);
+ __intel_engine_remove_signal(engine, request);
+ spin_unlock_irq(&b->rb_lock);
}
- rb_erase(&request->signaling.node, &b->signals);
- RB_CLEAR_NODE(&request->signaling.node);
-
- spin_unlock_irq(&b->rb_lock);
-
- i915_gem_request_put(request);
/* If the engine is saturated we may be continually
* processing completed requests. This angers the
@@ -710,19 +721,17 @@ static int intel_breadcrumbs_signaler(void *arg)
*/
do_schedule = need_resched();
}
+ i915_gem_request_put(request);
if (unlikely(do_schedule)) {
if (kthread_should_park())
kthread_parkme();
- if (unlikely(kthread_should_stop())) {
- i915_gem_request_put(request);
+ if (unlikely(kthread_should_stop()))
break;
- }
schedule();
}
- i915_gem_request_put(request);
} while (1);
__set_current_state(TASK_RUNNING);
@@ -751,12 +760,12 @@ void intel_engine_enable_signaling(struct drm_i915_gem_request *request,
if (!seqno)
return;
+ spin_lock(&b->rb_lock);
+
+ GEM_BUG_ON(request->signaling.wait.seqno);
request->signaling.wait.tsk = b->signaler;
request->signaling.wait.request = request;
request->signaling.wait.seqno = seqno;
- i915_gem_request_get(request);
-
- spin_lock(&b->rb_lock);
/* First add ourselves into the list of waiters, but register our
* bottom-half as the signaller thread. As per usual, only the oldest
@@ -795,7 +804,7 @@ void intel_engine_enable_signaling(struct drm_i915_gem_request *request,
rcu_assign_pointer(b->first_signal, request);
} else {
__intel_engine_remove_wait(engine, &request->signaling.wait);
- i915_gem_request_put(request);
+ request->signaling.wait.seqno = 0;
wakeup = false;
}
@@ -807,32 +816,17 @@ void intel_engine_enable_signaling(struct drm_i915_gem_request *request,
void intel_engine_cancel_signaling(struct drm_i915_gem_request *request)
{
- struct intel_engine_cs *engine = request->engine;
- struct intel_breadcrumbs *b = &engine->breadcrumbs;
-
GEM_BUG_ON(!irqs_disabled());
lockdep_assert_held(&request->lock);
- GEM_BUG_ON(!request->signaling.wait.seqno);
- spin_lock(&b->rb_lock);
+ if (request->signaling.wait.seqno) {
+ struct intel_engine_cs *engine = request->engine;
+ struct intel_breadcrumbs *b = &engine->breadcrumbs;
- if (!RB_EMPTY_NODE(&request->signaling.node)) {
- if (request == rcu_access_pointer(b->first_signal)) {
- struct rb_node *rb =
- rb_next(&request->signaling.node);
- rcu_assign_pointer(b->first_signal,
- rb ? to_signaler(rb) : NULL);
- }
- rb_erase(&request->signaling.node, &b->signals);
- RB_CLEAR_NODE(&request->signaling.node);
- i915_gem_request_put(request);
+ spin_lock(&b->rb_lock);
+ __intel_engine_remove_signal(engine, request);
+ spin_unlock(&b->rb_lock);
}
-
- __intel_engine_remove_wait(engine, &request->signaling.wait);
-
- spin_unlock(&b->rb_lock);
-
- request->signaling.wait.seqno = 0;
}
int intel_engine_init_breadcrumbs(struct intel_engine_cs *engine)
--
2.15.1
More information about the Intel-gfx-trybot
mailing list