diff options
Diffstat (limited to 'sys/dev/pci/drm/i915/i915_irq.c')
-rw-r--r-- | sys/dev/pci/drm/i915/i915_irq.c | 99 |
1 files changed, 59 insertions, 40 deletions
diff --git a/sys/dev/pci/drm/i915/i915_irq.c b/sys/dev/pci/drm/i915/i915_irq.c index d84f5a1344e..14c812d08f8 100644 --- a/sys/dev/pci/drm/i915/i915_irq.c +++ b/sys/dev/pci/drm/i915/i915_irq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: i915_irq.c,v 1.17 2015/02/10 06:19:36 jsg Exp $ */ +/* $OpenBSD: i915_irq.c,v 1.18 2015/02/10 10:50:49 jsg Exp $ */ /* i915_irq.c -- IRQ support for the I915 -*- linux-c -*- */ /* @@ -89,12 +89,13 @@ i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask) void intel_enable_asle(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; + unsigned long irqflags; /* FIXME: opregion/asle for VLV */ if (IS_VALLEYVIEW(dev)) return; - mtx_enter(&dev_priv->irq_lock); + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); if (HAS_PCH_SPLIT(dev)) ironlake_enable_display_irq(dev_priv, DE_GSE); @@ -106,7 +107,7 @@ void intel_enable_asle(struct drm_device *dev) PIPE_LEGACY_BLC_EVENT_ENABLE); } - mtx_leave(&dev_priv->irq_lock); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } /** @@ -306,8 +307,9 @@ static void ironlake_handle_rps_change(struct drm_device *dev) drm_i915_private_t *dev_priv = dev->dev_private; u32 busy_up, busy_down, max_avg, min_avg; u8 new_delay; + unsigned long flags; - mtx_enter(&mchdev_lock); + spin_lock_irqsave(&mchdev_lock, flags); I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS)); @@ -335,7 +337,7 @@ static void ironlake_handle_rps_change(struct drm_device *dev) if (ironlake_set_drps(dev, new_delay)) dev_priv->ips.cur_delay = new_delay; - mtx_leave(&mchdev_lock); + spin_unlock_irqrestore(&mchdev_lock, flags); return; } @@ -365,12 +367,12 @@ static void gen6_pm_rps_work(void *arg1) u32 pm_iir, pm_imr; u8 new_delay; - mtx_enter(&dev_priv->rps.lock); + spin_lock_irq(&dev_priv->rps.lock); pm_iir = dev_priv->rps.pm_iir; dev_priv->rps.pm_iir = 0; pm_imr = I915_READ(GEN6_PMIMR); I915_WRITE(GEN6_PMIMR, 0); - mtx_leave(&dev_priv->rps.lock); + spin_unlock_irq(&dev_priv->rps.lock); if ((pm_iir & GEN6_PM_DEFERRED_EVENTS) == 0) return; @@ -409,6 +411,7 @@ static void ivybridge_parity_work(void *arg1) u32 error_status, row, bank, subbank; // char *parity_event[5]; uint32_t misccpctl; + unsigned long flags; /* We must turn off DOP level clock gating to access the L3 registers. * In order to prevent a get/put style interface, acquire struct mutex @@ -431,10 +434,10 @@ static void ivybridge_parity_work(void *arg1) I915_WRITE(GEN7_MISCCPCTL, misccpctl); - mtx_enter(&dev_priv->irq_lock); + spin_lock_irqsave(&dev_priv->irq_lock, flags); dev_priv->gt_irq_mask &= ~GT_GEN7_L3_PARITY_ERROR_INTERRUPT; I915_WRITE(GTIMR, dev_priv->gt_irq_mask); - mtx_leave(&dev_priv->irq_lock); + spin_unlock_irqrestore(&dev_priv->irq_lock, flags); mutex_unlock(&dev->struct_mutex); @@ -464,14 +467,15 @@ static void ivybridge_parity_work(void *arg1) static void ivybridge_handle_parity_error(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + unsigned long flags; if (!HAS_L3_GPU_CACHE(dev)) return; - mtx_enter(&dev_priv->irq_lock); + spin_lock_irqsave(&dev_priv->irq_lock, flags); dev_priv->gt_irq_mask |= GT_GEN7_L3_PARITY_ERROR_INTERRUPT; I915_WRITE(GTIMR, dev_priv->gt_irq_mask); - mtx_leave(&dev_priv->irq_lock); + spin_unlock_irqrestore(&dev_priv->irq_lock, flags); task_add(systq, &dev_priv->l3_parity.error_task); } @@ -503,6 +507,8 @@ static void snb_gt_irq_handler(struct drm_device *dev, static void gen6_queue_rps_work(struct drm_i915_private *dev_priv, u32 pm_iir) { + unsigned long flags; + /* * IIR bits should never already be set because IMR should * prevent an interrupt from being shown in IIR. The warning @@ -513,11 +519,11 @@ static void gen6_queue_rps_work(struct drm_i915_private *dev_priv, * The mask bit in IMR is cleared by dev_priv->rps.work. */ - mtx_enter(&dev_priv->rps.lock); + spin_lock_irqsave(&dev_priv->rps.lock, flags); dev_priv->rps.pm_iir |= pm_iir; I915_WRITE(GEN6_PMIMR, dev_priv->rps.pm_iir); POSTING_READ(GEN6_PMIMR); - mtx_leave(&dev_priv->rps.lock); + spin_unlock_irqrestore(&dev_priv->rps.lock, flags); task_add(systq, &dev_priv->rps.task); } @@ -528,6 +534,7 @@ static int valleyview_intr(void *arg) struct drm_device *dev = (struct drm_device *)dev_priv->drmdev; u32 iir, gt_iir, pm_iir; int ret = IRQ_NONE; + unsigned long irqflags; int pipe; u32 pipe_stats[I915_MAX_PIPES]; bool blc_event; @@ -546,7 +553,7 @@ static int valleyview_intr(void *arg) snb_gt_irq_handler(dev, dev_priv, gt_iir); - mtx_enter(&dev_priv->irq_lock); + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); for_each_pipe(pipe) { int reg = PIPESTAT(pipe); pipe_stats[pipe] = I915_READ(reg); @@ -561,7 +568,7 @@ static int valleyview_intr(void *arg) I915_WRITE(reg, pipe_stats[pipe]); } } - mtx_leave(&dev_priv->irq_lock); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); for_each_pipe(pipe) { if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) @@ -1479,20 +1486,21 @@ static void i915_pageflip_stall_check(struct drm_device *dev, int pipe) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_i915_gem_object *obj; struct intel_unpin_work *work; + unsigned long flags; bool stall_detected; /* Ignore early vblank irqs */ if (intel_crtc == NULL) return; - mtx_enter(&dev->event_lock); + spin_lock_irqsave(&dev->event_lock, flags); work = intel_crtc->unpin_work; if (work == NULL || atomic_read(&work->pending) >= INTEL_FLIP_COMPLETE || !work->enable_stall_check) { /* Either the pending flip IRQ arrived, or we're too early. Don't check */ - mtx_leave(&dev->event_lock); + spin_unlock_irqrestore(&dev->event_lock, flags); return; } @@ -1509,7 +1517,7 @@ static void i915_pageflip_stall_check(struct drm_device *dev, int pipe) crtc->x * crtc->fb->bits_per_pixel/8); } - mtx_leave(&dev->event_lock); + spin_unlock_irqrestore(&dev->event_lock, flags); if (stall_detected) { DRM_DEBUG_DRIVER("Pageflip stall detected\n"); @@ -1523,11 +1531,12 @@ static void i915_pageflip_stall_check(struct drm_device *dev, int pipe) static int i915_enable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + unsigned long irqflags; if (!i915_pipe_enabled(dev, pipe)) return -EINVAL; - mtx_enter(&dev_priv->irq_lock); + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); if (INTEL_INFO(dev)->gen >= 4) i915_enable_pipestat(dev_priv, pipe, PIPE_START_VBLANK_INTERRUPT_ENABLE); @@ -1538,7 +1547,7 @@ static int i915_enable_vblank(struct drm_device *dev, int pipe) /* maintain vblank delivery even in deep C-states */ if (dev_priv->info->gen == 3) I915_WRITE(INSTPM, _MASKED_BIT_DISABLE(INSTPM_AGPBUSY_DIS)); - mtx_leave(&dev_priv->irq_lock); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); return 0; } @@ -1546,14 +1555,15 @@ static int i915_enable_vblank(struct drm_device *dev, int pipe) static int ironlake_enable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + unsigned long irqflags; if (!i915_pipe_enabled(dev, pipe)) return -EINVAL; - mtx_enter(&dev_priv->irq_lock); + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); ironlake_enable_display_irq(dev_priv, (pipe == 0) ? DE_PIPEA_VBLANK : DE_PIPEB_VBLANK); - mtx_leave(&dev_priv->irq_lock); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); return 0; } @@ -1561,14 +1571,15 @@ static int ironlake_enable_vblank(struct drm_device *dev, int pipe) static int ivybridge_enable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + unsigned long irqflags; if (!i915_pipe_enabled(dev, pipe)) return -EINVAL; - mtx_enter(&dev_priv->irq_lock); + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); ironlake_enable_display_irq(dev_priv, DE_PIPEA_VBLANK_IVB << (5 * pipe)); - mtx_leave(&dev_priv->irq_lock); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); return 0; } @@ -1576,12 +1587,13 @@ static int ivybridge_enable_vblank(struct drm_device *dev, int pipe) static int valleyview_enable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + unsigned long irqflags; u32 imr; if (!i915_pipe_enabled(dev, pipe)) return -EINVAL; - mtx_enter(&dev_priv->irq_lock); + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); imr = I915_READ(VLV_IMR); if (pipe == 0) imr &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT; @@ -1590,7 +1602,7 @@ static int valleyview_enable_vblank(struct drm_device *dev, int pipe) I915_WRITE(VLV_IMR, imr); i915_enable_pipestat(dev_priv, pipe, PIPE_START_VBLANK_INTERRUPT_ENABLE); - mtx_leave(&dev_priv->irq_lock); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); return 0; } @@ -1601,43 +1613,47 @@ static int valleyview_enable_vblank(struct drm_device *dev, int pipe) static void i915_disable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + unsigned long irqflags; - mtx_enter(&dev_priv->irq_lock); + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); if (dev_priv->info->gen == 3) I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_AGPBUSY_DIS)); i915_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE | PIPE_START_VBLANK_INTERRUPT_ENABLE); - mtx_leave(&dev_priv->irq_lock); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } static void ironlake_disable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + unsigned long irqflags; - mtx_enter(&dev_priv->irq_lock); + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); ironlake_disable_display_irq(dev_priv, (pipe == 0) ? DE_PIPEA_VBLANK : DE_PIPEB_VBLANK); - mtx_leave(&dev_priv->irq_lock); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } static void ivybridge_disable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + unsigned long irqflags; - mtx_enter(&dev_priv->irq_lock); + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); ironlake_disable_display_irq(dev_priv, DE_PIPEA_VBLANK_IVB << (pipe * 5)); - mtx_leave(&dev_priv->irq_lock); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } static void valleyview_disable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + unsigned long irqflags; u32 imr; - mtx_enter(&dev_priv->irq_lock); + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); i915_disable_pipestat(dev_priv, pipe, PIPE_START_VBLANK_INTERRUPT_ENABLE); imr = I915_READ(VLV_IMR); @@ -1646,7 +1662,7 @@ static void valleyview_disable_vblank(struct drm_device *dev, int pipe) else imr |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; I915_WRITE(VLV_IMR, imr); - mtx_leave(&dev_priv->irq_lock); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } static u32 @@ -2145,6 +2161,7 @@ static int i8xx_intr(void *arg) struct drm_device *dev = (struct drm_device *)dev_priv->drmdev; u16 iir, new_iir; u32 pipe_stats[2]; + unsigned long irqflags; int irq_received; int pipe; u16 flip_mask = @@ -2163,7 +2180,7 @@ static int i8xx_intr(void *arg) * It doesn't set the bit in iir again, but it still produces * interrupts (for non-MSI). */ - mtx_enter(&dev_priv->irq_lock); + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) i915_handle_error(dev, false); @@ -2182,7 +2199,7 @@ static int i8xx_intr(void *arg) irq_received = 1; } } - mtx_leave(&dev_priv->irq_lock); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); I915_WRITE16(IIR, iir & ~flip_mask); new_iir = I915_READ16(IIR); /* Flush posted writes */ @@ -2321,6 +2338,7 @@ static int i915_intr(void *arg) drm_i915_private_t *dev_priv = arg; struct drm_device *dev = (struct drm_device *)dev_priv->drmdev; u32 iir, new_iir, pipe_stats[I915_MAX_PIPES]; + unsigned long irqflags; u32 flip_mask = I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT | I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT; @@ -2342,7 +2360,7 @@ static int i915_intr(void *arg) * It doesn't set the bit in iir again, but it still produces * interrupts (for non-MSI). */ - mtx_enter(&dev_priv->irq_lock); + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) i915_handle_error(dev, false); @@ -2359,7 +2377,7 @@ static int i915_intr(void *arg) irq_received = true; } } - mtx_leave(&dev_priv->irq_lock); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); if (!irq_received) break; @@ -2558,6 +2576,7 @@ static int i965_intr(void *arg) struct drm_device *dev = (struct drm_device *)dev_priv->drmdev; u32 iir, new_iir; u32 pipe_stats[I915_MAX_PIPES]; + unsigned long irqflags; int irq_received; int ret = IRQ_NONE, pipe; @@ -2575,7 +2594,7 @@ static int i965_intr(void *arg) * It doesn't set the bit in iir again, but it still produces * interrupts (for non-MSI). */ - mtx_enter(&dev_priv->irq_lock); + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) i915_handle_error(dev, false); @@ -2594,7 +2613,7 @@ static int i965_intr(void *arg) irq_received = 1; } } - mtx_leave(&dev_priv->irq_lock); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); if (!irq_received) break; |