Skip to content

Commit

Permalink
drm/i915: Reduce locking in gen8 IRQ handler
Browse files Browse the repository at this point in the history
Similar in vain in reducing the number of unrequired spinlocks used for
execlist command submission (where the forcewake is required but
manually controlled), we know that the IRQ registers are outside of the
powerwell and so we can access them directly. Since we now have direct
access exported via I915_READ_FW/I915_WRITE_FW, lets put those to use in
the irq handlers as well.

In the process, reorder the execlist submission to happen as early as
possible.

v2: Restrict the untraced register mmio to just the GT path (i.e. the
hotpath for execlists)

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
  • Loading branch information
Chris Wilson authored and Daniel Vetter committed Apr 10, 2015
1 parent a6111f7 commit cb0d205
Showing 1 changed file with 23 additions and 24 deletions.
47 changes: 23 additions & 24 deletions drivers/gpu/drm/i915/i915_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -1285,74 +1285,74 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,
irqreturn_t ret = IRQ_NONE;

if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) {
tmp = I915_READ(GEN8_GT_IIR(0));
tmp = I915_READ_FW(GEN8_GT_IIR(0));
if (tmp) {
I915_WRITE(GEN8_GT_IIR(0), tmp);
I915_WRITE_FW(GEN8_GT_IIR(0), tmp);
ret = IRQ_HANDLED;

rcs = tmp >> GEN8_RCS_IRQ_SHIFT;
ring = &dev_priv->ring[RCS];
if (rcs & GT_RENDER_USER_INTERRUPT)
notify_ring(dev, ring);
if (rcs & GT_CONTEXT_SWITCH_INTERRUPT)
intel_lrc_irq_handler(ring);
if (rcs & GT_RENDER_USER_INTERRUPT)
notify_ring(dev, ring);

bcs = tmp >> GEN8_BCS_IRQ_SHIFT;
ring = &dev_priv->ring[BCS];
if (bcs & GT_RENDER_USER_INTERRUPT)
notify_ring(dev, ring);
if (bcs & GT_CONTEXT_SWITCH_INTERRUPT)
intel_lrc_irq_handler(ring);
if (bcs & GT_RENDER_USER_INTERRUPT)
notify_ring(dev, ring);
} else
DRM_ERROR("The master control interrupt lied (GT0)!\n");
}

if (master_ctl & (GEN8_GT_VCS1_IRQ | GEN8_GT_VCS2_IRQ)) {
tmp = I915_READ(GEN8_GT_IIR(1));
tmp = I915_READ_FW(GEN8_GT_IIR(1));
if (tmp) {
I915_WRITE(GEN8_GT_IIR(1), tmp);
I915_WRITE_FW(GEN8_GT_IIR(1), tmp);
ret = IRQ_HANDLED;

vcs = tmp >> GEN8_VCS1_IRQ_SHIFT;
ring = &dev_priv->ring[VCS];
if (vcs & GT_RENDER_USER_INTERRUPT)
notify_ring(dev, ring);
if (vcs & GT_CONTEXT_SWITCH_INTERRUPT)
intel_lrc_irq_handler(ring);
if (vcs & GT_RENDER_USER_INTERRUPT)
notify_ring(dev, ring);

vcs = tmp >> GEN8_VCS2_IRQ_SHIFT;
ring = &dev_priv->ring[VCS2];
if (vcs & GT_RENDER_USER_INTERRUPT)
notify_ring(dev, ring);
if (vcs & GT_CONTEXT_SWITCH_INTERRUPT)
intel_lrc_irq_handler(ring);
if (vcs & GT_RENDER_USER_INTERRUPT)
notify_ring(dev, ring);
} else
DRM_ERROR("The master control interrupt lied (GT1)!\n");
}

if (master_ctl & GEN8_GT_PM_IRQ) {
tmp = I915_READ(GEN8_GT_IIR(2));
tmp = I915_READ_FW(GEN8_GT_IIR(2));
if (tmp & dev_priv->pm_rps_events) {
I915_WRITE(GEN8_GT_IIR(2),
tmp & dev_priv->pm_rps_events);
I915_WRITE_FW(GEN8_GT_IIR(2),
tmp & dev_priv->pm_rps_events);
ret = IRQ_HANDLED;
gen6_rps_irq_handler(dev_priv, tmp);
} else
DRM_ERROR("The master control interrupt lied (PM)!\n");
}

if (master_ctl & GEN8_GT_VECS_IRQ) {
tmp = I915_READ(GEN8_GT_IIR(3));
tmp = I915_READ_FW(GEN8_GT_IIR(3));
if (tmp) {
I915_WRITE(GEN8_GT_IIR(3), tmp);
I915_WRITE_FW(GEN8_GT_IIR(3), tmp);
ret = IRQ_HANDLED;

vcs = tmp >> GEN8_VECS_IRQ_SHIFT;
ring = &dev_priv->ring[VECS];
if (vcs & GT_RENDER_USER_INTERRUPT)
notify_ring(dev, ring);
if (vcs & GT_CONTEXT_SWITCH_INTERRUPT)
intel_lrc_irq_handler(ring);
if (vcs & GT_RENDER_USER_INTERRUPT)
notify_ring(dev, ring);
} else
DRM_ERROR("The master control interrupt lied (GT3)!\n");
}
Expand Down Expand Up @@ -2178,13 +2178,12 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
aux_mask |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C |
GEN9_AUX_CHANNEL_D;

master_ctl = I915_READ(GEN8_MASTER_IRQ);
master_ctl = I915_READ_FW(GEN8_MASTER_IRQ);
master_ctl &= ~GEN8_MASTER_IRQ_CONTROL;
if (!master_ctl)
return IRQ_NONE;

I915_WRITE(GEN8_MASTER_IRQ, 0);
POSTING_READ(GEN8_MASTER_IRQ);
I915_WRITE_FW(GEN8_MASTER_IRQ, 0);

/* Find, clear, then process each source of interrupt */

Expand Down Expand Up @@ -2281,8 +2280,8 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)

}

I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
POSTING_READ(GEN8_MASTER_IRQ);
I915_WRITE_FW(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
POSTING_READ_FW(GEN8_MASTER_IRQ);

return ret;
}
Expand Down

0 comments on commit cb0d205

Please sign in to comment.