]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/iommu/amd_iommu_init.c
Merge branches 'x86/vt-d', 'x86/amd', 'arm/smmu', 'arm/omap', 'generic-dma-ops' and...
[linux.git] / drivers / iommu / amd_iommu_init.c
index 07d84dbab564e4dc0c7cda92eb138b616fb4cb75..eb104c719629e6de64328079563d94dde8fee740 100644 (file)
@@ -406,6 +406,9 @@ static void iommu_enable(struct amd_iommu *iommu)
 
 static void iommu_disable(struct amd_iommu *iommu)
 {
+       if (!iommu->mmio_base)
+               return;
+
        /* Disable command buffer */
        iommu_feature_disable(iommu, CONTROL_CMDBUF_EN);
 
@@ -2325,15 +2328,6 @@ static void __init free_iommu_resources(void)
        amd_iommu_dev_table = NULL;
 
        free_iommu_all();
-
-#ifdef CONFIG_GART_IOMMU
-       /*
-        * We failed to initialize the AMD IOMMU - try fallback to GART
-        * if possible.
-        */
-       gart_iommu_init();
-
-#endif
 }
 
 /* SB IOAPIC is always on this device in AMD systems */
@@ -2625,8 +2619,6 @@ static int __init state_next(void)
                init_state = ret ? IOMMU_INIT_ERROR : IOMMU_ACPI_FINISHED;
                if (init_state == IOMMU_ACPI_FINISHED && amd_iommu_disabled) {
                        pr_info("AMD IOMMU disabled on kernel command-line\n");
-                       free_dma_resources();
-                       free_iommu_resources();
                        init_state = IOMMU_CMDLINE_DISABLED;
                        ret = -EINVAL;
                }
@@ -2667,6 +2659,19 @@ static int __init state_next(void)
                BUG();
        }
 
+       if (ret) {
+               free_dma_resources();
+               if (!irq_remapping_enabled) {
+                       disable_iommus();
+                       free_iommu_resources();
+               } else {
+                       struct amd_iommu *iommu;
+
+                       uninit_device_table_dma();
+                       for_each_iommu(iommu)
+                               iommu_flush_all_caches(iommu);
+               }
+       }
        return ret;
 }
 
@@ -2740,17 +2745,15 @@ static int __init amd_iommu_init(void)
        int ret;
 
        ret = iommu_go_to_state(IOMMU_INITIALIZED);
-       if (ret) {
-               free_dma_resources();
-               if (!irq_remapping_enabled) {
-                       disable_iommus();
-                       free_iommu_resources();
-               } else {
-                       uninit_device_table_dma();
-                       for_each_iommu(iommu)
-                               iommu_flush_all_caches(iommu);
-               }
+#ifdef CONFIG_GART_IOMMU
+       if (ret && list_empty(&amd_iommu_list)) {
+               /*
+                * We failed to initialize the AMD IOMMU - try fallback
+                * to GART if possible.
+                */
+               gart_iommu_init();
        }
+#endif
 
        for_each_iommu(iommu)
                amd_iommu_debugfs_setup(iommu);