diff options
author | Thomas Daniel <thomas.daniel@intel.com> | 2014-07-24 12:04:39 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2014-08-14 16:43:47 -0400 |
commit | e981e7b17f2b41970e7e2367d4225e0bb3310667 (patch) | |
tree | d4109ce705c97f5e635aa7f4d97fa559b5d41cda /drivers/gpu/drm/i915/i915_irq.c | |
parent | acdd884a2e1b873995c120d5eabd8cab77f48f20 (diff) |
drm/i915/bdw: Handle context switch events
Handle all context status events in the context status buffer on every
context switch interrupt. We only remove work from the execlist queue
after a context status buffer reports that it has completed and we only
attempt to schedule new contexts on interrupt when a previously submitted
context completes (unless no contexts are queued, which means the GPU is
free).
We canot call intel_runtime_pm_get() in an interrupt (or with a spinlock
grabbed, FWIW), because it might sleep, which is not a nice thing to do.
Instead, do the runtime_pm get/put together with the create/destroy request,
and handle the forcewake get/put directly.
Signed-off-by: Thomas Daniel <thomas.daniel@intel.com>
v2: Unreferencing the context when we are freeing the request might free
the backing bo, which requires the struct_mutex to be grabbed, so defer
unreferencing and freeing to a bottom half.
v3:
- Ack the interrupt inmediately, before trying to handle it (fix for
missing interrupts by Bob Beckett <robert.beckett@intel.com>).
- Update the Context Status Buffer Read Pointer, just in case (spotted
by Damien Lespiau).
v4: New namespace and multiple rebase changes.
v5: Squash with "drm/i915/bdw: Do not call intel_runtime_pm_get() in an
interrupt", as suggested by Daniel.
Signed-off-by: Oscar Mateo <oscar.mateo@intel.com>
Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>
[danvet: Checkpatch ...]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 35 |
1 files changed, 24 insertions, 11 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 00957fa0b877..f5d6795887d2 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -1632,6 +1632,7 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, | |||
1632 | struct drm_i915_private *dev_priv, | 1632 | struct drm_i915_private *dev_priv, |
1633 | u32 master_ctl) | 1633 | u32 master_ctl) |
1634 | { | 1634 | { |
1635 | struct intel_engine_cs *ring; | ||
1635 | u32 rcs, bcs, vcs; | 1636 | u32 rcs, bcs, vcs; |
1636 | uint32_t tmp = 0; | 1637 | uint32_t tmp = 0; |
1637 | irqreturn_t ret = IRQ_NONE; | 1638 | irqreturn_t ret = IRQ_NONE; |
@@ -1641,14 +1642,20 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, | |||
1641 | if (tmp) { | 1642 | if (tmp) { |
1642 | I915_WRITE(GEN8_GT_IIR(0), tmp); | 1643 | I915_WRITE(GEN8_GT_IIR(0), tmp); |
1643 | ret = IRQ_HANDLED; | 1644 | ret = IRQ_HANDLED; |
1645 | |||
1644 | rcs = tmp >> GEN8_RCS_IRQ_SHIFT; | 1646 | rcs = tmp >> GEN8_RCS_IRQ_SHIFT; |
1645 | bcs = tmp >> GEN8_BCS_IRQ_SHIFT; | 1647 | ring = &dev_priv->ring[RCS]; |
1646 | if (rcs & GT_RENDER_USER_INTERRUPT) | 1648 | if (rcs & GT_RENDER_USER_INTERRUPT) |
1647 | notify_ring(dev, &dev_priv->ring[RCS]); | 1649 | notify_ring(dev, ring); |
1650 | if (rcs & GT_CONTEXT_SWITCH_INTERRUPT) | ||
1651 | intel_execlists_handle_ctx_events(ring); | ||
1652 | |||
1653 | bcs = tmp >> GEN8_BCS_IRQ_SHIFT; | ||
1654 | ring = &dev_priv->ring[BCS]; | ||
1648 | if (bcs & GT_RENDER_USER_INTERRUPT) | 1655 | if (bcs & GT_RENDER_USER_INTERRUPT) |
1649 | notify_ring(dev, &dev_priv->ring[BCS]); | 1656 | notify_ring(dev, ring); |
1650 | if ((rcs | bcs) & GT_CONTEXT_SWITCH_INTERRUPT) | 1657 | if (bcs & GT_CONTEXT_SWITCH_INTERRUPT) |
1651 | DRM_DEBUG_DRIVER("TODO: Context switch\n"); | 1658 | intel_execlists_handle_ctx_events(ring); |
1652 | } else | 1659 | } else |
1653 | DRM_ERROR("The master control interrupt lied (GT0)!\n"); | 1660 | DRM_ERROR("The master control interrupt lied (GT0)!\n"); |
1654 | } | 1661 | } |
@@ -1658,16 +1665,20 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, | |||
1658 | if (tmp) { | 1665 | if (tmp) { |
1659 | I915_WRITE(GEN8_GT_IIR(1), tmp); | 1666 | I915_WRITE(GEN8_GT_IIR(1), tmp); |
1660 | ret = IRQ_HANDLED; | 1667 | ret = IRQ_HANDLED; |
1668 | |||
1661 | vcs = tmp >> GEN8_VCS1_IRQ_SHIFT; | 1669 | vcs = tmp >> GEN8_VCS1_IRQ_SHIFT; |
1670 | ring = &dev_priv->ring[VCS]; | ||
1662 | if (vcs & GT_RENDER_USER_INTERRUPT) | 1671 | if (vcs & GT_RENDER_USER_INTERRUPT) |
1663 | notify_ring(dev, &dev_priv->ring[VCS]); | 1672 | notify_ring(dev, ring); |
1664 | if (vcs & GT_CONTEXT_SWITCH_INTERRUPT) | 1673 | if (vcs & GT_CONTEXT_SWITCH_INTERRUPT) |
1665 | DRM_DEBUG_DRIVER("TODO: Context switch\n"); | 1674 | intel_execlists_handle_ctx_events(ring); |
1675 | |||
1666 | vcs = tmp >> GEN8_VCS2_IRQ_SHIFT; | 1676 | vcs = tmp >> GEN8_VCS2_IRQ_SHIFT; |
1677 | ring = &dev_priv->ring[VCS2]; | ||
1667 | if (vcs & GT_RENDER_USER_INTERRUPT) | 1678 | if (vcs & GT_RENDER_USER_INTERRUPT) |
1668 | notify_ring(dev, &dev_priv->ring[VCS2]); | 1679 | notify_ring(dev, ring); |
1669 | if (vcs & GT_CONTEXT_SWITCH_INTERRUPT) | 1680 | if (vcs & GT_CONTEXT_SWITCH_INTERRUPT) |
1670 | DRM_DEBUG_DRIVER("TODO: Context switch\n"); | 1681 | intel_execlists_handle_ctx_events(ring); |
1671 | } else | 1682 | } else |
1672 | DRM_ERROR("The master control interrupt lied (GT1)!\n"); | 1683 | DRM_ERROR("The master control interrupt lied (GT1)!\n"); |
1673 | } | 1684 | } |
@@ -1688,11 +1699,13 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, | |||
1688 | if (tmp) { | 1699 | if (tmp) { |
1689 | I915_WRITE(GEN8_GT_IIR(3), tmp); | 1700 | I915_WRITE(GEN8_GT_IIR(3), tmp); |
1690 | ret = IRQ_HANDLED; | 1701 | ret = IRQ_HANDLED; |
1702 | |||
1691 | vcs = tmp >> GEN8_VECS_IRQ_SHIFT; | 1703 | vcs = tmp >> GEN8_VECS_IRQ_SHIFT; |
1704 | ring = &dev_priv->ring[VECS]; | ||
1692 | if (vcs & GT_RENDER_USER_INTERRUPT) | 1705 | if (vcs & GT_RENDER_USER_INTERRUPT) |
1693 | notify_ring(dev, &dev_priv->ring[VECS]); | 1706 | notify_ring(dev, ring); |
1694 | if (vcs & GT_CONTEXT_SWITCH_INTERRUPT) | 1707 | if (vcs & GT_CONTEXT_SWITCH_INTERRUPT) |
1695 | DRM_DEBUG_DRIVER("TODO: Context switch\n"); | 1708 | intel_execlists_handle_ctx_events(ring); |
1696 | } else | 1709 | } else |
1697 | DRM_ERROR("The master control interrupt lied (GT3)!\n"); | 1710 | DRM_ERROR("The master control interrupt lied (GT3)!\n"); |
1698 | } | 1711 | } |