]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
iommu/amd: Make sure dma_ops are set for hotplug devices
authorJoerg Roedel <joro@8bytes.org>
Tue, 26 Mar 2013 21:48:23 +0000 (22:48 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 5 Apr 2013 17:16:54 +0000 (10:16 -0700)
commit c2a2876e863356b092967ea62bebdb4dd663af80 upstream.

There is a bug introduced with commit 27c2127 that causes
devices which are hot unplugged and then hot-replugged to
not have per-device dma_ops set. This causes these devices
to not function correctly. Fixed with this patch.

Reported-by: Andreas Degert <andreas.degert@googlemail.com>
Signed-off-by: Joerg Roedel <joro@8bytes.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/x86/kernel/amd_iommu.c

index bfd75ff5d5bda6083651eaa23cfc86e8f3a843de..d9302b71066c9d08a15209d526447b4e654e9bc0 100644 (file)
@@ -53,6 +53,8 @@ static struct protection_domain *pt_domain;
 
 static struct iommu_ops amd_iommu_ops;
 
+static struct dma_map_ops amd_iommu_dma_ops;
+
 /*
  * general struct to manage commands send to an IOMMU
  */
@@ -1778,18 +1780,20 @@ static int device_change_notifier(struct notifier_block *nb,
 
                domain = domain_for_device(dev);
 
-               /* allocate a protection domain if a device is added */
                dma_domain = find_protection_domain(devid);
-               if (dma_domain)
-                       goto out;
-               dma_domain = dma_ops_domain_alloc();
-               if (!dma_domain)
-                       goto out;
-               dma_domain->target_dev = devid;
+               if (!dma_domain) {
+                       /* allocate a protection domain if a device is added */
+                       dma_domain = dma_ops_domain_alloc();
+                       if (!dma_domain)
+                               goto out;
+                       dma_domain->target_dev = devid;
+
+                       spin_lock_irqsave(&iommu_pd_list_lock, flags);
+                       list_add_tail(&dma_domain->list, &iommu_pd_list);
+                       spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
+               }
 
-               spin_lock_irqsave(&iommu_pd_list_lock, flags);
-               list_add_tail(&dma_domain->list, &iommu_pd_list);
-               spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
+               dev->archdata.dma_ops = &amd_iommu_dma_ops;
 
                break;
        case BUS_NOTIFY_DEL_DEVICE: