summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Roedel <jroedel@suse.de>2014-08-05 17:31:51 +0200
committerJoerg Roedel <jroedel@suse.de>2014-08-26 11:37:46 +0200
commit397111abaaac259afcc48cd2fbfb78f63f27e797 (patch)
tree9076983685482e21321c057c7c841422b1a4238c
parentf251e187f2949c690fc13a91df7b873a6b5be671 (diff)
downloadlinux-397111abaaac259afcc48cd2fbfb78f63f27e797.tar.gz
linux-397111abaaac259afcc48cd2fbfb78f63f27e797.tar.bz2
linux-397111abaaac259afcc48cd2fbfb78f63f27e797.zip
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>
-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)
static int __attach_device(struct iommu_dev_data *dev_data,
struct protection_domain *domain)
{
+ struct iommu_dev_data *head, *entry;
int ret;
/* lock domain */
spin_lock(&domain->lock);
- if (dev_data->alias_data != NULL) {
- struct iommu_dev_data *alias_data = dev_data->alias_data;
-
- /* Some sanity checks */
- ret = -EBUSY;
- if (alias_data->domain != NULL &&
- alias_data->domain != domain)
- goto out_unlock;
+ head = dev_data;
- if (dev_data->domain != NULL &&
- dev_data->domain != domain)
- goto out_unlock;
+ if (head->alias_data != NULL)
+ head = head->alias_data;
- /* Do real assignment */
- if (alias_data->domain == NULL)
- do_attach(alias_data, domain);
+ /* Now we have the root of the alias group, if any */
- atomic_inc(&alias_data->bind);
- }
+ ret = -EBUSY;
+ if (head->domain != NULL)
+ goto out_unlock;
- if (dev_data->domain == NULL)
- do_attach(dev_data, domain);
+ /* Attach alias group root */
+ do_attach(head, domain);
- atomic_inc(&dev_data->bind);
+ /* Attach other devices in the alias group */
+ list_for_each_entry(entry, &head->alias_list, alias_list)
+ do_attach(entry, domain);
ret = 0;
@@ -2325,6 +2319,7 @@ static int attach_device(struct device *dev,
*/
static void __detach_device(struct iommu_dev_data *dev_data)
{
+ struct iommu_dev_data *head, *entry;
struct protection_domain *domain;
unsigned long flags;
@@ -2334,15 +2329,14 @@ static void __detach_device(struct iommu_dev_data *dev_data)
spin_lock_irqsave(&domain->lock, flags);
- if (dev_data->alias_data != NULL) {
- struct iommu_dev_data *alias_data = dev_data->alias_data;
+ head = dev_data;
+ if (head->alias_data != NULL)
+ head = head->alias_data;
- if (atomic_dec_and_test(&alias_data->bind))
- do_detach(alias_data);
- }
+ list_for_each_entry(entry, &head->alias_list, alias_list)
+ do_detach(entry);
- if (atomic_dec_and_test(&dev_data->bind))
- do_detach(dev_data);
+ do_detach(head);
spin_unlock_irqrestore(&domain->lock, flags);