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: 92d420ec02 ("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>
This commit is contained in:
Joerg Roedel 2019-09-25 15:22:59 +02:00
parent 45e528d9c4
commit ab7b2577f0
2 changed files with 12 additions and 0 deletions

View File

@ -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 @@ static int attach_device(struct device *dev,
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);
}

View File

@ -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 */