x86/amd-iommu: Fix passthrough mode
authorJoerg Roedel <joerg.roedel@amd.com>
Thu, 10 Dec 2009 10:03:39 +0000 (11:03 +0100)
committerJoerg Roedel <joerg.roedel@amd.com>
Thu, 10 Dec 2009 11:21:31 +0000 (12:21 +0100)
The data structure changes to use dev->archdata.iommu field
broke the iommu=pt mode because in this case the
dev->archdata.iommu was left uninitialized. This moves the
inititalization of the devices into the main init function
and fixes the problem.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
arch/x86/include/asm/amd_iommu_proto.h
arch/x86/kernel/amd_iommu.c
arch/x86/kernel/amd_iommu_init.c

index 84786fb9a23b8b29aeaa4d1455b91ab1cd273626..2566e2606224b38d43e4d34a2d7a1dead634f312 100644 (file)
@@ -28,7 +28,8 @@ extern void amd_iommu_flush_all_domains(void);
 extern void amd_iommu_flush_all_devices(void);
 extern void amd_iommu_apply_erratum_63(u16 devid);
 extern void amd_iommu_reset_cmd_buffer(struct amd_iommu *iommu);
-
+extern int amd_iommu_init_devices(void);
+extern void amd_iommu_uninit_devices(void);
 #ifndef CONFIG_AMD_IOMMU_STATS
 
 static inline void amd_iommu_stats_init(void) { }
index 32fb09102a1356af2597d1cafd924bbc8e2ee941..450dd6ac03d35049944825fcbeda3dc4595f9eca 100644 (file)
@@ -166,6 +166,43 @@ static void iommu_uninit_device(struct device *dev)
 {
        kfree(dev->archdata.iommu);
 }
+
+void __init amd_iommu_uninit_devices(void)
+{
+       struct pci_dev *pdev = NULL;
+
+       for_each_pci_dev(pdev) {
+
+               if (!check_device(&pdev->dev))
+                       continue;
+
+               iommu_uninit_device(&pdev->dev);
+       }
+}
+
+int __init amd_iommu_init_devices(void)
+{
+       struct pci_dev *pdev = NULL;
+       int ret = 0;
+
+       for_each_pci_dev(pdev) {
+
+               if (!check_device(&pdev->dev))
+                       continue;
+
+               ret = iommu_init_device(&pdev->dev);
+               if (ret)
+                       goto out_free;
+       }
+
+       return 0;
+
+out_free:
+
+       amd_iommu_uninit_devices();
+
+       return ret;
+}
 #ifdef CONFIG_AMD_IOMMU_STATS
 
 /*
@@ -2145,8 +2182,6 @@ static void prealloc_protection_domains(void)
                if (!check_device(&dev->dev))
                        continue;
 
-               iommu_init_device(&dev->dev);
-
                /* Is there already any domain for it? */
                if (domain_for_device(&dev->dev))
                        continue;
index 7ffc39965233ce570a7b734f12636ce05e403d1e..df01c691d130cb93e5982f4965182804ca8b9601 100644 (file)
@@ -1274,6 +1274,10 @@ static int __init amd_iommu_init(void)
        if (ret)
                goto free;
 
+       ret = amd_iommu_init_devices();
+       if (ret)
+               goto free;
+
        if (iommu_pass_through)
                ret = amd_iommu_init_passthrough();
        else
@@ -1296,6 +1300,9 @@ out:
        return ret;
 
 free:
+
+       amd_iommu_uninit_devices();
+
        free_pages((unsigned long)amd_iommu_pd_alloc_bitmap,
                   get_order(MAX_DOMAIN_ID/8));