aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_irq.c
diff options
context:
space:
mode:
authorThomas Daniel <thomas.daniel@intel.com>2014-07-24 12:04:39 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-08-14 16:43:47 -0400
commite981e7b17f2b41970e7e2367d4225e0bb3310667 (patch)
treed4109ce705c97f5e635aa7f4d97fa559b5d41cda /drivers/gpu/drm/i915/i915_irq.c
parentacdd884a2e1b873995c120d5eabd8cab77f48f20 (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.c35
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 }