iommu/ipmmu-vmsa: Rereserving a free context before setting up a pagetable
Reserving a free context is both quicker and more likely to fail (due to limited hardware resources) than setting up a pagetable. What is more the pagetable init/cleanup code could require the context to be set up. Signed-off-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com> CC: Robin Murphy <robin.murphy@arm.com> CC: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Robin Murphy <robin.murphy@arm.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> CC: Joerg Roedel <joro@8bytes.org> Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:

committed by
Joerg Roedel

parent
7af9a5fdb9
commit
a175a67d30
@@ -324,6 +324,19 @@ static int ipmmu_domain_allocate_context(struct ipmmu_vmsa_device *mmu,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ipmmu_domain_free_context(struct ipmmu_vmsa_device *mmu,
|
||||||
|
unsigned int context_id)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&mmu->lock, flags);
|
||||||
|
|
||||||
|
clear_bit(context_id, mmu->ctx);
|
||||||
|
mmu->domains[context_id] = NULL;
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&mmu->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain)
|
static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain)
|
||||||
{
|
{
|
||||||
u64 ttbr;
|
u64 ttbr;
|
||||||
@@ -353,22 +366,22 @@ static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain)
|
|||||||
*/
|
*/
|
||||||
domain->cfg.iommu_dev = domain->mmu->dev;
|
domain->cfg.iommu_dev = domain->mmu->dev;
|
||||||
|
|
||||||
domain->iop = alloc_io_pgtable_ops(ARM_32_LPAE_S1, &domain->cfg,
|
|
||||||
domain);
|
|
||||||
if (!domain->iop)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find an unused context.
|
* Find an unused context.
|
||||||
*/
|
*/
|
||||||
ret = ipmmu_domain_allocate_context(domain->mmu, domain);
|
ret = ipmmu_domain_allocate_context(domain->mmu, domain);
|
||||||
if (ret == IPMMU_CTX_MAX) {
|
if (ret == IPMMU_CTX_MAX)
|
||||||
free_io_pgtable_ops(domain->iop);
|
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
|
||||||
|
|
||||||
domain->context_id = ret;
|
domain->context_id = ret;
|
||||||
|
|
||||||
|
domain->iop = alloc_io_pgtable_ops(ARM_32_LPAE_S1, &domain->cfg,
|
||||||
|
domain);
|
||||||
|
if (!domain->iop) {
|
||||||
|
ipmmu_domain_free_context(domain->mmu, domain->context_id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
/* TTBR0 */
|
/* TTBR0 */
|
||||||
ttbr = domain->cfg.arm_lpae_s1_cfg.ttbr[0];
|
ttbr = domain->cfg.arm_lpae_s1_cfg.ttbr[0];
|
||||||
ipmmu_ctx_write(domain, IMTTLBR0, ttbr);
|
ipmmu_ctx_write(domain, IMTTLBR0, ttbr);
|
||||||
@@ -409,19 +422,6 @@ static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ipmmu_domain_free_context(struct ipmmu_vmsa_device *mmu,
|
|
||||||
unsigned int context_id)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&mmu->lock, flags);
|
|
||||||
|
|
||||||
clear_bit(context_id, mmu->ctx);
|
|
||||||
mmu->domains[context_id] = NULL;
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&mmu->lock, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ipmmu_domain_destroy_context(struct ipmmu_vmsa_domain *domain)
|
static void ipmmu_domain_destroy_context(struct ipmmu_vmsa_domain *domain)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user