summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_irq.c
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2017-08-18 21:36:51 +0300
committerVille Syrjälä <ville.syrjala@linux.intel.com>2017-09-14 17:09:06 +0300
commit44d9241e3e62a6938b5ae2ec6b3b4cd5abfdb717 (patch)
tree20e9ba4fb7bc903a4f65d9fbebf6403748eb1225 /drivers/gpu/drm/i915/i915_irq.c
parent842ebf7aeb1d6d5d679491d33d8c3f113de7964e (diff)
downloadop-kernel-dev-44d9241e3e62a6938b5ae2ec6b3b4cd5abfdb717.zip
op-kernel-dev-44d9241e3e62a6938b5ae2ec6b3b4cd5abfdb717.tar.gz
drm/i915: Clear pipestat consistently
We have a lot of different ways of clearing the PIPESTAT registers. Let's unify it all into one function. There's no magic in PIPESTAT that would require any of the double clearing and whatnot that some of the code tries to do. All we can really do is clear the status bits and disable the enable bits. There is no way to mask anything so as soon as another event happens the status bit will become set again, and trying to clear them twice or something can't protect against that. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20170818183705.27850-3-ville.syrjala@linux.intel.com Reviewed-by: Imre Deak <imre.deak@intel.com>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c67
1 files changed, 30 insertions, 37 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 9b5be5c..12c5af9 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1709,6 +1709,19 @@ static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 gt_iir)
}
}
+static void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv)
+{
+ enum pipe pipe;
+
+ for_each_pipe(dev_priv, pipe) {
+ I915_WRITE(PIPESTAT(pipe),
+ PIPESTAT_INT_STATUS_MASK |
+ PIPE_FIFO_UNDERRUN_STATUS);
+
+ dev_priv->pipestat_irq_mask[pipe] = 0;
+ }
+}
+
static void valleyview_pipestat_irq_ack(struct drm_i915_private *dev_priv,
u32 iir, u32 pipe_stats[I915_MAX_PIPES])
{
@@ -2898,8 +2911,6 @@ static void gen5_gt_irq_reset(struct drm_i915_private *dev_priv)
static void vlv_display_irq_reset(struct drm_i915_private *dev_priv)
{
- enum pipe pipe;
-
if (IS_CHERRYVIEW(dev_priv))
I915_WRITE(DPINVGTT, DPINVGTT_STATUS_MASK_CHV);
else
@@ -2908,12 +2919,7 @@ static void vlv_display_irq_reset(struct drm_i915_private *dev_priv)
i915_hotplug_interrupt_update_locked(dev_priv, 0xffffffff, 0);
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
- for_each_pipe(dev_priv, pipe) {
- I915_WRITE(PIPESTAT(pipe),
- PIPE_FIFO_UNDERRUN_STATUS |
- PIPESTAT_INT_STATUS_MASK);
- dev_priv->pipestat_irq_mask[pipe] = 0;
- }
+ i9xx_pipestat_irq_reset(dev_priv);
GEN5_IRQ_RESET(VLV_);
dev_priv->irq_mask = ~0;
@@ -3566,10 +3572,9 @@ static void ironlake_irq_uninstall(struct drm_device *dev)
static void i8xx_irq_preinstall(struct drm_device * dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
- int pipe;
- for_each_pipe(dev_priv, pipe)
- I915_WRITE(PIPESTAT(pipe), 0);
+ i9xx_pipestat_irq_reset(dev_priv);
+
I915_WRITE16(IMR, 0xffff);
I915_WRITE16(IER, 0x0);
POSTING_READ16(IER);
@@ -3681,13 +3686,9 @@ out:
static void i8xx_irq_uninstall(struct drm_device * dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
- int pipe;
- for_each_pipe(dev_priv, pipe) {
- /* Clear enable bits; then clear status bits */
- I915_WRITE(PIPESTAT(pipe), 0);
- I915_WRITE(PIPESTAT(pipe), I915_READ(PIPESTAT(pipe)));
- }
+ i9xx_pipestat_irq_reset(dev_priv);
+
I915_WRITE16(IMR, 0xffff);
I915_WRITE16(IER, 0x0);
I915_WRITE16(IIR, I915_READ16(IIR));
@@ -3696,16 +3697,16 @@ static void i8xx_irq_uninstall(struct drm_device * dev)
static void i915_irq_preinstall(struct drm_device * dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
- int pipe;
if (I915_HAS_HOTPLUG(dev_priv)) {
i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
}
+ i9xx_pipestat_irq_reset(dev_priv);
+
I915_WRITE16(HWSTAM, 0xeffe);
- for_each_pipe(dev_priv, pipe)
- I915_WRITE(PIPESTAT(pipe), 0);
+
I915_WRITE(IMR, 0xffffffff);
I915_WRITE(IER, 0x0);
POSTING_READ(IER);
@@ -3861,36 +3862,32 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
static void i915_irq_uninstall(struct drm_device * dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
- int pipe;
if (I915_HAS_HOTPLUG(dev_priv)) {
i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
}
+ i9xx_pipestat_irq_reset(dev_priv);
+
I915_WRITE16(HWSTAM, 0xffff);
- for_each_pipe(dev_priv, pipe) {
- /* Clear enable bits; then clear status bits */
- I915_WRITE(PIPESTAT(pipe), 0);
- I915_WRITE(PIPESTAT(pipe), I915_READ(PIPESTAT(pipe)));
- }
+
I915_WRITE(IMR, 0xffffffff);
I915_WRITE(IER, 0x0);
-
I915_WRITE(IIR, I915_READ(IIR));
}
static void i965_irq_preinstall(struct drm_device * dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
- int pipe;
i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
+ i9xx_pipestat_irq_reset(dev_priv);
+
I915_WRITE(HWSTAM, 0xeffe);
- for_each_pipe(dev_priv, pipe)
- I915_WRITE(PIPESTAT(pipe), 0);
+
I915_WRITE(IMR, 0xffffffff);
I915_WRITE(IER, 0x0);
POSTING_READ(IER);
@@ -4084,7 +4081,6 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
static void i965_irq_uninstall(struct drm_device * dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
- int pipe;
if (!dev_priv)
return;
@@ -4092,15 +4088,12 @@ static void i965_irq_uninstall(struct drm_device * dev)
i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
+ i9xx_pipestat_irq_reset(dev_priv);
+
I915_WRITE(HWSTAM, 0xffffffff);
- for_each_pipe(dev_priv, pipe)
- I915_WRITE(PIPESTAT(pipe), 0);
+
I915_WRITE(IMR, 0xffffffff);
I915_WRITE(IER, 0x0);
-
- for_each_pipe(dev_priv, pipe)
- I915_WRITE(PIPESTAT(pipe),
- I915_READ(PIPESTAT(pipe)) & 0x8000ffff);
I915_WRITE(IIR, I915_READ(IIR));
}
OpenPOWER on IntegriCloud