iommu/ipmmu-vmsa: Rereserving a free context before setting up a pagetable
authorOleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
Wed, 23 Aug 2017 14:31:42 +0000 (17:31 +0300)
committerJoerg Roedel <jroedel@suse.de>
Wed, 30 Aug 2017 13:10:46 +0000 (15:10 +0200)
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>
drivers/iommu/ipmmu-vmsa.c

index 5a350582f359ae2394bcb97367125aedf2e07afb..1711fd306d33cb05567d9568f022a1104b3cb1dd 100644 (file)
@@ -324,6 +324,19 @@ static int ipmmu_domain_allocate_context(struct ipmmu_vmsa_device *mmu,
        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)
 {
        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->iop = alloc_io_pgtable_ops(ARM_32_LPAE_S1, &domain->cfg,
-                                          domain);
-       if (!domain->iop)
-               return -EINVAL;
-
        /*
         * Find an unused context.
         */
        ret = ipmmu_domain_allocate_context(domain->mmu, domain);
-       if (ret == IPMMU_CTX_MAX) {
-               free_io_pgtable_ops(domain->iop);
+       if (ret == IPMMU_CTX_MAX)
                return -EBUSY;
-       }
 
        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 */
        ttbr = domain->cfg.arm_lpae_s1_cfg.ttbr[0];
        ipmmu_ctx_write(domain, IMTTLBR0, ttbr);
@@ -409,19 +422,6 @@ static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain)
        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)
 {
        /*