From ab1f2cd08dd06af2de17df916e55814a772bb658 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Sat, 8 Mar 2014 20:18:23 +0100 Subject: [PATCH] intel_extreme: read and loop for new interrupts. Fix #9718. * MSI seems to trigger the need to loop: interrupts are not generated for bits set while we process. --- .../graphics/intel_extreme/intel_extreme.cpp | 49 ++++++++++--------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp index 5adb4b3f4c..f9dddbbfce 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp @@ -78,36 +78,41 @@ static int32 intel_interrupt_handler(void* data) { intel_info &info = *(intel_info*)data; - - uint16 identity = read16(info, find_reg(info, INTEL_INTERRUPT_IDENTITY)); + uint32 reg = find_reg(info, INTEL_INTERRUPT_IDENTITY); + uint16 identity = read16(info, reg); if (identity == 0) return B_UNHANDLED_INTERRUPT; int32 handled = B_HANDLED_INTERRUPT; - // TODO: verify that these aren't actually the same - bool hasPCH = info.device_type.HasPlatformControlHub(); - uint16 mask = hasPCH ? PCH_INTERRUPT_VBLANK_PIPEA : INTERRUPT_VBLANK_PIPEA; - if ((identity & mask) != 0) { - handled = release_vblank_sem(info); + while (identity != 0) { - // make sure we'll get another one of those - write32(info, INTEL_DISPLAY_A_PIPE_STATUS, - DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED); + // TODO: verify that these aren't actually the same + bool hasPCH = info.device_type.HasPlatformControlHub(); + uint16 mask = hasPCH ? PCH_INTERRUPT_VBLANK_PIPEA + : INTERRUPT_VBLANK_PIPEA; + if ((identity & mask) != 0) { + handled = release_vblank_sem(info); + + // make sure we'll get another one of those + write32(info, INTEL_DISPLAY_A_PIPE_STATUS, + DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED); + } + + mask = hasPCH ? PCH_INTERRUPT_VBLANK_PIPEB : INTERRUPT_VBLANK_PIPEB; + if ((identity & mask) != 0) { + handled = release_vblank_sem(info); + + // make sure we'll get another one of those + write32(info, INTEL_DISPLAY_B_PIPE_STATUS, + DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED); + } + + // setting the bit clears it! + write16(info, reg, identity); + identity = read16(info, reg); } - mask = hasPCH ? PCH_INTERRUPT_VBLANK_PIPEB : INTERRUPT_VBLANK_PIPEB; - if ((identity & mask) != 0) { - handled = release_vblank_sem(info); - - // make sure we'll get another one of those - write32(info, INTEL_DISPLAY_B_PIPE_STATUS, - DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED); - } - - // setting the bit clears it! - write16(info, find_reg(info, INTEL_INTERRUPT_IDENTITY), identity); - return handled; }