diff mbox

pci: Reenable the AMD IOMMU if it's mysteriously vanished over suspend

Message ID 1285861108-24122-1-git-send-email-mjg@redhat.com (mailing list archive)
State Superseded, archived
Headers show

Commit Message

Matthew Garrett Sept. 30, 2010, 3:38 p.m. UTC
None
diff mbox

Patch

diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 89ed181..dcf9832 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2695,6 +2695,39 @@  DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832,
 #endif /*CONFIG_MMC_RICOH_MMC*/
 
 
+#ifdef CONFIG_AMD_IOMMU
+
+/* Some AMD BIOSes fail to reenable the iommu on resume */
+
+static void amd_iommu_reenable(struct pci_dev *dev)
+{
+	u32 ioc_feature_control;
+	struct pci_dev *iommu;
+
+	iommu = pci_get_device(PCI_VENDOR_ID_ATI, 0x5a23, NULL);
+
+	if (!iommu)
+		return;
+
+	/* Select Northbridge indirect register 0x75 and enable writing */
+	pci_write_config_dword(dev, 0x60, 0x75 | (1 << 7));
+	pci_read_config_dword(dev, 0x64, &ioc_feature_control);
+
+	/* Enable the iommu if it's vanished */
+	if (!(ioc_feature_control & 0x1))
+		pci_write_config_dword(dev, 0x64, ioc_feature_control | 1);
+
+	/* Disable writing again */
+	pci_write_config_dword(dev, 0x60, 0x75);
+
+	pci_dev_put(iommu);
+}
+
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_ATI, 0x5a10, amd_iommu_reenable);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_ATI, 0x5a12, amd_iommu_reenable);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_ATI, 0x5a13, amd_iommu_reenable);
+#endif
+
 static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
 			  struct pci_fixup *end)
 {