summaryrefslogtreecommitdiff
path: root/drivers/iommu
diff options
context:
space:
mode:
authorJoerg Roedel <jroedel@suse.de>2019-09-25 16:22:59 +0300
committerJoerg Roedel <jroedel@suse.de>2019-09-28 15:44:04 +0300
commitab7b2577f0d119052b98b8d913bad369ac2760eb (patch)
treefb3c380fff0299866ebdc89fd52010d1bc4782f8 /drivers/iommu
parent45e528d9c479aeef2d3d1db1e619b243f91e324f (diff)
downloadlinux-ab7b2577f0d119052b98b8d913bad369ac2760eb.tar.xz
iommu/amd: Lock dev_data in attach/detach code paths
Make sure that attaching a detaching a device can't race against each other and protect the iommu_dev_data with a spin_lock in these code paths. Fixes: 92d420ec028d ("iommu/amd: Relax locking in dma_ops path") Reviewed-by: Filippo Sironi <sironi@amazon.de> Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/amd_iommu.c9
-rw-r--r--drivers/iommu/amd_iommu_types.h3
2 files changed, 12 insertions, 0 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 459247c32dc0..bac4e20a5919 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -201,6 +201,7 @@ static struct iommu_dev_data *alloc_dev_data(u16 devid)
if (!dev_data)
return NULL;
+ spin_lock_init(&dev_data->lock);
dev_data->devid = devid;
ratelimit_default_init(&dev_data->rs);
@@ -2157,6 +2158,8 @@ static int attach_device(struct device *dev,
dev_data = get_dev_data(dev);
+ spin_lock(&dev_data->lock);
+
ret = -EBUSY;
if (dev_data->domain != NULL)
goto out;
@@ -2199,6 +2202,8 @@ skip_ats_check:
domain_flush_complete(domain);
out:
+ spin_unlock(&dev_data->lock);
+
spin_unlock_irqrestore(&domain->lock, flags);
return ret;
@@ -2218,6 +2223,8 @@ static void detach_device(struct device *dev)
spin_lock_irqsave(&domain->lock, flags);
+ spin_lock(&dev_data->lock);
+
/*
* First check if the device is still attached. It might already
* be detached from its domain because the generic
@@ -2240,6 +2247,8 @@ static void detach_device(struct device *dev)
dev_data->ats.enabled = false;
out:
+ spin_unlock(&dev_data->lock);
+
spin_unlock_irqrestore(&domain->lock, flags);
}
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index 0186501ab971..c9c1612d52e0 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -633,6 +633,9 @@ struct devid_map {
* This struct contains device specific data for the IOMMU
*/
struct iommu_dev_data {
+ /*Protect against attach/detach races */
+ spinlock_t lock;
+
struct list_head list; /* For domain->dev_list */
struct llist_node dev_data_list; /* For global dev_data_list */
struct protection_domain *domain; /* Domain the device is bound to */