Commit 388c19e1 authored by Andi Kleen's avatar Andi Kleen Committed by Linus Torvalds

x86: Disable DAC on VIA bridges

Several reports that VIA bridges don't support DAC and corrupt
data.  I don't know if it's fixed, but let's just blacklist
them all for now.

It can be overwritten with iommu=usedac
Signed-off-by: default avatarAndi Kleen <ak@suse.de>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 0b622330
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h>
#include <asm/io.h> #include <asm/io.h>
struct dma_coherent_mem { struct dma_coherent_mem {
...@@ -148,3 +149,29 @@ void *dma_mark_declared_memory_occupied(struct device *dev, ...@@ -148,3 +149,29 @@ void *dma_mark_declared_memory_occupied(struct device *dev,
return mem->virt_base + (pos << PAGE_SHIFT); return mem->virt_base + (pos << PAGE_SHIFT);
} }
EXPORT_SYMBOL(dma_mark_declared_memory_occupied); EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
#ifdef CONFIG_PCI
/* Many VIA bridges seem to corrupt data for DAC. Disable it here */
int forbid_dac;
EXPORT_SYMBOL(forbid_dac);
static __devinit void via_no_dac(struct pci_dev *dev)
{
if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && forbid_dac == 0) {
printk(KERN_INFO "PCI: VIA PCI bridge detected. Disabling DAC.\n");
forbid_dac = 1;
}
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID, via_no_dac);
static int check_iommu(char *s)
{
if (!strcmp(s, "usedac")) {
forbid_dac = -1;
return 1;
}
return 0;
}
__setup("iommu=", check_iommu);
#endif
...@@ -322,5 +322,17 @@ static int __init pci_iommu_init(void) ...@@ -322,5 +322,17 @@ static int __init pci_iommu_init(void)
return 0; return 0;
} }
#ifdef CONFIG_PCI
/* Many VIA bridges seem to corrupt data for DAC. Disable it here */
static __devinit void via_no_dac(struct pci_dev *dev)
{
if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && forbid_dac == 0) {
printk(KERN_INFO "PCI: VIA PCI bridge detected. Disabling DAC.\n");
forbid_dac = 1;
}
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID, via_no_dac);
#endif
/* Must execute after PCI subsystem */ /* Must execute after PCI subsystem */
fs_initcall(pci_iommu_init); fs_initcall(pci_iommu_init);
...@@ -123,6 +123,8 @@ dma_mapping_error(dma_addr_t dma_addr) ...@@ -123,6 +123,8 @@ dma_mapping_error(dma_addr_t dma_addr)
return 0; return 0;
} }
extern int forbid_dac;
static inline int static inline int
dma_supported(struct device *dev, u64 mask) dma_supported(struct device *dev, u64 mask)
{ {
...@@ -134,6 +136,10 @@ dma_supported(struct device *dev, u64 mask) ...@@ -134,6 +136,10 @@ dma_supported(struct device *dev, u64 mask)
if(mask < 0x00ffffff) if(mask < 0x00ffffff)
return 0; return 0;
/* Work around chipset bugs */
if (forbid_dac > 0 && mask > 0xffffffffULL)
return 0;
return 1; return 1;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment