summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2009-11-11 20:08:46 +1100
committerStephen Rothwell <sfr@canb.auug.org.au>2009-11-11 20:08:46 +1100
commitc75429b46af611833c4c0dcb7929cfccd03b4e92 (patch)
treeaa22f5204162ae57c9acf2cd8f4a3466d769b489
parentcd1af99a4e38a84740d3650a8fe18d39fe922c23 (diff)
Revert "x86: Handle HW IOMMU initialization failure gracefully"
This reverts commit 75f1cdf1dda92cae037ec848ae63690d91913eac.
-rw-r--r--arch/x86/include/asm/iommu.h1
-rw-r--r--arch/x86/kernel/amd_iommu.c2
-rw-r--r--arch/x86/kernel/amd_iommu_init.c2
-rw-r--r--arch/x86/kernel/aperture_64.c2
-rw-r--r--arch/x86/kernel/pci-calgary_64.c10
-rw-r--r--arch/x86/kernel/pci-dma.c21
-rw-r--r--arch/x86/kernel/pci-gart_64.c1
-rw-r--r--arch/x86/kernel/pci-nommu.c9
-rw-r--r--arch/x86/kernel/pci-swiotlb.c7
-rw-r--r--drivers/pci/dmar.c3
-rw-r--r--drivers/pci/intel-iommu.c6
-rw-r--r--lib/swiotlb.c4
12 files changed, 39 insertions, 29 deletions
diff --git a/arch/x86/include/asm/iommu.h b/arch/x86/include/asm/iommu.h
index df42a712361f..878b30715766 100644
--- a/arch/x86/include/asm/iommu.h
+++ b/arch/x86/include/asm/iommu.h
@@ -2,6 +2,7 @@
#define _ASM_X86_IOMMU_H
static inline void iommu_shutdown_noop(void) {}
+extern void no_iommu_init(void);
extern struct dma_map_ops nommu_dma_ops;
extern int force_iommu, no_iommu;
extern int iommu_detected;
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 66237fde758f..0285521e0a99 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -2110,8 +2110,8 @@ int __init amd_iommu_init_dma_ops(void)
prealloc_protection_domains();
iommu_detected = 1;
+ force_iommu = 1;
bad_dma_address = 0;
- swiotlb = 0;
#ifdef CONFIG_GART_IOMMU
gart_iommu_aperture_disabled = 1;
gart_iommu_aperture = 0;
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c
index 0d4581e602a4..c41aabddaa2a 100644
--- a/arch/x86/kernel/amd_iommu_init.c
+++ b/arch/x86/kernel/amd_iommu_init.c
@@ -1330,7 +1330,7 @@ static int __init early_amd_iommu_detect(struct acpi_table_header *table)
void __init amd_iommu_detect(void)
{
- if (no_iommu || (iommu_detected && !gart_iommu_aperture))
+ if (swiotlb || no_iommu || (iommu_detected && !gart_iommu_aperture))
return;
if (acpi_table_parse("IVRS", early_amd_iommu_detect) == 0) {
diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c
index e0dfb6856aa2..03933cf0b63c 100644
--- a/arch/x86/kernel/aperture_64.c
+++ b/arch/x86/kernel/aperture_64.c
@@ -458,7 +458,7 @@ out:
if (aper_alloc) {
/* Got the aperture from the AGP bridge */
- } else if (!valid_agp) {
+ } else if (swiotlb && !valid_agp) {
/* Do nothing */
} else if ((!no_iommu && max_pfn > MAX_DMA32_PFN) ||
force_iommu ||
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index 833f491440b9..47bd419ea4d2 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -1360,7 +1360,7 @@ void __init detect_calgary(void)
* if the user specified iommu=off or iommu=soft or we found
* another HW IOMMU already, bail out.
*/
- if (no_iommu || iommu_detected)
+ if (swiotlb || no_iommu || iommu_detected)
return;
if (!use_calgary)
@@ -1445,6 +1445,10 @@ void __init detect_calgary(void)
printk(KERN_INFO "PCI-DMA: Calgary TCE table spec is %d\n",
specified_table_size);
+ /* swiotlb for devices that aren't behind the Calgary. */
+ if (max_pfn > MAX_DMA32_PFN)
+ swiotlb = 1;
+
x86_init.iommu.iommu_init = calgary_iommu_init;
}
return;
@@ -1472,7 +1476,11 @@ int __init calgary_iommu_init(void)
return ret;
}
+ force_iommu = 1;
bad_dma_address = 0x0;
+ /* dma_ops is set to swiotlb or nommu */
+ if (!dma_ops)
+ dma_ops = &nommu_dma_ops;
return 0;
}
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index 835f09af77cf..5bd31553d2f2 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -123,26 +123,26 @@ static void __init dma32_free_bootmem(void)
void __init pci_iommu_alloc(void)
{
- /* swiotlb is forced by the boot option */
- int use_swiotlb = swiotlb;
#ifdef CONFIG_X86_64
/* free the range so iommu could get some range less than 4G */
dma32_free_bootmem();
#else
dma_ops = &nommu_dma_ops;
#endif
- pci_swiotlb_init();
- if (use_swiotlb)
- return;
+ /*
+ * The order of these functions is important for
+ * fall-back/fail-over reasons
+ */
gart_iommu_hole_init();
detect_calgary();
detect_intel_iommu();
- /* needs to be called after gart_iommu_hole_init */
amd_iommu_detect();
+
+ pci_swiotlb_init();
}
void *dma_generic_alloc_coherent(struct device *dev, size_t size,
@@ -292,15 +292,10 @@ static int __init pci_iommu_init(void)
#ifdef CONFIG_PCI
dma_debug_add_bus(&pci_bus_type);
#endif
- x86_init.iommu.iommu_init();
- if (swiotlb) {
- printk(KERN_INFO "PCI-DMA: "
- "Using software bounce buffering for IO (SWIOTLB)\n");
- swiotlb_print_info();
- } else
- swiotlb_free();
+ x86_init.iommu.iommu_init();
+ no_iommu_init();
return 0;
}
/* Must execute after PCI subsystem */
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index 919182e15d1e..0410bd30060d 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -833,7 +833,6 @@ int __init gart_iommu_init(void)
flush_gart();
dma_ops = &gart_dma_ops;
x86_platform.iommu_shutdown = gart_iommu_shutdown;
- swiotlb = 0;
return 0;
}
diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c
index 875e3822ae61..a3933d4330cd 100644
--- a/arch/x86/kernel/pci-nommu.c
+++ b/arch/x86/kernel/pci-nommu.c
@@ -103,3 +103,12 @@ struct dma_map_ops nommu_dma_ops = {
.sync_sg_for_device = nommu_sync_sg_for_device,
.is_phys = 1,
};
+
+void __init no_iommu_init(void)
+{
+ if (dma_ops)
+ return;
+
+ force_iommu = 0; /* no HW IOMMU */
+ dma_ops = &nommu_dma_ops;
+}
diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c
index 17ce4221bd03..ea20ef7ca523 100644
--- a/arch/x86/kernel/pci-swiotlb.c
+++ b/arch/x86/kernel/pci-swiotlb.c
@@ -46,12 +46,13 @@ void __init pci_swiotlb_init(void)
{
/* don't initialize swiotlb if iommu=off (no_iommu=1) */
#ifdef CONFIG_X86_64
- if (!no_iommu && max_pfn > MAX_DMA32_PFN)
+ if ((!iommu_detected && !no_iommu && max_pfn > MAX_DMA32_PFN))
swiotlb = 1;
#endif
+ if (swiotlb_force)
+ swiotlb = 1;
if (swiotlb) {
swiotlb_init(0);
dma_ops = &swiotlb_dma_ops;
- } else
- dma_ops = &nommu_dma_ops;
+ }
}
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index bab8c6e1ee6f..09598c8feb4d 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -644,7 +644,8 @@ void __init detect_intel_iommu(void)
"x2apic and Intr-remapping.\n");
#endif
#ifdef CONFIG_DMAR
- if (ret && !no_iommu && !iommu_detected && !dmar_disabled)
+ if (ret && !no_iommu && !iommu_detected && !swiotlb &&
+ !dmar_disabled)
iommu_detected = 1;
#endif
#ifdef CONFIG_X86
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 34c8bbe6f9ec..c83113646223 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -3240,7 +3240,7 @@ int __init intel_iommu_init(void)
* Check the need for DMA-remapping initialization now.
* Above initialization will also be used by Interrupt-remapping.
*/
- if (no_iommu || dmar_disabled)
+ if (no_iommu || swiotlb || dmar_disabled)
return -ENODEV;
iommu_init_mempool();
@@ -3261,9 +3261,7 @@ int __init intel_iommu_init(void)
"PCI-DMA: Intel(R) Virtualization Technology for Directed I/O\n");
init_timer(&unmap_timer);
-#ifdef CONFIG_SWIOTLB
- swiotlb = 0;
-#endif
+ force_iommu = 1;
dma_ops = &intel_dma_ops;
init_iommu_sysfs();
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index e6755a0574fb..0c12d7cce300 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -109,10 +109,8 @@ setup_io_tlb_npages(char *str)
}
if (*str == ',')
++str;
- if (!strcmp(str, "force")) {
+ if (!strcmp(str, "force"))
swiotlb_force = 1;
- swiotlb = 1;
- }
return 1;
}
__setup("swiotlb=", setup_io_tlb_npages);