aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/amd_iommu.c
diff options
context:
space:
mode:
authorJoerg Roedel <jroedel@suse.de>2014-08-05 11:31:51 -0400
committerJoerg Roedel <jroedel@suse.de>2014-08-26 05:37:46 -0400
commit397111abaaac259afcc48cd2fbfb78f63f27e797 (patch)
tree9076983685482e21321c057c7c841422b1a4238c /drivers/iommu/amd_iommu.c
parentf251e187f2949c690fc13a91df7b873a6b5be671 (diff)
iommu/amd: Attach and detach complete alias group
Change tha device attach and detach semantic to apply to all devices in an alias group. This means all devices in an alias group are now attached and detached at the same time. Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu/amd_iommu.c')
-rw-r--r--drivers/iommu/amd_iommu.c46
1 files changed, 20 insertions, 26 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 8a152564a098..a5e6b0a2de16 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2149,35 +2149,29 @@ static void do_detach(struct iommu_dev_data *dev_data)
2149static int __attach_device(struct iommu_dev_data *dev_data, 2149static int __attach_device(struct iommu_dev_data *dev_data,
2150 struct protection_domain *domain) 2150 struct protection_domain *domain)
2151{ 2151{
2152 struct iommu_dev_data *head, *entry;
2152 int ret; 2153 int ret;
2153 2154
2154 /* lock domain */ 2155 /* lock domain */
2155 spin_lock(&domain->lock); 2156 spin_lock(&domain->lock);
2156 2157
2157 if (dev_data->alias_data != NULL) { 2158 head = dev_data;
2158 struct iommu_dev_data *alias_data = dev_data->alias_data;
2159
2160 /* Some sanity checks */
2161 ret = -EBUSY;
2162 if (alias_data->domain != NULL &&
2163 alias_data->domain != domain)
2164 goto out_unlock;
2165 2159
2166 if (dev_data->domain != NULL && 2160 if (head->alias_data != NULL)
2167 dev_data->domain != domain) 2161 head = head->alias_data;
2168 goto out_unlock;
2169 2162
2170 /* Do real assignment */ 2163 /* Now we have the root of the alias group, if any */
2171 if (alias_data->domain == NULL)
2172 do_attach(alias_data, domain);
2173 2164
2174 atomic_inc(&alias_data->bind); 2165 ret = -EBUSY;
2175 } 2166 if (head->domain != NULL)
2167 goto out_unlock;
2176 2168
2177 if (dev_data->domain == NULL) 2169 /* Attach alias group root */
2178 do_attach(dev_data, domain); 2170 do_attach(head, domain);
2179 2171
2180 atomic_inc(&dev_data->bind); 2172 /* Attach other devices in the alias group */
2173 list_for_each_entry(entry, &head->alias_list, alias_list)
2174 do_attach(entry, domain);
2181 2175
2182 ret = 0; 2176 ret = 0;
2183 2177
@@ -2325,6 +2319,7 @@ static int attach_device(struct device *dev,
2325 */ 2319 */
2326static void __detach_device(struct iommu_dev_data *dev_data) 2320static void __detach_device(struct iommu_dev_data *dev_data)
2327{ 2321{
2322 struct iommu_dev_data *head, *entry;
2328 struct protection_domain *domain; 2323 struct protection_domain *domain;
2329 unsigned long flags; 2324 unsigned long flags;
2330 2325
@@ -2334,15 +2329,14 @@ static void __detach_device(struct iommu_dev_data *dev_data)
2334 2329
2335 spin_lock_irqsave(&domain->lock, flags); 2330 spin_lock_irqsave(&domain->lock, flags);
2336 2331
2337 if (dev_data->alias_data != NULL) { 2332 head = dev_data;
2338 struct iommu_dev_data *alias_data = dev_data->alias_data; 2333 if (head->alias_data != NULL)
2334 head = head->alias_data;
2339 2335
2340 if (atomic_dec_and_test(&alias_data->bind)) 2336 list_for_each_entry(entry, &head->alias_list, alias_list)
2341 do_detach(alias_data); 2337 do_detach(entry);
2342 }
2343 2338
2344 if (atomic_dec_and_test(&dev_data->bind)) 2339 do_detach(head);
2345 do_detach(dev_data);
2346 2340
2347 spin_unlock_irqrestore(&domain->lock, flags); 2341 spin_unlock_irqrestore(&domain->lock, flags);
2348 2342