summaryrefslogtreecommitdiff
path: root/sys/dev/pci/drm/i915/i915_irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pci/drm/i915/i915_irq.c')
-rw-r--r--sys/dev/pci/drm/i915/i915_irq.c99
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;