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.
This commit is contained in:
Jérôme Duval
2014-03-18 21:43:31 +01:00
parent 4fc7f247a8
commit ab1f2cd08d
@@ -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;
}