Re: [Intel-gfx] [PATCH 08/10] drm/i915: print PCH FIFO underrun interrupts

2013-02-14 Thread Paulo Zanoni
Hi

2013/2/9 Daniel Vetter dan...@ffwll.ch:
 On Fri, Feb 08, 2013 at 05:35:19PM -0200, Paulo Zanoni wrote:
 From: Paulo Zanoni paulo.r.zan...@intel.com

 Also add an ignore bit that avoids printing the message in two
 cases:
   - When the message is in fact expected.
   - After we get the first message. In tihs case, we expect to get
 hundreds of consecutive messages, so we just ignore all the
 subsequent messages until the next crtc_enable.

 Signed-off-by: Paulo Zanoni paulo.r.zan...@intel.com

 Ah, here's the block underrun reporting stuff. You need to set up this
 infrastructure first, then enable the error interrupts. Otherwise a poor
 bloke will hit the irq strom in between these two patches in a bisect and
 die from a heart attack when looking at dmesg.

Nope. This patch is also the patch that adds the dmesg message, so
without this patch there is no message to ignore. Without this patch
we still get the interrupts, but this shouldn't be a problem because
we don't print anything and because of patch 5.


 Also, you update the ignore_bla from the irq handler, so this needs proper
 locking.
Will fix.

 And I vote for the bikeshed to be moved into struct intel_crtc,
 e.g.

It may be a little slightly slower, since we'll have to look for the
crtc pointers on our structs. And on Haswell, checking which crtc is
using the PCH transcoder will be more complicated. I'll try to think
on a good solution.

My initial idea was to actually group all the interrupt-related bits
from dev_priv into an interrupt struct, and put the ignore_fifo bits
there.


 struct intel_crtc {
 ...

 struct spinlock underrun_lock;
 int underrun_reporting_enabled;
 }

 Then smash a little helper into every crtc_enable/disable function. Aside:
 you need to use the spin_lock_irqsafe/restore functions in the irq handler
 (and for safety also in the helpers).  Another curious question: Why do we
 need separate ignore bits for the cpu and the pch?

Because: (i) sometimes we get errors from one but not from the other;
(ii) during pipe/transcoder disable we only want to ignore the PCH
underruns, not the CPU underruns; (iii) on Haswell, there's no 1:1
mapping between CPU pipe and PCH transcoder.

 -Daniel

 ---
  drivers/gpu/drm/i915/i915_drv.h  |3 +++
  drivers/gpu/drm/i915/i915_irq.c  |   37 
 +-
  drivers/gpu/drm/i915/i915_reg.h  |7 +--
  drivers/gpu/drm/i915/intel_display.c |   14 -
  4 files changed, 53 insertions(+), 8 deletions(-)

 diff --git a/drivers/gpu/drm/i915/i915_drv.h 
 b/drivers/gpu/drm/i915/i915_drv.h
 index 08c5def..e96d75e 100644
 --- a/drivers/gpu/drm/i915/i915_drv.h
 +++ b/drivers/gpu/drm/i915/i915_drv.h
 @@ -909,6 +909,9 @@ typedef struct drm_i915_private {
   struct work_struct hotplug_work;
   bool enable_hotplug_processing;

 + /* Bit 0: PCH transcoder A and so on. */
 + u8 ignore_pch_fifo_underrun;
 +
   int num_pipe;
   int num_pch_pll;

 diff --git a/drivers/gpu/drm/i915/i915_irq.c 
 b/drivers/gpu/drm/i915/i915_irq.c
 index 703a08a..7497589 100644
 --- a/drivers/gpu/drm/i915/i915_irq.c
 +++ b/drivers/gpu/drm/i915/i915_irq.c
 @@ -659,10 +659,17 @@ static void ibx_irq_handler(struct drm_device *dev, 
 u32 pch_iir)
   if (pch_iir  (SDE_TRANSB_CRC_ERR | SDE_TRANSA_CRC_ERR))
   DRM_DEBUG_DRIVER(PCH transcoder CRC error interrupt\n);

 - if (pch_iir  SDE_TRANSB_FIFO_UNDER)
 - DRM_DEBUG_DRIVER(PCH transcoder B underrun interrupt\n);
 - if (pch_iir  SDE_TRANSA_FIFO_UNDER)
 - DRM_DEBUG_DRIVER(PCH transcoder A underrun interrupt\n);
 + if ((pch_iir  SDE_TRANSB_FIFO_UNDER) 
 + !(dev_priv-ignore_pch_fifo_underrun  (1  TRANSCODER_B))) {
 + DRM_DEBUG_DRIVER(PCH transcoder B underrun\n);
 + dev_priv-ignore_pch_fifo_underrun |= (1  TRANSCODER_B);
 + }
 +
 + if ((pch_iir  SDE_TRANSA_FIFO_UNDER) 
 + !(dev_priv-ignore_pch_fifo_underrun  (1  TRANSCODER_A))) {
 + DRM_DEBUG_DRIVER(PCH transcoder A underrun\n);
 + dev_priv-ignore_pch_fifo_underrun |= (1  TRANSCODER_A);
 + }
  }

  static void err_int_handler(struct drm_device *dev)
 @@ -684,6 +691,24 @@ static void serr_int_handler(struct drm_device *dev)
   if (serr_int  SERR_INT_POISON)
   DRM_ERROR(PCH poison interrupt\n);

 + if ((serr_int  SERR_INT_TRANS_A_FIFO_UNDERRUN) 
 + !(dev_priv-ignore_pch_fifo_underrun  (1  TRANSCODER_A))) {
 + DRM_ERROR(PCH transcoder A FIFO underrun\n);
 + dev_priv-ignore_pch_fifo_underrun |= (1  TRANSCODER_A);
 + }
 +
 + if ((serr_int  SERR_INT_TRANS_B_FIFO_UNDERRUN) 
 + !(dev_priv-ignore_pch_fifo_underrun  (1  TRANSCODER_B))) {
 + DRM_ERROR(PCH transcoder B FIFO underrun\n);
 + dev_priv-ignore_pch_fifo_underrun |= (1  TRANSCODER_B);
 + }
 +
 + if ((serr_int  SERR_INT_TRANS_C_FIFO_UNDERRUN) 
 + 

Re: [Intel-gfx] [PATCH 08/10] drm/i915: print PCH FIFO underrun interrupts

2013-02-14 Thread Daniel Vetter
On Thu, Feb 14, 2013 at 06:53:42PM -0200, Paulo Zanoni wrote:
 Hi
 
 2013/2/9 Daniel Vetter dan...@ffwll.ch:
  On Fri, Feb 08, 2013 at 05:35:19PM -0200, Paulo Zanoni wrote:
  From: Paulo Zanoni paulo.r.zan...@intel.com
 
  Also add an ignore bit that avoids printing the message in two
  cases:
- When the message is in fact expected.
- After we get the first message. In tihs case, we expect to get
  hundreds of consecutive messages, so we just ignore all the
  subsequent messages until the next crtc_enable.
 
  Signed-off-by: Paulo Zanoni paulo.r.zan...@intel.com
 
  Ah, here's the block underrun reporting stuff. You need to set up this
  infrastructure first, then enable the error interrupts. Otherwise a poor
  bloke will hit the irq strom in between these two patches in a bisect and
  die from a heart attack when looking at dmesg.
 
 Nope. This patch is also the patch that adds the dmesg message, so
 without this patch there is no message to ignore. Without this patch
 we still get the interrupts, but this shouldn't be a problem because
 we don't print anything and because of patch 5.
 
 
  Also, you update the ignore_bla from the irq handler, so this needs proper
  locking.
 Will fix.
 
  And I vote for the bikeshed to be moved into struct intel_crtc,
  e.g.
 
 It may be a little slightly slower, since we'll have to look for the
 crtc pointers on our structs. And on Haswell, checking which crtc is
 using the PCH transcoder will be more complicated. I'll try to think
 on a good solution.

Imo speed doesn't matter at all - we shouldn't ever get these in the
interrupt handler under normal conditions. And if we get too many of those
while modesetting, so that we suck away cpu time, it's probably best to
just disable all underrun reporting while doing a modeset.

 My initial idea was to actually group all the interrupt-related bits
 from dev_priv into an interrupt struct, and put the ignore_fifo bits
 there.
 
 
  struct intel_crtc {
  ...
 
  struct spinlock underrun_lock;
  int underrun_reporting_enabled;
  }
 
  Then smash a little helper into every crtc_enable/disable function. Aside:
  you need to use the spin_lock_irqsafe/restore functions in the irq handler
  (and for safety also in the helpers).  Another curious question: Why do we
  need separate ignore bits for the cpu and the pch?
 
 Because: (i) sometimes we get errors from one but not from the other;
 (ii) during pipe/transcoder disable we only want to ignore the PCH
 underruns, not the CPU underruns; (iii) on Haswell, there's no 1:1
 mapping between CPU pipe and PCH transcoder.

Ok, I see your aim with separate underrun reporting disables for pch/cpu.
But I also fear that we'll have tons of fun with just enabling the
underrun interrupts once the pipe is up, so a fine-grained report
disabling scheme sounds a bit like overkill. At least until we've fixed
the first set of big bugs.

The other thing is that I think we should just disable the interrupts when
we expect them (modeset) to avoid blowing through too much cpu time. So
having just one knob for everything sounds simpler.

Wrt Haswell pch interrupts: Either loop through the crtc list and check
-pch_encoder or check the DDI E port. The former shouldn't be a locking
issue as long as you grab the right irqsafe spinlocks first and check
whether reporting is enabled, since locks serve as barriers, too.

The reason for all this can we keep this generic bikeshed is that I'd
like to enable underrun reporting for i9xx/vlv, too. So having a bit of
abstraction would help.
-Daniel

 
  -Daniel
 
  ---
   drivers/gpu/drm/i915/i915_drv.h  |3 +++
   drivers/gpu/drm/i915/i915_irq.c  |   37 
  +-
   drivers/gpu/drm/i915/i915_reg.h  |7 +--
   drivers/gpu/drm/i915/intel_display.c |   14 -
   4 files changed, 53 insertions(+), 8 deletions(-)
 
  diff --git a/drivers/gpu/drm/i915/i915_drv.h 
  b/drivers/gpu/drm/i915/i915_drv.h
  index 08c5def..e96d75e 100644
  --- a/drivers/gpu/drm/i915/i915_drv.h
  +++ b/drivers/gpu/drm/i915/i915_drv.h
  @@ -909,6 +909,9 @@ typedef struct drm_i915_private {
struct work_struct hotplug_work;
bool enable_hotplug_processing;
 
  + /* Bit 0: PCH transcoder A and so on. */
  + u8 ignore_pch_fifo_underrun;
  +
int num_pipe;
int num_pch_pll;
 
  diff --git a/drivers/gpu/drm/i915/i915_irq.c 
  b/drivers/gpu/drm/i915/i915_irq.c
  index 703a08a..7497589 100644
  --- a/drivers/gpu/drm/i915/i915_irq.c
  +++ b/drivers/gpu/drm/i915/i915_irq.c
  @@ -659,10 +659,17 @@ static void ibx_irq_handler(struct drm_device *dev, 
  u32 pch_iir)
if (pch_iir  (SDE_TRANSB_CRC_ERR | SDE_TRANSA_CRC_ERR))
DRM_DEBUG_DRIVER(PCH transcoder CRC error interrupt\n);
 
  - if (pch_iir  SDE_TRANSB_FIFO_UNDER)
  - DRM_DEBUG_DRIVER(PCH transcoder B underrun interrupt\n);
  - if (pch_iir  SDE_TRANSA_FIFO_UNDER)
  - 

Re: [Intel-gfx] [PATCH 08/10] drm/i915: print PCH FIFO underrun interrupts

2013-02-14 Thread Paulo Zanoni
Hi

2013/2/14 Daniel Vetter dan...@ffwll.ch:
 On Thu, Feb 14, 2013 at 06:53:42PM -0200, Paulo Zanoni wrote:
 Hi

 2013/2/9 Daniel Vetter dan...@ffwll.ch:
  On Fri, Feb 08, 2013 at 05:35:19PM -0200, Paulo Zanoni wrote:
  From: Paulo Zanoni paulo.r.zan...@intel.com
 
  Also add an ignore bit that avoids printing the message in two
  cases:
- When the message is in fact expected.
- After we get the first message. In tihs case, we expect to get
  hundreds of consecutive messages, so we just ignore all the
  subsequent messages until the next crtc_enable.
 
  Signed-off-by: Paulo Zanoni paulo.r.zan...@intel.com
 
  Ah, here's the block underrun reporting stuff. You need to set up this
  infrastructure first, then enable the error interrupts. Otherwise a poor
  bloke will hit the irq strom in between these two patches in a bisect and
  die from a heart attack when looking at dmesg.

 Nope. This patch is also the patch that adds the dmesg message, so
 without this patch there is no message to ignore. Without this patch
 we still get the interrupts, but this shouldn't be a problem because
 we don't print anything and because of patch 5.

 
  Also, you update the ignore_bla from the irq handler, so this needs proper
  locking.
 Will fix.

  And I vote for the bikeshed to be moved into struct intel_crtc,
  e.g.

 It may be a little slightly slower, since we'll have to look for the
 crtc pointers on our structs. And on Haswell, checking which crtc is
 using the PCH transcoder will be more complicated. I'll try to think
 on a good solution.

 Imo speed doesn't matter at all - we shouldn't ever get these in the
 interrupt handler under normal conditions.

Nope. We get hundreds of interrupts at every crtc_disable. We are
*ignoring* them (by not printing anything), but we're still receiving
the interrupts (so we run the irq handler every time).

 And if we get too many of those
 while modesetting, so that we suck away cpu time, it's probably best to
 just disable all underrun reporting while doing a modeset.

With the current code I didn't notice and slowdowns, but didn't really
measure anything. Do you mean disable all underrun reporting (aka
don't print messages but still get the interrupts) or do you mean
disable all the interrupts (aka don't run the irq handler)?

The problem with disabling the interrupts is that you can't just
disable the PCH FIFO underrun interrupts. You have to disable all
the SERR interrupts, so you may lose other possible error messages.
Same thing with the CPU on IVB/HSW.


 My initial idea was to actually group all the interrupt-related bits
 from dev_priv into an interrupt struct, and put the ignore_fifo bits
 there.

 
  struct intel_crtc {
  ...
 
  struct spinlock underrun_lock;
  int underrun_reporting_enabled;
  }
 
  Then smash a little helper into every crtc_enable/disable function. Aside:
  you need to use the spin_lock_irqsafe/restore functions in the irq handler
  (and for safety also in the helpers).  Another curious question: Why do we
  need separate ignore bits for the cpu and the pch?

 Because: (i) sometimes we get errors from one but not from the other;
 (ii) during pipe/transcoder disable we only want to ignore the PCH
 underruns, not the CPU underruns; (iii) on Haswell, there's no 1:1
 mapping between CPU pipe and PCH transcoder.

 Ok, I see your aim with separate underrun reporting disables for pch/cpu.
 But I also fear that we'll have tons of fun with just enabling the
 underrun interrupts once the pipe is up, so a fine-grained report
 disabling scheme sounds a bit like overkill. At least until we've fixed
 the first set of big bugs.

What do you mean by tons of fun? As soon as we get the error
interrupt again we enable the ignore bit, so we'll see at most 1
message per mode set per pipe/transcoder.


 The other thing is that I think we should just disable the interrupts when
 we expect them (modeset) to avoid blowing through too much cpu time. So
 having just one knob for everything sounds simpler.

You mean definitely *disable* the interrupts? We can't just disable
the PCH FIFO underrun interrupts, we need to completely disable SERR,
which in turn disable all the other possible error messages (e.g.,
Poison, the other FIFO underruns from all the other pipes and also the
other error interrupts we're currently ignoring). Same thing with the
CPU FIFO underruns on IVB/Haswell: we need to disable GEN7_ERR_INT, so
we disable all the other interrupts it can generate.


 Wrt Haswell pch interrupts: Either loop through the crtc list and check
 -pch_encoder or check the DDI E port. The former shouldn't be a locking
 issue as long as you grab the right irqsafe spinlocks first and check
 whether reporting is enabled, since locks serve as barriers, too.

 The reason for all this can we keep this generic bikeshed is that I'd
 like to enable underrun reporting for i9xx/vlv, too. So having a bit of
 abstraction would help.

I don't understand how 

Re: [Intel-gfx] [PATCH 08/10] drm/i915: print PCH FIFO underrun interrupts

2013-02-09 Thread Daniel Vetter
On Fri, Feb 08, 2013 at 05:35:19PM -0200, Paulo Zanoni wrote:
 From: Paulo Zanoni paulo.r.zan...@intel.com
 
 Also add an ignore bit that avoids printing the message in two
 cases:
   - When the message is in fact expected.
   - After we get the first message. In tihs case, we expect to get
 hundreds of consecutive messages, so we just ignore all the
 subsequent messages until the next crtc_enable.
 
 Signed-off-by: Paulo Zanoni paulo.r.zan...@intel.com

Ah, here's the block underrun reporting stuff. You need to set up this
infrastructure first, then enable the error interrupts. Otherwise a poor
bloke will hit the irq strom in between these two patches in a bisect and
die from a heart attack when looking at dmesg.

Also, you update the ignore_bla from the irq handler, so this needs proper
locking. And I vote for the bikeshed to be moved into struct intel_crtc,
e.g.

struct intel_crtc {
...

struct spinlock underrun_lock;
int underrun_reporting_enabled;
}

Then smash a little helper into every crtc_enable/disable function. Aside:
you need to use the spin_lock_irqsafe/restore functions in the irq handler
(and for safety also in the helpers).  Another curious question: Why do we
need separate ignore bits for the cpu and the pch?
-Daniel

 ---
  drivers/gpu/drm/i915/i915_drv.h  |3 +++
  drivers/gpu/drm/i915/i915_irq.c  |   37 
 +-
  drivers/gpu/drm/i915/i915_reg.h  |7 +--
  drivers/gpu/drm/i915/intel_display.c |   14 -
  4 files changed, 53 insertions(+), 8 deletions(-)
 
 diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
 index 08c5def..e96d75e 100644
 --- a/drivers/gpu/drm/i915/i915_drv.h
 +++ b/drivers/gpu/drm/i915/i915_drv.h
 @@ -909,6 +909,9 @@ typedef struct drm_i915_private {
   struct work_struct hotplug_work;
   bool enable_hotplug_processing;
  
 + /* Bit 0: PCH transcoder A and so on. */
 + u8 ignore_pch_fifo_underrun;
 +
   int num_pipe;
   int num_pch_pll;
  
 diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
 index 703a08a..7497589 100644
 --- a/drivers/gpu/drm/i915/i915_irq.c
 +++ b/drivers/gpu/drm/i915/i915_irq.c
 @@ -659,10 +659,17 @@ static void ibx_irq_handler(struct drm_device *dev, u32 
 pch_iir)
   if (pch_iir  (SDE_TRANSB_CRC_ERR | SDE_TRANSA_CRC_ERR))
   DRM_DEBUG_DRIVER(PCH transcoder CRC error interrupt\n);
  
 - if (pch_iir  SDE_TRANSB_FIFO_UNDER)
 - DRM_DEBUG_DRIVER(PCH transcoder B underrun interrupt\n);
 - if (pch_iir  SDE_TRANSA_FIFO_UNDER)
 - DRM_DEBUG_DRIVER(PCH transcoder A underrun interrupt\n);
 + if ((pch_iir  SDE_TRANSB_FIFO_UNDER) 
 + !(dev_priv-ignore_pch_fifo_underrun  (1  TRANSCODER_B))) {
 + DRM_DEBUG_DRIVER(PCH transcoder B underrun\n);
 + dev_priv-ignore_pch_fifo_underrun |= (1  TRANSCODER_B);
 + }
 +
 + if ((pch_iir  SDE_TRANSA_FIFO_UNDER) 
 + !(dev_priv-ignore_pch_fifo_underrun  (1  TRANSCODER_A))) {
 + DRM_DEBUG_DRIVER(PCH transcoder A underrun\n);
 + dev_priv-ignore_pch_fifo_underrun |= (1  TRANSCODER_A);
 + }
  }
  
  static void err_int_handler(struct drm_device *dev)
 @@ -684,6 +691,24 @@ static void serr_int_handler(struct drm_device *dev)
   if (serr_int  SERR_INT_POISON)
   DRM_ERROR(PCH poison interrupt\n);
  
 + if ((serr_int  SERR_INT_TRANS_A_FIFO_UNDERRUN) 
 + !(dev_priv-ignore_pch_fifo_underrun  (1  TRANSCODER_A))) {
 + DRM_ERROR(PCH transcoder A FIFO underrun\n);
 + dev_priv-ignore_pch_fifo_underrun |= (1  TRANSCODER_A);
 + }
 +
 + if ((serr_int  SERR_INT_TRANS_B_FIFO_UNDERRUN) 
 + !(dev_priv-ignore_pch_fifo_underrun  (1  TRANSCODER_B))) {
 + DRM_ERROR(PCH transcoder B FIFO underrun\n);
 + dev_priv-ignore_pch_fifo_underrun |= (1  TRANSCODER_B);
 + }
 +
 + if ((serr_int  SERR_INT_TRANS_C_FIFO_UNDERRUN) 
 + !(dev_priv-ignore_pch_fifo_underrun  (1  TRANSCODER_C))) {
 + DRM_ERROR(PCH transcoder C FIFO underrun\n);
 + dev_priv-ignore_pch_fifo_underrun |= (1  TRANSCODER_C);
 + }
 +
   I915_WRITE(SERR_INT, serr_int);
  }
  
 @@ -2000,7 +2025,9 @@ static void ibx_irq_postinstall(struct drm_device *dev)
   mask = SDE_HOTPLUG_MASK |
  SDE_GMBUS |
  SDE_AUX_MASK |
 -SDE_POISON;
 +SDE_POISON |
 +SDE_TRANSB_FIFO_UNDER |
 +SDE_TRANSA_FIFO_UNDER;
   } else {
   mask = SDE_HOTPLUG_MASK_CPT |
  SDE_GMBUS_CPT |
 diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
 index f22e27d..d565bd7 100644
 --- a/drivers/gpu/drm/i915/i915_reg.h
 +++ b/drivers/gpu/drm/i915/i915_reg.h
 @@ -3554,8 +3554,11 @@
  #define SDEIIR  0xc4008
  

[Intel-gfx] [PATCH 08/10] drm/i915: print PCH FIFO underrun interrupts

2013-02-08 Thread Paulo Zanoni
From: Paulo Zanoni paulo.r.zan...@intel.com

Also add an ignore bit that avoids printing the message in two
cases:
  - When the message is in fact expected.
  - After we get the first message. In tihs case, we expect to get
hundreds of consecutive messages, so we just ignore all the
subsequent messages until the next crtc_enable.

Signed-off-by: Paulo Zanoni paulo.r.zan...@intel.com
---
 drivers/gpu/drm/i915/i915_drv.h  |3 +++
 drivers/gpu/drm/i915/i915_irq.c  |   37 +-
 drivers/gpu/drm/i915/i915_reg.h  |7 +--
 drivers/gpu/drm/i915/intel_display.c |   14 -
 4 files changed, 53 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 08c5def..e96d75e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -909,6 +909,9 @@ typedef struct drm_i915_private {
struct work_struct hotplug_work;
bool enable_hotplug_processing;
 
+   /* Bit 0: PCH transcoder A and so on. */
+   u8 ignore_pch_fifo_underrun;
+
int num_pipe;
int num_pch_pll;
 
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 703a08a..7497589 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -659,10 +659,17 @@ static void ibx_irq_handler(struct drm_device *dev, u32 
pch_iir)
if (pch_iir  (SDE_TRANSB_CRC_ERR | SDE_TRANSA_CRC_ERR))
DRM_DEBUG_DRIVER(PCH transcoder CRC error interrupt\n);
 
-   if (pch_iir  SDE_TRANSB_FIFO_UNDER)
-   DRM_DEBUG_DRIVER(PCH transcoder B underrun interrupt\n);
-   if (pch_iir  SDE_TRANSA_FIFO_UNDER)
-   DRM_DEBUG_DRIVER(PCH transcoder A underrun interrupt\n);
+   if ((pch_iir  SDE_TRANSB_FIFO_UNDER) 
+   !(dev_priv-ignore_pch_fifo_underrun  (1  TRANSCODER_B))) {
+   DRM_DEBUG_DRIVER(PCH transcoder B underrun\n);
+   dev_priv-ignore_pch_fifo_underrun |= (1  TRANSCODER_B);
+   }
+
+   if ((pch_iir  SDE_TRANSA_FIFO_UNDER) 
+   !(dev_priv-ignore_pch_fifo_underrun  (1  TRANSCODER_A))) {
+   DRM_DEBUG_DRIVER(PCH transcoder A underrun\n);
+   dev_priv-ignore_pch_fifo_underrun |= (1  TRANSCODER_A);
+   }
 }
 
 static void err_int_handler(struct drm_device *dev)
@@ -684,6 +691,24 @@ static void serr_int_handler(struct drm_device *dev)
if (serr_int  SERR_INT_POISON)
DRM_ERROR(PCH poison interrupt\n);
 
+   if ((serr_int  SERR_INT_TRANS_A_FIFO_UNDERRUN) 
+   !(dev_priv-ignore_pch_fifo_underrun  (1  TRANSCODER_A))) {
+   DRM_ERROR(PCH transcoder A FIFO underrun\n);
+   dev_priv-ignore_pch_fifo_underrun |= (1  TRANSCODER_A);
+   }
+
+   if ((serr_int  SERR_INT_TRANS_B_FIFO_UNDERRUN) 
+   !(dev_priv-ignore_pch_fifo_underrun  (1  TRANSCODER_B))) {
+   DRM_ERROR(PCH transcoder B FIFO underrun\n);
+   dev_priv-ignore_pch_fifo_underrun |= (1  TRANSCODER_B);
+   }
+
+   if ((serr_int  SERR_INT_TRANS_C_FIFO_UNDERRUN) 
+   !(dev_priv-ignore_pch_fifo_underrun  (1  TRANSCODER_C))) {
+   DRM_ERROR(PCH transcoder C FIFO underrun\n);
+   dev_priv-ignore_pch_fifo_underrun |= (1  TRANSCODER_C);
+   }
+
I915_WRITE(SERR_INT, serr_int);
 }
 
@@ -2000,7 +2025,9 @@ static void ibx_irq_postinstall(struct drm_device *dev)
mask = SDE_HOTPLUG_MASK |
   SDE_GMBUS |
   SDE_AUX_MASK |
-  SDE_POISON;
+  SDE_POISON |
+  SDE_TRANSB_FIFO_UNDER |
+  SDE_TRANSA_FIFO_UNDER;
} else {
mask = SDE_HOTPLUG_MASK_CPT |
   SDE_GMBUS_CPT |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index f22e27d..d565bd7 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3554,8 +3554,11 @@
 #define SDEIIR  0xc4008
 #define SDEIER  0xc400c
 
-#define SERR_INT   0xc4040
-#define  SERR_INT_POISON   (1  31)
+#define SERR_INT   0xc4040
+#define  SERR_INT_POISON   (1  31)
+#define  SERR_INT_TRANS_C_FIFO_UNDERRUN(1  6)
+#define  SERR_INT_TRANS_B_FIFO_UNDERRUN(1  3)
+#define  SERR_INT_TRANS_A_FIFO_UNDERRUN(1  0)
 
 /* digital port hotplug */
 #define PCH_PORT_HOTPLUG0xc4030/* SHOTPLUG_CTL */
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index d75c6a0..67bfb58 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3274,6 +3274,9 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
return;
 
intel_crtc-active = true;
+
+   dev_priv-ignore_pch_fifo_underrun = ~(1  pipe);
+