summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2009-02-13 23:18:03 +0000
committerGreg Kroah-Hartman <gregkh@suse.de>2009-02-20 14:40:19 -0800
commitf585c3cf6db583055c2dc027e8602b0fd07faeb6 (patch)
tree0f7ade0786a403d258673d5f08c8e675e3cf5a11
parent2d554b617ee692633b99c5e1c15cfb983443bd8c (diff)
Fix Intel IOMMU write-buffer flushing
commit ca77fde8e62cecb2c0769052228d15b901367af8 upstream. This is the cause of the DMA faults and disk corruption that people have been seeing. Some chipsets neglect to report the RWBF "capability" -- the flag which says that we need to flush the chipset write-buffer when changing the DMA page tables, to ensure that the change is visible to the IOMMU. Override that bit on the affected chipsets, and everything is happy again. Thanks to Chris and Bhavesh and others for helping to debug. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> Tested-by: Chris Wright <chrisw@sous-sol.org> Reviewed-by: Bhavesh Davda <bhavesh@vmware.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/pci/intel-iommu.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 5c8baa43ac9c..3a4fea19309f 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -71,6 +71,8 @@ static struct deferred_flush_tables *deferred_flush;
/* bitmap for indexing intel_iommus */
static int g_num_of_iommus;
+static int rwbf_quirk = 0;
+
static DEFINE_SPINLOCK(async_umap_flush_lock);
static LIST_HEAD(unmaps_to_do);
@@ -506,7 +508,7 @@ static void iommu_flush_write_buffer(struct intel_iommu *iommu)
u32 val;
unsigned long flag;
- if (!cap_rwbf(iommu->cap))
+ if (!rwbf_quirk && !cap_rwbf(iommu->cap))
return;
val = iommu->gcmd | DMA_GCMD_WBF;
@@ -2436,3 +2438,13 @@ u64 intel_iommu_iova_to_pfn(struct dmar_domain *domain, u64 iova)
return pfn >> VTD_PAGE_SHIFT;
}
EXPORT_SYMBOL_GPL(intel_iommu_iova_to_pfn);
+
+static void __devinit quirk_iommu_rwbf(struct pci_dev *dev)
+{
+ /* Mobile 4 Series Chipset neglects to set RWBF capability,
+ but needs it */
+ printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n");
+ rwbf_quirk = 1;
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);