فهرست منبع

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>
Joerg Roedel 11 سال پیش
والد
کامیت
397111abaa
1فایلهای تغییر یافته به همراه20 افزوده شده و 26 حذف شده
  1. 20 26
      drivers/iommu/amd_iommu.c

+ 20 - 26
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,
 static int __attach_device(struct iommu_dev_data *dev_data,
 			   struct protection_domain *domain)
 			   struct protection_domain *domain)
 {
 {
+	struct iommu_dev_data *head, *entry;
 	int ret;
 	int ret;
 
 
 	/* lock domain */
 	/* lock domain */
 	spin_lock(&domain->lock);
 	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;
 	ret = 0;
 
 
@@ -2325,6 +2319,7 @@ static int attach_device(struct device *dev,
  */
  */
 static void __detach_device(struct iommu_dev_data *dev_data)
 static void __detach_device(struct iommu_dev_data *dev_data)
 {
 {
+	struct iommu_dev_data *head, *entry;
 	struct protection_domain *domain;
 	struct protection_domain *domain;
 	unsigned long flags;
 	unsigned long flags;
 
 
@@ -2334,15 +2329,14 @@ static void __detach_device(struct iommu_dev_data *dev_data)
 
 
 	spin_lock_irqsave(&domain->lock, flags);
 	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);
 	spin_unlock_irqrestore(&domain->lock, flags);