Commit 54400257 authored by Chris Wilson's avatar Chris Wilson

drm/i915/gt: Remove direct invocation of breadcrumb signaling

Only signal the breadcrumbs from inside the irq_work, simplifying our
interface and calling conventions. The micro-optimisation here is that
by always using the irq_work interface, we know we are always inside an
irq-off critical section for the breadcrumb signaling and can ellide
save/restore of the irq flags.
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarTvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191217095642.3124521-7-chris@chris-wilson.co.uk
parent df6a4205
...@@ -130,16 +130,15 @@ __dma_fence_signal__notify(struct dma_fence *fence, ...@@ -130,16 +130,15 @@ __dma_fence_signal__notify(struct dma_fence *fence,
} }
} }
void intel_engine_breadcrumbs_irq(struct intel_engine_cs *engine) static void signal_irq_work(struct irq_work *work)
{ {
struct intel_breadcrumbs *b = &engine->breadcrumbs; struct intel_breadcrumbs *b = container_of(work, typeof(*b), irq_work);
const ktime_t timestamp = ktime_get(); const ktime_t timestamp = ktime_get();
struct intel_context *ce, *cn; struct intel_context *ce, *cn;
struct list_head *pos, *next; struct list_head *pos, *next;
unsigned long flags;
LIST_HEAD(signal); LIST_HEAD(signal);
spin_lock_irqsave(&b->irq_lock, flags); spin_lock(&b->irq_lock);
if (b->irq_armed && list_empty(&b->signalers)) if (b->irq_armed && list_empty(&b->signalers))
__intel_breadcrumbs_disarm_irq(b); __intel_breadcrumbs_disarm_irq(b);
...@@ -185,31 +184,23 @@ void intel_engine_breadcrumbs_irq(struct intel_engine_cs *engine) ...@@ -185,31 +184,23 @@ void intel_engine_breadcrumbs_irq(struct intel_engine_cs *engine)
} }
} }
spin_unlock_irqrestore(&b->irq_lock, flags); spin_unlock(&b->irq_lock);
list_for_each_safe(pos, next, &signal) { list_for_each_safe(pos, next, &signal) {
struct i915_request *rq = struct i915_request *rq =
list_entry(pos, typeof(*rq), signal_link); list_entry(pos, typeof(*rq), signal_link);
struct list_head cb_list; struct list_head cb_list;
spin_lock_irqsave(&rq->lock, flags); spin_lock(&rq->lock);
list_replace(&rq->fence.cb_list, &cb_list); list_replace(&rq->fence.cb_list, &cb_list);
__dma_fence_signal__timestamp(&rq->fence, timestamp); __dma_fence_signal__timestamp(&rq->fence, timestamp);
__dma_fence_signal__notify(&rq->fence, &cb_list); __dma_fence_signal__notify(&rq->fence, &cb_list);
spin_unlock_irqrestore(&rq->lock, flags); spin_unlock(&rq->lock);
i915_request_put(rq); i915_request_put(rq);
} }
} }
static void signal_irq_work(struct irq_work *work)
{
struct intel_engine_cs *engine =
container_of(work, typeof(*engine), breadcrumbs.irq_work);
intel_engine_breadcrumbs_irq(engine);
}
static bool __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) static bool __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b)
{ {
struct intel_engine_cs *engine = struct intel_engine_cs *engine =
...@@ -290,9 +281,9 @@ bool i915_request_enable_breadcrumb(struct i915_request *rq) ...@@ -290,9 +281,9 @@ bool i915_request_enable_breadcrumb(struct i915_request *rq)
/* /*
* We keep the seqno in retirement order, so we can break * We keep the seqno in retirement order, so we can break
* inside intel_engine_breadcrumbs_irq as soon as we've passed * inside intel_engine_signal_breadcrumbs as soon as we've
* the last completed request (or seen a request that hasn't * passed the last completed request (or seen a request that
* event started). We could iterate the timeline->requests list, * hasn't event started). We could walk the timeline->requests,
* but keeping a separate signalers_list has the advantage of * but keeping a separate signalers_list has the advantage of
* hopefully being much smaller than the full list and so * hopefully being much smaller than the full list and so
* provides faster iteration and detection when there are no * provides faster iteration and detection when there are no
......
...@@ -213,13 +213,11 @@ void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine); ...@@ -213,13 +213,11 @@ void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine);
void intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine); void intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine);
static inline void static inline void
intel_engine_queue_breadcrumbs(struct intel_engine_cs *engine) intel_engine_signal_breadcrumbs(struct intel_engine_cs *engine)
{ {
irq_work_queue(&engine->breadcrumbs.irq_work); irq_work_queue(&engine->breadcrumbs.irq_work);
} }
void intel_engine_breadcrumbs_irq(struct intel_engine_cs *engine);
void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine); void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine);
void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine); void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine);
......
...@@ -28,7 +28,7 @@ cs_irq_handler(struct intel_engine_cs *engine, u32 iir) ...@@ -28,7 +28,7 @@ cs_irq_handler(struct intel_engine_cs *engine, u32 iir)
tasklet = true; tasklet = true;
if (iir & GT_RENDER_USER_INTERRUPT) { if (iir & GT_RENDER_USER_INTERRUPT) {
intel_engine_queue_breadcrumbs(engine); intel_engine_signal_breadcrumbs(engine);
tasklet |= intel_engine_needs_breadcrumb_tasklet(engine); tasklet |= intel_engine_needs_breadcrumb_tasklet(engine);
} }
...@@ -245,9 +245,9 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt) ...@@ -245,9 +245,9 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
void gen5_gt_irq_handler(struct intel_gt *gt, u32 gt_iir) void gen5_gt_irq_handler(struct intel_gt *gt, u32 gt_iir)
{ {
if (gt_iir & GT_RENDER_USER_INTERRUPT) if (gt_iir & GT_RENDER_USER_INTERRUPT)
intel_engine_breadcrumbs_irq(gt->engine_class[RENDER_CLASS][0]); intel_engine_signal_breadcrumbs(gt->engine_class[RENDER_CLASS][0]);
if (gt_iir & ILK_BSD_USER_INTERRUPT) if (gt_iir & ILK_BSD_USER_INTERRUPT)
intel_engine_breadcrumbs_irq(gt->engine_class[VIDEO_DECODE_CLASS][0]); intel_engine_signal_breadcrumbs(gt->engine_class[VIDEO_DECODE_CLASS][0]);
} }
static void gen7_parity_error_irq_handler(struct intel_gt *gt, u32 iir) static void gen7_parity_error_irq_handler(struct intel_gt *gt, u32 iir)
...@@ -271,11 +271,11 @@ static void gen7_parity_error_irq_handler(struct intel_gt *gt, u32 iir) ...@@ -271,11 +271,11 @@ static void gen7_parity_error_irq_handler(struct intel_gt *gt, u32 iir)
void gen6_gt_irq_handler(struct intel_gt *gt, u32 gt_iir) void gen6_gt_irq_handler(struct intel_gt *gt, u32 gt_iir)
{ {
if (gt_iir & GT_RENDER_USER_INTERRUPT) if (gt_iir & GT_RENDER_USER_INTERRUPT)
intel_engine_breadcrumbs_irq(gt->engine_class[RENDER_CLASS][0]); intel_engine_signal_breadcrumbs(gt->engine_class[RENDER_CLASS][0]);
if (gt_iir & GT_BSD_USER_INTERRUPT) if (gt_iir & GT_BSD_USER_INTERRUPT)
intel_engine_breadcrumbs_irq(gt->engine_class[VIDEO_DECODE_CLASS][0]); intel_engine_signal_breadcrumbs(gt->engine_class[VIDEO_DECODE_CLASS][0]);
if (gt_iir & GT_BLT_USER_INTERRUPT) if (gt_iir & GT_BLT_USER_INTERRUPT)
intel_engine_breadcrumbs_irq(gt->engine_class[COPY_ENGINE_CLASS][0]); intel_engine_signal_breadcrumbs(gt->engine_class[COPY_ENGINE_CLASS][0]);
if (gt_iir & (GT_BLT_CS_ERROR_INTERRUPT | if (gt_iir & (GT_BLT_CS_ERROR_INTERRUPT |
GT_BSD_CS_ERROR_INTERRUPT | GT_BSD_CS_ERROR_INTERRUPT |
......
...@@ -1483,7 +1483,7 @@ static void virtual_xfer_breadcrumbs(struct virtual_engine *ve, ...@@ -1483,7 +1483,7 @@ static void virtual_xfer_breadcrumbs(struct virtual_engine *ve,
if (!list_empty(&ve->context.signal_link)) { if (!list_empty(&ve->context.signal_link)) {
list_move_tail(&ve->context.signal_link, list_move_tail(&ve->context.signal_link,
&engine->breadcrumbs.signalers); &engine->breadcrumbs.signalers);
intel_engine_queue_breadcrumbs(engine); intel_engine_signal_breadcrumbs(engine);
} }
spin_unlock(&old->breadcrumbs.irq_lock); spin_unlock(&old->breadcrumbs.irq_lock);
} }
......
...@@ -742,7 +742,7 @@ static void reset_finish_engine(struct intel_engine_cs *engine) ...@@ -742,7 +742,7 @@ static void reset_finish_engine(struct intel_engine_cs *engine)
engine->reset.finish(engine); engine->reset.finish(engine);
intel_uncore_forcewake_put(engine->uncore, FORCEWAKE_ALL); intel_uncore_forcewake_put(engine->uncore, FORCEWAKE_ALL);
intel_engine_breadcrumbs_irq(engine); intel_engine_signal_breadcrumbs(engine);
} }
static void reset_finish(struct intel_gt *gt, intel_engine_mask_t awake) static void reset_finish(struct intel_gt *gt, intel_engine_mask_t awake)
...@@ -771,7 +771,7 @@ static void nop_submit_request(struct i915_request *request) ...@@ -771,7 +771,7 @@ static void nop_submit_request(struct i915_request *request)
i915_request_mark_complete(request); i915_request_mark_complete(request);
spin_unlock_irqrestore(&engine->active.lock, flags); spin_unlock_irqrestore(&engine->active.lock, flags);
intel_engine_queue_breadcrumbs(engine); intel_engine_signal_breadcrumbs(engine);
} }
static void __intel_gt_set_wedged(struct intel_gt *gt) static void __intel_gt_set_wedged(struct intel_gt *gt)
......
...@@ -719,7 +719,7 @@ static int xcs_resume(struct intel_engine_cs *engine) ...@@ -719,7 +719,7 @@ static int xcs_resume(struct intel_engine_cs *engine)
} }
/* Papering over lost _interrupts_ immediately following the restart */ /* Papering over lost _interrupts_ immediately following the restart */
intel_engine_queue_breadcrumbs(engine); intel_engine_signal_breadcrumbs(engine);
out: out:
intel_uncore_forcewake_put(engine->uncore, FORCEWAKE_ALL); intel_uncore_forcewake_put(engine->uncore, FORCEWAKE_ALL);
......
...@@ -1566,7 +1566,7 @@ void gen6_rps_irq_handler(struct intel_rps *rps, u32 pm_iir) ...@@ -1566,7 +1566,7 @@ void gen6_rps_irq_handler(struct intel_rps *rps, u32 pm_iir)
return; return;
if (pm_iir & PM_VEBOX_USER_INTERRUPT) if (pm_iir & PM_VEBOX_USER_INTERRUPT)
intel_engine_breadcrumbs_irq(gt->engine[VECS0]); intel_engine_signal_breadcrumbs(gt->engine[VECS0]);
if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT) if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT)
DRM_DEBUG("Command parser error, pm_iir 0x%08x\n", pm_iir); DRM_DEBUG("Command parser error, pm_iir 0x%08x\n", pm_iir);
......
...@@ -77,7 +77,7 @@ static void advance(struct i915_request *request) ...@@ -77,7 +77,7 @@ static void advance(struct i915_request *request)
i915_request_mark_complete(request); i915_request_mark_complete(request);
GEM_BUG_ON(!i915_request_completed(request)); GEM_BUG_ON(!i915_request_completed(request));
intel_engine_queue_breadcrumbs(request->engine); intel_engine_signal_breadcrumbs(request->engine);
} }
static void hw_delay_complete(struct timer_list *t) static void hw_delay_complete(struct timer_list *t)
......
...@@ -3619,7 +3619,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) ...@@ -3619,7 +3619,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
intel_uncore_write16(&dev_priv->uncore, GEN2_IIR, iir); intel_uncore_write16(&dev_priv->uncore, GEN2_IIR, iir);
if (iir & I915_USER_INTERRUPT) if (iir & I915_USER_INTERRUPT)
intel_engine_breadcrumbs_irq(dev_priv->engine[RCS0]); intel_engine_signal_breadcrumbs(dev_priv->engine[RCS0]);
if (iir & I915_MASTER_ERROR_INTERRUPT) if (iir & I915_MASTER_ERROR_INTERRUPT)
i8xx_error_irq_handler(dev_priv, eir, eir_stuck); i8xx_error_irq_handler(dev_priv, eir, eir_stuck);
...@@ -3724,7 +3724,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) ...@@ -3724,7 +3724,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
I915_WRITE(GEN2_IIR, iir); I915_WRITE(GEN2_IIR, iir);
if (iir & I915_USER_INTERRUPT) if (iir & I915_USER_INTERRUPT)
intel_engine_breadcrumbs_irq(dev_priv->engine[RCS0]); intel_engine_signal_breadcrumbs(dev_priv->engine[RCS0]);
if (iir & I915_MASTER_ERROR_INTERRUPT) if (iir & I915_MASTER_ERROR_INTERRUPT)
i9xx_error_irq_handler(dev_priv, eir, eir_stuck); i9xx_error_irq_handler(dev_priv, eir, eir_stuck);
...@@ -3866,10 +3866,10 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) ...@@ -3866,10 +3866,10 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
I915_WRITE(GEN2_IIR, iir); I915_WRITE(GEN2_IIR, iir);
if (iir & I915_USER_INTERRUPT) if (iir & I915_USER_INTERRUPT)
intel_engine_breadcrumbs_irq(dev_priv->engine[RCS0]); intel_engine_signal_breadcrumbs(dev_priv->engine[RCS0]);
if (iir & I915_BSD_USER_INTERRUPT) if (iir & I915_BSD_USER_INTERRUPT)
intel_engine_breadcrumbs_irq(dev_priv->engine[VCS0]); intel_engine_signal_breadcrumbs(dev_priv->engine[VCS0]);
if (iir & I915_MASTER_ERROR_INTERRUPT) if (iir & I915_MASTER_ERROR_INTERRUPT)
i9xx_error_irq_handler(dev_priv, eir, eir_stuck); i9xx_error_irq_handler(dev_priv, eir, eir_stuck);
......
...@@ -408,7 +408,7 @@ bool __i915_request_submit(struct i915_request *request) ...@@ -408,7 +408,7 @@ bool __i915_request_submit(struct i915_request *request)
if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &request->fence.flags) && if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &request->fence.flags) &&
!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &request->fence.flags) && !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &request->fence.flags) &&
!i915_request_enable_breadcrumb(request)) !i915_request_enable_breadcrumb(request))
intel_engine_queue_breadcrumbs(engine); intel_engine_signal_breadcrumbs(engine);
__notify_execute_cb(request); __notify_execute_cb(request);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment