From c7972423be87a0a933c01821815cd7173a851ce3 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Wed, 20 Jun 2007 12:23:32 +0200 Subject: [PATCH] --- yaml --- r: 57883 b: refs/heads/master c: 388c19e176436707eb30a81c7e4129e08769f92b h: refs/heads/master i: 57881: 30493c663cc72094b4a3552cb6733c1ae7381261 57879: 7f07ea70909836d807c55a05b9f2c4750ae86d67 v: v3 --- [refs] | 2 +- trunk/arch/i386/kernel/pci-dma.c | 27 +++++++++++++++++++++++++++ trunk/arch/x86_64/kernel/pci-dma.c | 12 ++++++++++++ trunk/include/asm-i386/dma-mapping.h | 6 ++++++ 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index a1c975fb628b..b1126e55b6ef 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 0b622330213ce0f0ee23199e433ed73284209b46 +refs/heads/master: 388c19e176436707eb30a81c7e4129e08769f92b diff --git a/trunk/arch/i386/kernel/pci-dma.c b/trunk/arch/i386/kernel/pci-dma.c index 30b754f7cbec..048f09b62553 100644 --- a/trunk/arch/i386/kernel/pci-dma.c +++ b/trunk/arch/i386/kernel/pci-dma.c @@ -12,6 +12,7 @@ #include #include #include +#include #include struct dma_coherent_mem { @@ -148,3 +149,29 @@ void *dma_mark_declared_memory_occupied(struct device *dev, return mem->virt_base + (pos << PAGE_SHIFT); } 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 diff --git a/trunk/arch/x86_64/kernel/pci-dma.c b/trunk/arch/x86_64/kernel/pci-dma.c index 651ccfb06697..9f80aad3fe2d 100644 --- a/trunk/arch/x86_64/kernel/pci-dma.c +++ b/trunk/arch/x86_64/kernel/pci-dma.c @@ -322,5 +322,17 @@ static int __init pci_iommu_init(void) 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 */ fs_initcall(pci_iommu_init); diff --git a/trunk/include/asm-i386/dma-mapping.h b/trunk/include/asm-i386/dma-mapping.h index 183eebeebbdc..f1d72d177f68 100644 --- a/trunk/include/asm-i386/dma-mapping.h +++ b/trunk/include/asm-i386/dma-mapping.h @@ -123,6 +123,8 @@ dma_mapping_error(dma_addr_t dma_addr) return 0; } +extern int forbid_dac; + static inline int dma_supported(struct device *dev, u64 mask) { @@ -134,6 +136,10 @@ dma_supported(struct device *dev, u64 mask) if(mask < 0x00ffffff) return 0; + /* Work around chipset bugs */ + if (forbid_dac > 0 && mask > 0xffffffffULL) + return 0; + return 1; }