Skip to content

Commit

Permalink
iommu/amd: Refactor amd_iommu_domain_enable_v2 to remove locking
Browse files Browse the repository at this point in the history
The current function to enable IOMMU v2 also lock the domain.
In order to reuse the same code in different code path, in which
the domain has already been locked, refactor the function to separate
the locking from the enabling logic.

Co-developed-by: Vasant Hegde <vasant.hegde@amd.com>
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Link: https://lore.kernel.org/r/20220825063939.8360-5-vasant.hegde@amd.com
Signed-off-by: Joerg Roedel <jroedel@suse.de>
  • Loading branch information
Suravee Suthikulpanit authored and Joerg Roedel committed Sep 7, 2022
1 parent 6b080c4 commit 43312b7
Showing 1 changed file with 27 additions and 19 deletions.
46 changes: 27 additions & 19 deletions drivers/iommu/amd/iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ struct iommu_cmd {
struct kmem_cache *amd_iommu_irq_cache;

static void detach_device(struct device *dev);
static int domain_enable_v2(struct protection_domain *domain, int pasids);

/****************************************************************************
*
Expand Down Expand Up @@ -2450,11 +2451,10 @@ void amd_iommu_domain_direct_map(struct iommu_domain *dom)
}
EXPORT_SYMBOL(amd_iommu_domain_direct_map);

int amd_iommu_domain_enable_v2(struct iommu_domain *dom, int pasids)
/* Note: This function expects iommu_domain->lock to be held prior calling the function. */
static int domain_enable_v2(struct protection_domain *domain, int pasids)
{
struct protection_domain *domain = to_pdomain(dom);
unsigned long flags;
int levels, ret;
int levels;

/* Number of GCR3 table levels required */
for (levels = 0; (pasids - 1) & ~0x1ff; pasids >>= 9)
Expand All @@ -2463,32 +2463,40 @@ int amd_iommu_domain_enable_v2(struct iommu_domain *dom, int pasids)
if (levels > amd_iommu_max_glx_val)
return -EINVAL;

spin_lock_irqsave(&domain->lock, flags);
domain->gcr3_tbl = (void *)get_zeroed_page(GFP_ATOMIC);
if (domain->gcr3_tbl == NULL)
return -ENOMEM;

domain->glx = levels;
domain->flags |= PD_IOMMUV2_MASK;

amd_iommu_domain_update(domain);

return 0;
}

int amd_iommu_domain_enable_v2(struct iommu_domain *dom, int pasids)
{
struct protection_domain *pdom = to_pdomain(dom);
unsigned long flags;
int ret;

spin_lock_irqsave(&pdom->lock, flags);

/*
* Save us all sanity checks whether devices already in the
* domain support IOMMUv2. Just force that the domain has no
* devices attached when it is switched into IOMMUv2 mode.
*/
ret = -EBUSY;
if (domain->dev_cnt > 0 || domain->flags & PD_IOMMUV2_MASK)
goto out;

ret = -ENOMEM;
domain->gcr3_tbl = (void *)get_zeroed_page(GFP_ATOMIC);
if (domain->gcr3_tbl == NULL)
if (pdom->dev_cnt > 0 || pdom->flags & PD_IOMMUV2_MASK)
goto out;

domain->glx = levels;
domain->flags |= PD_IOMMUV2_MASK;

amd_iommu_domain_update(domain);

ret = 0;
if (!pdom->gcr3_tbl)
ret = domain_enable_v2(pdom, pasids);

out:
spin_unlock_irqrestore(&domain->lock, flags);

spin_unlock_irqrestore(&pdom->lock, flags);
return ret;
}
EXPORT_SYMBOL(amd_iommu_domain_enable_v2);
Expand Down

0 comments on commit 43312b7

Please sign in to comment.