diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2014-03-09 16:31:18 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2014-03-24 10:06:44 -0400 |
commit | 5a8f40e8c8801a9805bbe60d140ed2b0b3b91d18 (patch) | |
tree | 8f70047bbeeb2b8e356e3fadac52130df27079db | |
parent | e2f8c5f6d45b092b52adea9d71018ef11250b924 (diff) |
iommu/vt-d: Always store iommu in device_domain_info
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
-rw-r--r-- | drivers/iommu/intel-iommu.c | 47 |
1 files changed, 31 insertions, 16 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 84f0d4284125..8303f256fe84 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c | |||
@@ -1274,8 +1274,6 @@ iommu_support_dev_iotlb (struct dmar_domain *domain, struct intel_iommu *iommu, | |||
1274 | if (!dmar_find_matched_atsr_unit(pdev)) | 1274 | if (!dmar_find_matched_atsr_unit(pdev)) |
1275 | return NULL; | 1275 | return NULL; |
1276 | 1276 | ||
1277 | info->iommu = iommu; | ||
1278 | |||
1279 | return info; | 1277 | return info; |
1280 | } | 1278 | } |
1281 | 1279 | ||
@@ -2134,7 +2132,7 @@ static struct dmar_domain *find_domain(struct device *dev) | |||
2134 | return NULL; | 2132 | return NULL; |
2135 | } | 2133 | } |
2136 | 2134 | ||
2137 | static inline struct dmar_domain * | 2135 | static inline struct device_domain_info * |
2138 | dmar_search_domain_by_dev_info(int segment, int bus, int devfn) | 2136 | dmar_search_domain_by_dev_info(int segment, int bus, int devfn) |
2139 | { | 2137 | { |
2140 | struct device_domain_info *info; | 2138 | struct device_domain_info *info; |
@@ -2142,16 +2140,17 @@ dmar_search_domain_by_dev_info(int segment, int bus, int devfn) | |||
2142 | list_for_each_entry(info, &device_domain_list, global) | 2140 | list_for_each_entry(info, &device_domain_list, global) |
2143 | if (info->segment == segment && info->bus == bus && | 2141 | if (info->segment == segment && info->bus == bus && |
2144 | info->devfn == devfn) | 2142 | info->devfn == devfn) |
2145 | return info->domain; | 2143 | return info; |
2146 | 2144 | ||
2147 | return NULL; | 2145 | return NULL; |
2148 | } | 2146 | } |
2149 | 2147 | ||
2150 | static struct dmar_domain *dmar_insert_dev_info(int segment, int bus, int devfn, | 2148 | static struct dmar_domain *dmar_insert_dev_info(struct intel_iommu *iommu, |
2149 | int segment, int bus, int devfn, | ||
2151 | struct device *dev, | 2150 | struct device *dev, |
2152 | struct dmar_domain *domain) | 2151 | struct dmar_domain *domain) |
2153 | { | 2152 | { |
2154 | struct dmar_domain *found; | 2153 | struct dmar_domain *found = NULL; |
2155 | struct device_domain_info *info; | 2154 | struct device_domain_info *info; |
2156 | unsigned long flags; | 2155 | unsigned long flags; |
2157 | 2156 | ||
@@ -2164,14 +2163,19 @@ static struct dmar_domain *dmar_insert_dev_info(int segment, int bus, int devfn, | |||
2164 | info->devfn = devfn; | 2163 | info->devfn = devfn; |
2165 | info->dev = dev; | 2164 | info->dev = dev; |
2166 | info->domain = domain; | 2165 | info->domain = domain; |
2166 | info->iommu = iommu; | ||
2167 | if (!dev) | 2167 | if (!dev) |
2168 | domain->flags |= DOMAIN_FLAG_P2P_MULTIPLE_DEVICES; | 2168 | domain->flags |= DOMAIN_FLAG_P2P_MULTIPLE_DEVICES; |
2169 | 2169 | ||
2170 | spin_lock_irqsave(&device_domain_lock, flags); | 2170 | spin_lock_irqsave(&device_domain_lock, flags); |
2171 | if (dev) | 2171 | if (dev) |
2172 | found = find_domain(dev); | 2172 | found = find_domain(dev); |
2173 | else | 2173 | else { |
2174 | found = dmar_search_domain_by_dev_info(segment, bus, devfn); | 2174 | struct device_domain_info *info2; |
2175 | info2 = dmar_search_domain_by_dev_info(segment, bus, devfn); | ||
2176 | if (info2) | ||
2177 | found = info2->domain; | ||
2178 | } | ||
2175 | if (found) { | 2179 | if (found) { |
2176 | spin_unlock_irqrestore(&device_domain_lock, flags); | 2180 | spin_unlock_irqrestore(&device_domain_lock, flags); |
2177 | free_devinfo_mem(info); | 2181 | free_devinfo_mem(info); |
@@ -2192,7 +2196,8 @@ static struct dmar_domain *dmar_insert_dev_info(int segment, int bus, int devfn, | |||
2192 | static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw) | 2196 | static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw) |
2193 | { | 2197 | { |
2194 | struct dmar_domain *domain, *free = NULL; | 2198 | struct dmar_domain *domain, *free = NULL; |
2195 | struct intel_iommu *iommu; | 2199 | struct intel_iommu *iommu = NULL; |
2200 | struct device_domain_info *info; | ||
2196 | struct dmar_drhd_unit *drhd; | 2201 | struct dmar_drhd_unit *drhd; |
2197 | struct pci_dev *dev_tmp; | 2202 | struct pci_dev *dev_tmp; |
2198 | unsigned long flags; | 2203 | unsigned long flags; |
@@ -2215,10 +2220,13 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw) | |||
2215 | devfn = dev_tmp->devfn; | 2220 | devfn = dev_tmp->devfn; |
2216 | } | 2221 | } |
2217 | spin_lock_irqsave(&device_domain_lock, flags); | 2222 | spin_lock_irqsave(&device_domain_lock, flags); |
2218 | domain = dmar_search_domain_by_dev_info(segment, bus, devfn); | 2223 | info = dmar_search_domain_by_dev_info(segment, bus, devfn); |
2224 | if (info) { | ||
2225 | iommu = info->iommu; | ||
2226 | domain = info->domain; | ||
2227 | } | ||
2219 | spin_unlock_irqrestore(&device_domain_lock, flags); | 2228 | spin_unlock_irqrestore(&device_domain_lock, flags); |
2220 | /* pcie-pci bridge already has a domain, uses it */ | 2229 | if (info) |
2221 | if (domain) | ||
2222 | goto found_domain; | 2230 | goto found_domain; |
2223 | } | 2231 | } |
2224 | 2232 | ||
@@ -2244,14 +2252,15 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw) | |||
2244 | 2252 | ||
2245 | /* register pcie-to-pci device */ | 2253 | /* register pcie-to-pci device */ |
2246 | if (dev_tmp) { | 2254 | if (dev_tmp) { |
2247 | domain = dmar_insert_dev_info(segment, bus, devfn, NULL, domain); | 2255 | domain = dmar_insert_dev_info(iommu, segment, bus, devfn, NULL, |
2256 | domain); | ||
2248 | if (!domain) | 2257 | if (!domain) |
2249 | goto error; | 2258 | goto error; |
2250 | } | 2259 | } |
2251 | 2260 | ||
2252 | found_domain: | 2261 | found_domain: |
2253 | domain = dmar_insert_dev_info(segment, pdev->bus->number, pdev->devfn, | 2262 | domain = dmar_insert_dev_info(iommu, segment, pdev->bus->number, |
2254 | &pdev->dev, domain); | 2263 | pdev->devfn, &pdev->dev, domain); |
2255 | error: | 2264 | error: |
2256 | if (free != domain) | 2265 | if (free != domain) |
2257 | domain_exit(free); | 2266 | domain_exit(free); |
@@ -2453,9 +2462,15 @@ static int domain_add_dev_info(struct dmar_domain *domain, | |||
2453 | int translation) | 2462 | int translation) |
2454 | { | 2463 | { |
2455 | struct dmar_domain *ndomain; | 2464 | struct dmar_domain *ndomain; |
2465 | struct intel_iommu *iommu; | ||
2456 | int ret; | 2466 | int ret; |
2457 | 2467 | ||
2458 | ndomain = dmar_insert_dev_info(pci_domain_nr(pdev->bus), | 2468 | iommu = device_to_iommu(pci_domain_nr(pdev->bus), |
2469 | pdev->bus->number, pdev->devfn); | ||
2470 | if (!iommu) | ||
2471 | return -ENODEV; | ||
2472 | |||
2473 | ndomain = dmar_insert_dev_info(iommu, pci_domain_nr(pdev->bus), | ||
2459 | pdev->bus->number, pdev->devfn, | 2474 | pdev->bus->number, pdev->devfn, |
2460 | &pdev->dev, domain); | 2475 | &pdev->dev, domain); |
2461 | if (ndomain != domain) | 2476 | if (ndomain != domain) |