Commit ab7b2577 authored by Joerg Roedel's avatar Joerg Roedel
Browse files

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: 92d420ec ("iommu/amd: Relax locking in dma_ops path")
Reviewed-by: default avatarFilippo Sironi <sironi@amazon.de>
Reviewed-by: default avatarJerry Snitselaar <jsnitsel@redhat.com>
Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent 45e528d9
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -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);
}

+3 −0
Original line number Diff line number Diff line
@@ -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 */