Skip to content

Commit f6c0bfc

Browse files
committed
iommu/amd: Take domain->lock for complete attach/detach path
The code-paths before __attach_device() and __detach_device() are called also access and modify domain state, so take the domain lock there too. This allows to get rid of the __detach_device() function. Fixes: 92d420e ("iommu/amd: Relax locking in dma_ops path") Reviewed-by: Filippo Sironi <[email protected]> Reviewed-by: Jerry Snitselaar <[email protected]> Signed-off-by: Joerg Roedel <[email protected]>
1 parent 3a11905 commit f6c0bfc

File tree

1 file changed

+26
-39
lines changed

1 file changed

+26
-39
lines changed

drivers/iommu/amd_iommu.c

Lines changed: 26 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2079,27 +2079,13 @@ static void do_detach(struct iommu_dev_data *dev_data)
20792079
static int __attach_device(struct iommu_dev_data *dev_data,
20802080
struct protection_domain *domain)
20812081
{
2082-
unsigned long flags;
2083-
int ret;
2084-
2085-
/* lock domain */
2086-
spin_lock_irqsave(&domain->lock, flags);
2087-
2088-
ret = -EBUSY;
20892082
if (dev_data->domain != NULL)
2090-
goto out_unlock;
2083+
return -EBUSY;
20912084

20922085
/* Attach alias group root */
20932086
do_attach(dev_data, domain);
20942087

2095-
ret = 0;
2096-
2097-
out_unlock:
2098-
2099-
/* ready */
2100-
spin_unlock_irqrestore(&domain->lock, flags);
2101-
2102-
return ret;
2088+
return 0;
21032089
}
21042090

21052091

@@ -2181,21 +2167,25 @@ static int attach_device(struct device *dev,
21812167
{
21822168
struct pci_dev *pdev;
21832169
struct iommu_dev_data *dev_data;
2170+
unsigned long flags;
21842171
int ret;
21852172

2173+
spin_lock_irqsave(&domain->lock, flags);
2174+
21862175
dev_data = get_dev_data(dev);
21872176

21882177
if (!dev_is_pci(dev))
21892178
goto skip_ats_check;
21902179

21912180
pdev = to_pci_dev(dev);
21922181
if (domain->flags & PD_IOMMUV2_MASK) {
2182+
ret = -EINVAL;
21932183
if (!dev_data->passthrough)
2194-
return -EINVAL;
2184+
goto out;
21952185

21962186
if (dev_data->iommu_v2) {
21972187
if (pdev_iommuv2_enable(pdev) != 0)
2198-
return -EINVAL;
2188+
goto out;
21992189

22002190
dev_data->ats.enabled = true;
22012191
dev_data->ats.qdep = pci_ats_queue_depth(pdev);
@@ -2219,24 +2209,10 @@ static int attach_device(struct device *dev,
22192209

22202210
domain_flush_complete(domain);
22212211

2222-
return ret;
2223-
}
2224-
2225-
/*
2226-
* Removes a device from a protection domain (unlocked)
2227-
*/
2228-
static void __detach_device(struct iommu_dev_data *dev_data)
2229-
{
2230-
struct protection_domain *domain;
2231-
unsigned long flags;
2232-
2233-
domain = dev_data->domain;
2234-
2235-
spin_lock_irqsave(&domain->lock, flags);
2236-
2237-
do_detach(dev_data);
2238-
2212+
out:
22392213
spin_unlock_irqrestore(&domain->lock, flags);
2214+
2215+
return ret;
22402216
}
22412217

22422218
/*
@@ -2246,30 +2222,36 @@ static void detach_device(struct device *dev)
22462222
{
22472223
struct protection_domain *domain;
22482224
struct iommu_dev_data *dev_data;
2225+
unsigned long flags;
22492226

22502227
dev_data = get_dev_data(dev);
22512228
domain = dev_data->domain;
22522229

2230+
spin_lock_irqsave(&domain->lock, flags);
2231+
22532232
/*
22542233
* First check if the device is still attached. It might already
22552234
* be detached from its domain because the generic
22562235
* iommu_detach_group code detached it and we try again here in
22572236
* our alias handling.
22582237
*/
22592238
if (WARN_ON(!dev_data->domain))
2260-
return;
2239+
goto out;
22612240

2262-
__detach_device(dev_data);
2241+
do_detach(dev_data);
22632242

22642243
if (!dev_is_pci(dev))
2265-
return;
2244+
goto out;
22662245

22672246
if (domain->flags & PD_IOMMUV2_MASK && dev_data->iommu_v2)
22682247
pdev_iommuv2_disable(to_pci_dev(dev));
22692248
else if (dev_data->ats.enabled)
22702249
pci_disable_ats(to_pci_dev(dev));
22712250

22722251
dev_data->ats.enabled = false;
2252+
2253+
out:
2254+
spin_unlock_irqrestore(&domain->lock, flags);
22732255
}
22742256

22752257
static int amd_iommu_add_device(struct device *dev)
@@ -2904,13 +2886,18 @@ int __init amd_iommu_init_dma_ops(void)
29042886
static void cleanup_domain(struct protection_domain *domain)
29052887
{
29062888
struct iommu_dev_data *entry;
2889+
unsigned long flags;
2890+
2891+
spin_lock_irqsave(&domain->lock, flags);
29072892

29082893
while (!list_empty(&domain->dev_list)) {
29092894
entry = list_first_entry(&domain->dev_list,
29102895
struct iommu_dev_data, list);
29112896
BUG_ON(!entry->domain);
2912-
__detach_device(entry);
2897+
do_detach(entry);
29132898
}
2899+
2900+
spin_unlock_irqrestore(&domain->lock, flags);
29142901
}
29152902

29162903
static void protection_domain_free(struct protection_domain *domain)

0 commit comments

Comments
 (0)