[PATCH] drm/i915: signal fences from irq handler if complete
Chris Wilson
chris at chris-wilson.co.uk
Tue Jan 17 14:47:53 UTC 2017
If needs must.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
drivers/gpu/drm/i915/i915_drv.h | 12 ++++++++----
drivers/gpu/drm/i915/i915_gem_request.c | 1 +
drivers/gpu/drm/i915/i915_gem_request.h | 2 ++
drivers/gpu/drm/i915/intel_breadcrumbs.c | 10 +---------
drivers/gpu/drm/i915/intel_ringbuffer.h | 24 ++++++++++++++----------
5 files changed, 26 insertions(+), 23 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 15c13c5294da..e996b4d1cd78 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3989,7 +3989,10 @@ static inline bool
__i915_request_irq_complete(const struct drm_i915_gem_request *req)
{
struct intel_engine_cs *engine = req->engine;
- u32 seqno = i915_gem_request_global_seqno(req);
+ u32 seqno;
+
+ if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &req->fence.flags))
+ return true;
/* The request was dequeued before we were awoken. We check after
* inspecting the hw to confirm that this was the same request
@@ -3997,6 +4000,7 @@ __i915_request_irq_complete(const struct drm_i915_gem_request *req)
* the request execution are sufficient to ensure that a check
* after reading the value from hw matches this request.
*/
+ seqno = i915_gem_request_global_seqno(req);
if (!seqno)
return false;
@@ -4018,7 +4022,7 @@ __i915_request_irq_complete(const struct drm_i915_gem_request *req)
* is woken.
*/
if (engine->irq_seqno_barrier &&
- rcu_access_pointer(engine->breadcrumbs.irq_seqno_bh) == current &&
+ engine->breadcrumbs.first_wait->request == req &&
cmpxchg_relaxed(&engine->breadcrumbs.irq_posted, 1, 0)) {
struct task_struct *tsk;
@@ -4043,8 +4047,8 @@ __i915_request_irq_complete(const struct drm_i915_gem_request *req)
* irq_posted == false but we are still running).
*/
rcu_read_lock();
- tsk = rcu_dereference(engine->breadcrumbs.irq_seqno_bh);
- if (tsk && tsk != current)
+ tsk = lockless_dereference(engine->breadcrumbs.first_wait->tsk);
+ if (tsk != current)
/* Note that if the bottom-half is changed as we
* are sending the wake-up, the new bottom-half will
* be woken by whomever made the change. We only have
diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c
index ab91367d7092..bacb875a6ef3 100644
--- a/drivers/gpu/drm/i915/i915_gem_request.c
+++ b/drivers/gpu/drm/i915/i915_gem_request.c
@@ -1063,6 +1063,7 @@ long i915_wait_request(struct drm_i915_gem_request *req,
}
wait.tsk = current;
+ wait.request = req;
restart:
do {
diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h
index 282cf7c6455a..316c86c98b6a 100644
--- a/drivers/gpu/drm/i915/i915_gem_request.h
+++ b/drivers/gpu/drm/i915/i915_gem_request.h
@@ -32,10 +32,12 @@
struct drm_file;
struct drm_i915_gem_object;
+struct drm_i915_gem_request;
struct intel_wait {
struct rb_node node;
struct task_struct *tsk;
+ struct drm_i915_gem_request *request;
u32 seqno;
};
diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c
index 5f09a2de0956..6fbdfe6927af 100644
--- a/drivers/gpu/drm/i915/intel_breadcrumbs.c
+++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c
@@ -251,7 +251,6 @@ static bool __intel_engine_add_wait(struct intel_engine_cs *engine,
}
rb_link_node(&wait->node, parent, p);
rb_insert_color(&wait->node, &b->waiters);
- GEM_BUG_ON(!first && !rcu_access_pointer(b->irq_seqno_bh));
if (completed) {
struct rb_node *next = rb_next(completed);
@@ -261,7 +260,6 @@ static bool __intel_engine_add_wait(struct intel_engine_cs *engine,
GEM_BUG_ON(first);
b->timeout = wait_timeout();
b->first_wait = to_wait(next);
- rcu_assign_pointer(b->irq_seqno_bh, b->first_wait->tsk);
/* As there is a delay between reading the current
* seqno, processing the completed tasks and selecting
* the next waiter, we may have missed the interrupt
@@ -288,7 +286,6 @@ static bool __intel_engine_add_wait(struct intel_engine_cs *engine,
GEM_BUG_ON(rb_first(&b->waiters) != &wait->node);
b->timeout = wait_timeout();
b->first_wait = wait;
- rcu_assign_pointer(b->irq_seqno_bh, wait->tsk);
/* After assigning ourselves as the new bottom-half, we must
* perform a cursory check to prevent a missed interrupt.
* Either we miss the interrupt whilst programming the hardware,
@@ -299,7 +296,6 @@ static bool __intel_engine_add_wait(struct intel_engine_cs *engine,
*/
__intel_breadcrumbs_enable_irq(b);
}
- GEM_BUG_ON(!rcu_access_pointer(b->irq_seqno_bh));
GEM_BUG_ON(!b->first_wait);
GEM_BUG_ON(rb_first(&b->waiters) != &b->first_wait->node);
@@ -347,8 +343,6 @@ static void __intel_engine_remove_wait(struct intel_engine_cs *engine,
const int priority = wakeup_priority(b, wait->tsk);
struct rb_node *next;
- GEM_BUG_ON(rcu_access_pointer(b->irq_seqno_bh) != wait->tsk);
-
/* We are the current bottom-half. Find the next candidate,
* the first waiter in the queue on the remaining oldest
* request. As multiple seqnos may complete in the time it
@@ -391,13 +385,11 @@ static void __intel_engine_remove_wait(struct intel_engine_cs *engine,
*/
b->timeout = wait_timeout();
b->first_wait = to_wait(next);
- rcu_assign_pointer(b->irq_seqno_bh, b->first_wait->tsk);
if (b->first_wait->seqno != wait->seqno)
__intel_breadcrumbs_enable_irq(b);
wake_up_process(b->first_wait->tsk);
} else {
b->first_wait = NULL;
- rcu_assign_pointer(b->irq_seqno_bh, NULL);
__intel_breadcrumbs_disable_irq(b);
}
} else {
@@ -411,7 +403,6 @@ static void __intel_engine_remove_wait(struct intel_engine_cs *engine,
GEM_BUG_ON(b->first_wait == wait);
GEM_BUG_ON(rb_first(&b->waiters) !=
(b->first_wait ? &b->first_wait->node : NULL));
- GEM_BUG_ON(!rcu_access_pointer(b->irq_seqno_bh) ^ RB_EMPTY_ROOT(&b->waiters));
}
void intel_engine_remove_wait(struct intel_engine_cs *engine,
@@ -570,6 +561,7 @@ void intel_engine_enable_signaling(struct drm_i915_gem_request *request)
return;
request->signaling.wait.tsk = b->signaler;
+ request->signaling.wait.request = request;
request->signaling.wait.seqno = seqno;
i915_gem_request_get(request);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 10df8f9cf084..450da3dba9bd 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -229,7 +229,6 @@ struct intel_engine_cs {
* the overhead of waking that client is much preferred.
*/
struct intel_breadcrumbs {
- struct task_struct __rcu *irq_seqno_bh; /* bh for interrupts */
bool irq_posted;
spinlock_t lock; /* protects the lists of requests; irqsafe */
@@ -607,10 +606,10 @@ void intel_engine_cancel_signaling(struct drm_i915_gem_request *request);
static inline bool intel_engine_has_waiter(const struct intel_engine_cs *engine)
{
- return rcu_access_pointer(engine->breadcrumbs.irq_seqno_bh);
+ return READ_ONCE(engine->breadcrumbs.first_wait);
}
-static inline bool intel_engine_wakeup(const struct intel_engine_cs *engine)
+static inline bool intel_engine_wakeup(struct intel_engine_cs *engine)
{
bool wakeup = false;
@@ -622,13 +621,18 @@ static inline bool intel_engine_wakeup(const struct intel_engine_cs *engine)
* is unlikely to be beneficial.
*/
if (intel_engine_has_waiter(engine)) {
- struct task_struct *tsk;
-
- rcu_read_lock();
- tsk = rcu_dereference(engine->breadcrumbs.irq_seqno_bh);
- if (tsk)
- wakeup = wake_up_process(tsk);
- rcu_read_unlock();
+ struct intel_wait *wait;
+
+ spin_lock(&engine->breadcrumbs.lock);
+ wait = engine->breadcrumbs.first_wait;
+ if (wait) {
+ if (i915_seqno_passed(intel_engine_get_seqno(engine),
+ wait->seqno))
+ dma_fence_signal(&wait->request->fence);
+
+ wakeup = wake_up_process(wait->tsk);
+ }
+ spin_unlock(&engine->breadcrumbs.lock);
}
return wakeup;
--
2.11.0
More information about the Intel-gfx-trybot
mailing list