diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2009-08-09 05:53:41 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2009-08-09 05:53:50 -0400 |
commit | 5fe60f4e5871b64e687229199fafd4ef13cd0886 (patch) | |
tree | 8a4967096922ffbed25d4918ab9ddefebbee215b | |
parent | a131bc185528331451a93db6c50a7d2070376a61 (diff) |
intel-iommu: make domain_add_dev_info() call domain_context_mapping()
All callers of the former were also calling the latter, in one order or
the other, and failing to correctly clean up if the second returned
failure.
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
-rw-r--r-- | drivers/pci/intel-iommu.c | 35 |
1 files changed, 15 insertions, 20 deletions
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 3f256b8d83c1..09606e9aedec 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -2094,15 +2094,23 @@ static int identity_mapping(struct pci_dev *pdev) | |||
2094 | } | 2094 | } |
2095 | 2095 | ||
2096 | static int domain_add_dev_info(struct dmar_domain *domain, | 2096 | static int domain_add_dev_info(struct dmar_domain *domain, |
2097 | struct pci_dev *pdev) | 2097 | struct pci_dev *pdev, |
2098 | int translation) | ||
2098 | { | 2099 | { |
2099 | struct device_domain_info *info; | 2100 | struct device_domain_info *info; |
2100 | unsigned long flags; | 2101 | unsigned long flags; |
2102 | int ret; | ||
2101 | 2103 | ||
2102 | info = alloc_devinfo_mem(); | 2104 | info = alloc_devinfo_mem(); |
2103 | if (!info) | 2105 | if (!info) |
2104 | return -ENOMEM; | 2106 | return -ENOMEM; |
2105 | 2107 | ||
2108 | ret = domain_context_mapping(domain, pdev, translation); | ||
2109 | if (ret) { | ||
2110 | free_devinfo_mem(info); | ||
2111 | return ret; | ||
2112 | } | ||
2113 | |||
2106 | info->segment = pci_domain_nr(pdev->bus); | 2114 | info->segment = pci_domain_nr(pdev->bus); |
2107 | info->bus = pdev->bus->number; | 2115 | info->bus = pdev->bus->number; |
2108 | info->devfn = pdev->devfn; | 2116 | info->devfn = pdev->devfn; |
@@ -2173,15 +2181,11 @@ static int iommu_prepare_static_identity_mapping(int hw) | |||
2173 | printk(KERN_INFO "IOMMU: %s identity mapping for device %s\n", | 2181 | printk(KERN_INFO "IOMMU: %s identity mapping for device %s\n", |
2174 | hw ? "hardware" : "software", pci_name(pdev)); | 2182 | hw ? "hardware" : "software", pci_name(pdev)); |
2175 | 2183 | ||
2176 | ret = domain_context_mapping(si_domain, pdev, | 2184 | ret = domain_add_dev_info(si_domain, pdev, |
2177 | hw ? CONTEXT_TT_PASS_THROUGH : | 2185 | hw ? CONTEXT_TT_PASS_THROUGH : |
2178 | CONTEXT_TT_MULTI_LEVEL); | 2186 | CONTEXT_TT_MULTI_LEVEL); |
2179 | if (ret) | 2187 | if (ret) |
2180 | return ret; | 2188 | return ret; |
2181 | |||
2182 | ret = domain_add_dev_info(si_domain, pdev); | ||
2183 | if (ret) | ||
2184 | return ret; | ||
2185 | } | 2189 | } |
2186 | } | 2190 | } |
2187 | 2191 | ||
@@ -2510,13 +2514,10 @@ static int iommu_no_mapping(struct device *dev) | |||
2510 | */ | 2514 | */ |
2511 | if (iommu_should_identity_map(pdev, 0)) { | 2515 | if (iommu_should_identity_map(pdev, 0)) { |
2512 | int ret; | 2516 | int ret; |
2513 | ret = domain_add_dev_info(si_domain, pdev); | 2517 | ret = domain_add_dev_info(si_domain, pdev, |
2514 | if (ret) | 2518 | hw_pass_through ? |
2515 | return 0; | 2519 | CONTEXT_TT_PASS_THROUGH : |
2516 | ret = domain_context_mapping(si_domain, pdev, | 2520 | CONTEXT_TT_MULTI_LEVEL); |
2517 | hw_pass_through ? | ||
2518 | CONTEXT_TT_PASS_THROUGH : | ||
2519 | CONTEXT_TT_MULTI_LEVEL); | ||
2520 | if (!ret) { | 2521 | if (!ret) { |
2521 | printk(KERN_INFO "64bit %s uses identity mapping\n", | 2522 | printk(KERN_INFO "64bit %s uses identity mapping\n", |
2522 | pci_name(pdev)); | 2523 | pci_name(pdev)); |
@@ -3486,7 +3487,6 @@ static int intel_iommu_attach_device(struct iommu_domain *domain, | |||
3486 | struct intel_iommu *iommu; | 3487 | struct intel_iommu *iommu; |
3487 | int addr_width; | 3488 | int addr_width; |
3488 | u64 end; | 3489 | u64 end; |
3489 | int ret; | ||
3490 | 3490 | ||
3491 | /* normally pdev is not mapped */ | 3491 | /* normally pdev is not mapped */ |
3492 | if (unlikely(domain_context_mapped(pdev))) { | 3492 | if (unlikely(domain_context_mapped(pdev))) { |
@@ -3518,12 +3518,7 @@ static int intel_iommu_attach_device(struct iommu_domain *domain, | |||
3518 | return -EFAULT; | 3518 | return -EFAULT; |
3519 | } | 3519 | } |
3520 | 3520 | ||
3521 | ret = domain_add_dev_info(dmar_domain, pdev); | 3521 | return domain_add_dev_info(dmar_domain, pdev, CONTEXT_TT_MULTI_LEVEL); |
3522 | if (ret) | ||
3523 | return ret; | ||
3524 | |||
3525 | ret = domain_context_mapping(dmar_domain, pdev, CONTEXT_TT_MULTI_LEVEL); | ||
3526 | return ret; | ||
3527 | } | 3522 | } |
3528 | 3523 | ||
3529 | static void intel_iommu_detach_device(struct iommu_domain *domain, | 3524 | static void intel_iommu_detach_device(struct iommu_domain *domain, |