linux/drivers/gpu/drm/i915
Paulo Zanoni 44498aea29 drm/i915: also disable south interrupts when handling them
From the docs:

  "IIR can queue up to two interrupt events. When the IIR is cleared,
  it will set itself again after one clock if a second event was
  stored."

  "Only the rising edge of the PCH Display interrupt will cause the
  North Display IIR (DEIIR) PCH Display Interrupt even bit to be set,
  so all PCH Display Interrupts, including back to back interrupts,
  must be cleared before a new PCH Display interrupt can cause DEIIR
  to be set".

The current code works fine because we don't get many interrupts, but
if we enable the PCH FIFO underrun interrupts we'll start getting so
many interrupts that at some point new PCH interrupts won't cause
DEIIR to be set.

The initial implementation I tried was to turn the code that checks
SDEIIR into a loop, but we can still get interrupts even after the
loop is done (and before the irq handler finishes), so we have to
either disable the interrupts or mask them. In the end I concluded
that just disabling the PCH interrupts is enough, you don't even need
the loop, so this is what this patch implements. I've tested it and it
passes the 2 "PCH FIFO underrun interrupt storms" I can reproduce:
the "ironlake_crtc_disable" case and the "wrong watermarks" case.

In other words, here's how to reproduce the problem fixed by this
patch:
  1 - Enable PCH FIFO underrun interrupts (SERR_INT on SNB+)
  2 - Boot the machine
  3 - While booting we'll get tons of PCH FIFO underrun interrupts
  4 - Plug a new monitor
  5 - Run xrandr, notice it won't detect the new monitor
  6 - Read SDEIIR and notice it's not 0 while DEIIR is 0

Q: Can't we just clear DEIIR before SDEIIR?
A: It doesn't work. SDEIIR has to be completely cleared (including the
interrupts stored on its back queue) before it can flip DEIIR's bit to
1 again, and even while you're clearing it you'll be getting more and
more interrupts.

Q: Why does it work by just disabling+enabling the south interrupts?
A: Because when we re-enable them, if there's something on the SDEIIR
register (maybe an interrupt stored on the queue), the re-enabling
will make DEIIR's bit flip to 1, and since we'll already have
interrupts enabled we'll get another interrupt, then run our irq
handler again to process the "back" interrupts.

v2: Even bigger commit message, added code comments.

Note that this fixes missed dp aux irqs which have been reported for
3.9-rc1. This regression has been introduced by switching to
irq-driven dp aux transactions with

commit 9ee32fea5f
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
Date:   Sat Dec 1 13:53:48 2012 +0100

    drm/i915: irq-drive the dp aux communication

References: http://www.mail-archive.com/intel-gfx@lists.freedesktop.org/msg18588.html
References: https://lkml.org/lkml/2013/2/26/769
Tested-by: Imre Deak <imre.deak@intel.com>
Reported-by: Sedat Dilek <sedat.dilek@gmail.com>
Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
[danvet: Pimp commit message with references for the dp aux irq
timeout regression this fixes.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2013-03-05 20:06:22 +01:00
..
dvo_ch7xxx.c drm/i915/dvo-ch7xxx: fix get_hw_state 2012-10-12 10:59:11 +02:00
dvo_ch7017.c drm/i915/dvo: implement get_hw_state 2012-09-06 07:58:52 +02:00
dvo_ivch.c drm/i915/dvo: implement get_hw_state 2012-09-06 07:58:52 +02:00
dvo_ns2501.c drm/i915/dvo: implement get_hw_state 2012-09-06 07:58:52 +02:00
dvo_sil164.c drm/i915/dvo: implement get_hw_state 2012-09-06 07:58:52 +02:00
dvo_tfp410.c drm/i915/dvo: implement get_hw_state 2012-09-06 07:58:52 +02:00
dvo.h Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux 2012-10-03 23:29:23 -07:00
i915_debugfs.c drm/i915: Print the hw context status is debugfs 2013-02-20 00:21:48 +01:00
i915_dma.c i915: ignore lid open event when resuming 2013-02-14 00:47:51 +01:00
i915_drv.c drm/i915: enable irqs earlier when resuming 2013-03-05 10:21:36 +01:00
i915_drv.h drm/i915: Preserve the FDI line reversal override bit on CPT 2013-02-20 00:21:45 +01:00
i915_gem_context.c drm/i915/ctx: Remove bad invariant 2013-02-15 10:30:40 +01:00
i915_gem_debug.c UAPI: (Scripted) Convert #include "..." to #include <path/...> in drivers/gpu/ 2012-10-02 18:01:07 +01:00
i915_gem_dmabuf.c Merge tag 'drm-intel-next-2012-12-21' of git://people.freedesktop.org/~danvet/drm-intel into drm-next 2013-01-17 20:34:08 +10:00
i915_gem_evict.c drm/i915: Create a gtt structure 2013-01-17 22:33:56 +01:00
i915_gem_execbuffer.c Merge branch 'fbcon-locking-fixes' of ssh://people.freedesktop.org/~airlied/linux into drm-next 2013-02-08 12:10:18 +10:00
i915_gem_gtt.c drm/i915: Fix gen2 mappable calculations 2013-02-15 10:30:38 +01:00
i915_gem_stolen.c drm/i915: remove intel_gtt structure 2013-01-31 11:50:07 +01:00
i915_gem_tiling.c drm/i915: Create a gtt structure 2013-01-17 22:33:56 +01:00
i915_gem.c drm/i915: Use HAS_L3_GPU_CACHE in i915_gem_l3_remap 2013-02-20 00:21:47 +01:00
i915_ioc32.c UAPI: (Scripted) Convert #include "..." to #include <path/...> in drivers/gpu/ 2012-10-02 18:01:07 +01:00
i915_irq.c drm/i915: also disable south interrupts when handling them 2013-03-05 20:06:22 +01:00
i915_reg.h drm/i915: Implement pipe CSC based limited range RGB output 2013-02-20 00:21:49 +01:00
i915_suspend.c drm/i915: Introduce i915_vgacntrl_reg() 2013-01-31 11:50:12 +01:00
i915_sysfs.c drm/i915: fixup l3 parity sysfs access check 2012-12-05 19:10:20 +01:00
i915_trace_points.c
i915_trace.h drm/i915: Allow DRM_ROOT_ONLY|DRM_MASTER to submit privileged batchbuffers 2012-10-17 21:06:59 +02:00
i915_ums.c drm/i915: move DP save/restore into i915_ums.c 2013-01-31 11:50:04 +01:00
intel_acpi.c UAPI: (Scripted) Convert #include "..." to #include <path/...> in drivers/gpu/ 2012-10-02 18:01:07 +01:00
intel_bios.c Merge branch 'drm-next-3.8' of git://people.freedesktop.org/~agd5f/linux into drm-next 2012-12-10 20:03:58 +10:00
intel_bios.h UAPI: (Scripted) Convert #include "..." to #include <path/...> in drivers/gpu/ 2012-10-02 18:01:07 +01:00
intel_crt.c drm/i915: Preserve the FDI line reversal override bit on CPT 2013-02-20 00:21:45 +01:00
intel_ddi.c drm/i915: Fix missing variable initilization 2013-03-03 18:19:48 +01:00
intel_display.c DRM/i915: On G45 enable cursor plane briefly after enabling the display plane. 2013-03-04 17:22:07 +01:00
intel_dp.c drm/i915: wait_event_timeout's timeout is in jiffies 2013-03-03 18:35:51 +01:00
intel_drv.h drm/i915: Handle untiled planes when computing their offsets 2013-02-21 21:52:08 +01:00
intel_dvo.c Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux 2012-10-03 23:29:23 -07:00
intel_fb.c Merge tag 'drm-intel-next-2013-02-01' of git://people.freedesktop.org/~danvet/drm-intel into drm-next 2013-02-08 11:08:10 +10:00
intel_hdmi.c drm/i915: Revert hdmi HDP pin checks 2013-02-22 13:04:33 +01:00
intel_i2c.c drm/i915: GPIO/GMBUS registers need an offset on VLV 2013-01-24 23:45:03 +01:00
intel_lvds.c drm/i915: clean up panel fitter handling in lvds 2013-02-20 00:21:40 +01:00
intel_modes.c drm/i915: Add "Automatic" mode for the "Broadcast RGB" property 2013-01-20 13:09:44 +01:00
intel_opregion.c GPU/i915: Fix acpi_bus_get_device() check in drivers/gpu/drm/i915/intel_opregion.c 2013-02-01 11:01:50 +01:00
intel_overlay.c Merge tag 'drm-intel-next-2013-02-01' of git://people.freedesktop.org/~danvet/drm-intel into drm-next 2013-02-08 11:08:10 +10:00
intel_panel.c drm/i915: write backlight harder 2013-02-15 10:30:36 +01:00
intel_pm.c drm/i915: Increase the RC6p threshold. 2013-03-05 10:02:00 +01:00
intel_ringbuffer.c drm/i915: Fix PIPE_CONTROL DW/QW write through global GTT on IVB+ 2013-02-20 00:21:47 +01:00
intel_ringbuffer.h Merge tag 'drm-intel-next-2012-12-21' of git://people.freedesktop.org/~danvet/drm-intel into drm-next 2013-01-17 20:34:08 +10:00
intel_sdvo_regs.h drm/i915: clear the entire sdvo infoframe buffer 2012-10-24 15:12:48 +02:00
intel_sdvo.c drm/i915: Provide the quantization range in the AVI infoframe 2013-01-20 13:09:45 +01:00
intel_sprite.c drm/i915: Handle untiled planes when computing their offsets 2013-02-21 21:52:08 +01:00
intel_tv.c drm/i915: Return the real error code from intel_set_mode() 2012-12-20 21:09:55 +01:00
Makefile drm/i915: extract ums suspend/resume into i915_ums.c 2013-01-31 11:50:03 +01:00