forked from luck/tmp_suning_uos_patched
PCI: Add quirk for still enabled interrupts on Intel Sandy Bridge GPUs
Some BIOS implementations leave the Intel GPU interrupts enabled, even though no one is handling them (f.e. i915 driver is never loaded). Additionally the interrupt destination is not set up properly and the interrupt ends up -somewhere-. These spurious interrupts are "sticky" and the kernel disables the (shared) interrupt line after 100.000+ generated interrupts. Fix it by disabling the still enabled interrupts. This resolves crashes often seen on monitor unplug. Tested on the following boards: - Intel DH61CR: Affected - Intel DH67BL: Affected - Intel S1200KP server board: Affected - Asus P8H61-M LE: Affected, but system does not crash. Probably the IRQ ends up somewhere unnoticed. According to reports on the net, the Intel DH61WW board is also affected. Many thanks to Jesse Barnes from Intel for helping with the register configuration and to Intel in general for providing public hardware documentation. Signed-off-by: Thomas Jarosch <thomas.jarosch@intra2net.com> Tested-by: Charlie Suffin <charlie.suffin@stratus.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
This commit is contained in:
parent
3209874a1d
commit
f67fd55fa9
@ -2924,6 +2924,40 @@ static void do_one_fixup_debug(void (*fn)(struct pci_dev *dev), struct pci_dev *
|
||||
duration);
|
||||
}
|
||||
|
||||
/*
|
||||
* Some BIOS implementations leave the Intel GPU interrupts enabled,
|
||||
* even though no one is handling them (f.e. i915 driver is never loaded).
|
||||
* Additionally the interrupt destination is not set up properly
|
||||
* and the interrupt ends up -somewhere-.
|
||||
*
|
||||
* These spurious interrupts are "sticky" and the kernel disables
|
||||
* the (shared) interrupt line after 100.000+ generated interrupts.
|
||||
*
|
||||
* Fix it by disabling the still enabled interrupts.
|
||||
* This resolves crashes often seen on monitor unplug.
|
||||
*/
|
||||
#define I915_DEIER_REG 0x4400c
|
||||
static void __devinit disable_igfx_irq(struct pci_dev *dev)
|
||||
{
|
||||
void __iomem *regs = pci_iomap(dev, 0, 0);
|
||||
if (regs == NULL) {
|
||||
dev_warn(&dev->dev, "igfx quirk: Can't iomap PCI device\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if any interrupt line is still enabled */
|
||||
if (readl(regs + I915_DEIER_REG) != 0) {
|
||||
dev_warn(&dev->dev, "BIOS left Intel GPU interrupts enabled; "
|
||||
"disabling\n");
|
||||
|
||||
writel(0, regs + I915_DEIER_REG);
|
||||
}
|
||||
|
||||
pci_iounmap(dev, regs);
|
||||
}
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0102, disable_igfx_irq);
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq);
|
||||
|
||||
static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
|
||||
struct pci_fixup *end)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user