Code: Select all
cat /proc/interrupts
CPU0 CPU1 CPU2 CPU3
0: 121 0 1 0 IO-APIC-edge timer
1: 0 0 2 0 IO-APIC-edge i8042
8: 0 0 1 0 IO-APIC-edge rtc0
9: 0 0 0 0 IO-APIC-fasteoi acpi
12: 0 0 4 0 IO-APIC-edge i8042
18: 0 1 1728 7 IO-APIC-fasteoi radeon
43: 4 4 22211 37 PCI-MSI-edge ahci
44: 0 0 587 2 PCI-MSI-edge pata_atiixp
45: 0 0 31 0 PCI-MSI-edge eth0
46: 0 0 0 0 PCI-MSI-edge eth1
47: 0 0 0 0 PCI-MSI-edge ehci_hcd:usb1
48: 0 0 195 1 PCI-MSI-edge ehci_hcd:usb2
49: 0 0 0 0 PCI-MSI-edge ohci_hcd:usb3
50: 0 0 0 0 PCI-MSI-edge ohci_hcd:usb4
51: 0 0 462 3 PCI-MSI-edge ohci_hcd:usb5
52: 0 0 0 0 PCI-MSI-edge ohci_hcd:usb6
53: 0 0 487 0 PCI-MSI-edge snd_hda_intel
NMI: 0 0 0 0 Non-maskable interrupts
LOC: 502 16819 36710 21430 Local timer interrupts
SPU: 0 0 0 0 Spurious interrupts
PMI: 0 0 0 0 Performance monitoring interrupts
IWI: 0 0 0 0 IRQ work interrupts
RES: 18444 18765 15323 18871 Rescheduling interrupts
CAL: 123 156 69 153 Function call interrupts
TLB: 784 638 588 800 TLB shootdowns
ERR: 0
MIS: 0
Code: Select all
diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c
index 04ee1e2..49bf4f8 100644
--- a/arch/x86/kernel/quirks.c
+++ b/arch/x86/kernel/quirks.c
@@ -497,6 +497,8 @@ void force_hpet_resume(void)
}
}
+/* XXX: should add EPP/ECP parport as well.. */
+#if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE)
/*
* HPET MSI on some boards (ATI SB700/SB800) has side effect on
* floppy DMA. Disable HPET MSI on such platforms.
@@ -511,6 +513,7 @@ static void force_disable_hpet_msi(struct pci_dev *unused)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS,
force_disable_hpet_msi);
+#endif
#endif
diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c
index 24e5105..cc222a7 100644
--- a/drivers/ata/pata_atiixp.c
+++ b/drivers/ata/pata_atiixp.c
@@ -278,7 +278,15 @@ static int atiixp_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
.port_ops = &atiixp_port_ops
};
const struct ata_port_info *ppi[] = { &info, &info };
-
+ u8 tmp8, mask;
+
+ pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
+ mask = (1 << 2) | (1 << 0);
+
+ /* Both channels in native mode? */
+ if ((tmp8 & mask) == mask)
+ pci_enable_msi(pdev);
+
return ata_pci_bmdma_init_one(pdev, ppi, &atiixp_sht, NULL,
ATA_HOST_PARALLEL_SCAN);
}
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index f6c31fa..e98a885 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2581,16 +2581,44 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
PCI_DEVICE_ID_TIGON3_5715S,
quirk_msi_intx_disable_bug);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4390,
- quirk_msi_intx_disable_ati_bug);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4391,
- quirk_msi_intx_disable_ati_bug);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4392,
- quirk_msi_intx_disable_ati_bug);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4393,
- quirk_msi_intx_disable_ati_bug);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4394,
- quirk_msi_intx_disable_ati_bug);
+/* Enable MSI capability on SB7x0 SATA */
+static void quirk_amd_sb700_sata_enable_msi_capability(struct pci_dev *dev)
+{
+ u8 tmp;
+
+ pci_read_config_byte(dev, 0x34, &tmp);
+
+ /* Is D3 enabled or MSI disabled? */
+ if (tmp != 0x50) {
+ pci_read_config_byte(dev, 0x40, &tmp);
+ pci_write_config_byte(dev, 0x40, tmp|1);
+
+ /* Set next pointer to MSI cap ignoring power management cap, see RPR 7.11 */
+ pci_write_config_byte(dev, 0x34, 0x50);
+
+ pci_write_config_byte(dev, 0x40, tmp);
+ dev_info(&dev->dev, "Enabled SATA MSI capability and disabled D3 power management capability\n");
+ }
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x4390, quirk_amd_sb700_sata_enable_msi_capability);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_ATI, 0x4390, quirk_amd_sb700_sata_enable_msi_capability);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4390, quirk_msi_intx_disable_ati_bug);
+
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x4391, quirk_amd_sb700_sata_enable_msi_capability);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_ATI, 0x4391, quirk_amd_sb700_sata_enable_msi_capability);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4391, quirk_msi_intx_disable_ati_bug);
+
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x4392, quirk_amd_sb700_sata_enable_msi_capability);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_ATI, 0x4392, quirk_amd_sb700_sata_enable_msi_capability);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4392, quirk_msi_intx_disable_ati_bug);
+
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x4393, quirk_amd_sb700_sata_enable_msi_capability);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_ATI, 0x4393, quirk_amd_sb700_sata_enable_msi_capability);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4393, quirk_msi_intx_disable_ati_bug);
+
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x4394, quirk_amd_sb700_sata_enable_msi_capability);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_ATI, 0x4394, quirk_amd_sb700_sata_enable_msi_capability);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4394, quirk_msi_intx_disable_ati_bug);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4373,
quirk_msi_intx_disable_bug);
@@ -2599,6 +2627,99 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4374,
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4375,
quirk_msi_intx_disable_bug);
+/* Enable MSI capability on SB7x0 PCIB */
+static void quirk_amd_sb700_pcib_enable_msi_capability(struct pci_dev *dev)
+{
+ u8 tmp;
+
+ pci_read_config_byte(dev, 0x40, &tmp);
+
+ /* Is MSI disabled ? */
+ if ((tmp & (1 << 3)) == 0) {
+ pci_write_config_byte(dev, 0x40, tmp | (1 << 3));
+ dev_info(&dev->dev, "Enabled PCIB MSI capability\n");
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, 0x4384, quirk_amd_sb700_pcib_enable_msi_capability);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_ATI, 0x4384, quirk_amd_sb700_pcib_enable_msi_capability);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4384, quirk_msi_intx_disable_ati_bug);
+
+/* Enable MSI capability on SB7x0 Azalia */
+static void quirk_amd_sb700_azalia_enable_msi_capability(struct pci_dev *dev)
+{
+ u8 tmp;
+
+ pci_read_config_byte(dev, 0x45, &tmp);
+
+ /* Is MSI disabled ? */
+ if ((tmp & 1) == 0) {
+ pci_write_config_byte(dev, 0x45, tmp | 1);
+ dev_info(&dev->dev, "Enabled Azalia MSI capability\n");
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, 0x4383, quirk_amd_sb700_azalia_enable_msi_capability);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_ATI, 0x4383, quirk_amd_sb700_azalia_enable_msi_capability);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4383, quirk_msi_intx_disable_ati_bug);
+
+/* Enable MSI capability on SB7x0 OHCI */
+static void quirk_amd_sb700_ohci_enable_msi_capability(struct pci_dev *dev)
+{
+ u8 tmp;
+
+ pci_read_config_byte(dev, 0x41, &tmp);
+
+ /* Is MSI disabled ? */
+ if ((tmp & 3) != 0) {
+ pci_write_config_byte(dev, 0x41, tmp & ~3);
+ dev_info(&dev->dev, "Enabled OHCI0/1 MSI capability\n");
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, 0x4397, quirk_amd_sb700_ohci_enable_msi_capability);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_ATI, 0x4397, quirk_amd_sb700_ohci_enable_msi_capability);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4397, quirk_msi_intx_disable_ati_bug);
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, 0x4398, quirk_amd_sb700_ohci_enable_msi_capability);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_ATI, 0x4398, quirk_amd_sb700_ohci_enable_msi_capability);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4398, quirk_msi_intx_disable_ati_bug);
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, 0x4399, quirk_amd_sb700_ohci_enable_msi_capability);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_ATI, 0x4399, quirk_amd_sb700_ohci_enable_msi_capability);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4399, quirk_msi_intx_disable_ati_bug);
+
+/* Enable MSI capability on SB7x0 EHCI */
+static void quirk_amd_sb700_ehci_enable_msi_capability(struct pci_dev *dev)
+{
+ u8 tmp;
+
+ pci_read_config_byte(dev, 0x50, &tmp);
+
+ /* Is MSI disabled ? */
+ if ((tmp & (1 << 6)) != 0) {
+ pci_write_config_byte(dev, 0x50, tmp & ~(1 << 6));
+ dev_info(&dev->dev, "Enabled EHCI MSI capability\n");
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, 0x4396, quirk_amd_sb700_ehci_enable_msi_capability);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_ATI, 0x4396, quirk_amd_sb700_ehci_enable_msi_capability);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4396, quirk_msi_intx_disable_ati_bug);
+
+static void quirk_amd_ide_native_mode(struct pci_dev *pdev)
+{
+ /* set SBX00/Hudson-2 IDE to native mode */
+ const u8 mask = 1 | (1 << 2);
+ u8 tmp;
+
+ pci_read_config_byte(pdev, 0x9, &tmp);
+ if ((tmp & mask) != mask) {
+ pci_write_config_byte(pdev, 0x9, tmp | mask);
+ dev_info(&pdev->dev, "set both IDE channels to native mode\n");
+ }
+}
+
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x439c, quirk_amd_ide_native_mode);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_ATI, 0x439c, quirk_amd_ide_native_mode);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x439c, quirk_msi_intx_disable_ati_bug);
+
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x1062,
quirk_msi_intx_disable_bug);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x1063,
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 6bd299e..e12e800 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -352,12 +352,19 @@ static const struct pci_device_id pci_ids [] = { {
};
MODULE_DEVICE_TABLE(pci, pci_ids);
+static int ehci_hcd_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
+{
+ pci_enable_msi(dev);
+ return usb_hcd_pci_probe(dev, id);
+}
+
/* pci driver glue; this is a "new style" PCI driver module */
static struct pci_driver ehci_pci_driver = {
.name = (char *) hcd_name,
.id_table = pci_ids,
- .probe = usb_hcd_pci_probe,
+ .probe = ehci_hcd_pci_probe,
.remove = usb_hcd_pci_remove,
.shutdown = usb_hcd_pci_shutdown,
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index ec337c2..82117cb 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -28,6 +28,12 @@
static const char hcd_name[] = "ohci-pci";
+static int ohci_hcd_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
+{
+ pci_enable_msi(dev);
+ return usb_hcd_pci_probe(dev, id);
+}
/*-------------------------------------------------------------------------*/
@@ -285,7 +291,7 @@ static struct pci_driver ohci_pci_driver = {
.name = (char *) hcd_name,
.id_table = pci_ids,
- .probe = usb_hcd_pci_probe,
+ .probe = ohci_hcd_pci_probe,
.remove = usb_hcd_pci_remove,
.shutdown = usb_hcd_pci_shutdown,
(Update) Warning, the following patch for not disabling MSI for HPET shouldn't be used if you have DMA enabled devices on the LPC bus (eg. floppy drive, maybe also flashrom fro reading/writing to SPI flash rom?) due to a chipset bug. For me it seems to work nicely, but I didn't test flash rom and I don't have a floppy attached. You'll get another line in /proc/interrups:
Code: Select all
40: 64775 0 0 0 HPET_MSI-edge hpet2
The patch: (Update) Removed and incorporated into main patch
(Update 2) Modified the patch to a) switch the IDE controller to native mode and B) let it use MSI, as well. (I should note that simply switching IDE controller from legacy mode to native mode at this stage will only reliably work when using MSI, as my bios doesn't properly assign an IRQ for it. So it won't work in PIC mode unless the IRQ line register is properly set up - as far as I understood. It worked in APIC mode though, as Linux seems to correctly choose the proper irq, even though at least the mp table didn't contain routing infos for it. I didn't understand the acpi dump though...)
(Update 3) Includes roarinelk's changes (thx!) and SATA bits.
(Update 4) Patch against Linux 3.12.5.





