| From ca77fde8e62cecb2c0769052228d15b901367af8 Mon Sep 17 00:00:00 2001 |
| From: David Woodhouse <dwmw2@infradead.org> |
| Date: Fri, 13 Feb 2009 23:18:03 +0000 |
| Subject: Fix Intel IOMMU write-buffer flushing |
| |
| From: David Woodhouse <dwmw2@infradead.org> |
| |
| 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> |
| |
| --- |
| drivers/pci/intel-iommu.c | 13 ++++++++++++- |
| 1 file changed, 12 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/pci/intel-iommu.c |
| +++ b/drivers/pci/intel-iommu.c |
| @@ -72,6 +72,8 @@ static struct deferred_flush_tables *def |
| /* 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); |
| |
| @@ -527,7 +529,7 @@ static void iommu_flush_write_buffer(str |
| u32 val; |
| unsigned long flag; |
| |
| - if (!cap_rwbf(iommu->cap)) |
| + if (!rwbf_quirk && !cap_rwbf(iommu->cap)) |
| return; |
| val = iommu->gcmd | DMA_GCMD_WBF; |
| |
| @@ -2453,3 +2455,12 @@ int __init intel_iommu_init(void) |
| return 0; |
| } |
| |
| +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); |