aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2012-07-17 05:47:14 -0400
committerJoerg Roedel <joerg.roedel@amd.com>2012-07-17 05:47:14 -0400
commitf9a4f063a88297e361fd6676986cf3e39b22de72 (patch)
tree50067d8fc72cc677db62de68da013039734a0c6c /drivers/iommu
parent9e971a03af736acc6f96c200c2626d3bcb3d6927 (diff)
iommu/tegra: Don't call alloc_pdir with as->lock
Instead of taking as->lock before calling alloc_pdir() and releasing it in that function to allocate memory, just take the lock only in the alloc_pdir function and run the loop without any lock held. This simplifies the complicated lock->unlock->alloc->lock->unlock sequence into alloc->lock->unlock. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/tegra-smmu.c29
1 files changed, 16 insertions, 13 deletions
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 68a15a0d5b8a..541d210cb421 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -553,11 +553,11 @@ static inline void put_signature(struct smmu_as *as,
553#endif 553#endif
554 554
555/* 555/*
556 * Caller must lock/unlock as 556 * Caller must not hold as->lock
557 */ 557 */
558static int alloc_pdir(struct smmu_as *as, unsigned long *flags) 558static int alloc_pdir(struct smmu_as *as)
559{ 559{
560 unsigned long *pdir; 560 unsigned long *pdir, flags;
561 int pdn, err = 0; 561 int pdn, err = 0;
562 u32 val; 562 u32 val;
563 struct smmu_device *smmu = as->smmu; 563 struct smmu_device *smmu = as->smmu;
@@ -565,13 +565,14 @@ static int alloc_pdir(struct smmu_as *as, unsigned long *flags)
565 unsigned int *cnt; 565 unsigned int *cnt;
566 566
567 /* 567 /*
568 * do the allocation outside the as->lock 568 * do the allocation, then grab as->lock
569 */ 569 */
570 spin_unlock_irqrestore(&as->lock, *flags);
571 cnt = devm_kzalloc(smmu->dev, 570 cnt = devm_kzalloc(smmu->dev,
572 sizeof(cnt[0]) * SMMU_PDIR_COUNT, GFP_KERNEL); 571 sizeof(cnt[0]) * SMMU_PDIR_COUNT,
572 GFP_KERNEL);
573 page = alloc_page(GFP_KERNEL | __GFP_DMA); 573 page = alloc_page(GFP_KERNEL | __GFP_DMA);
574 spin_lock_irqsave(&as->lock, *flags); 574
575 spin_lock_irqsave(&as->lock, flags);
575 576
576 if (as->pdir_page) { 577 if (as->pdir_page) {
577 /* We raced, free the redundant */ 578 /* We raced, free the redundant */
@@ -603,9 +604,13 @@ static int alloc_pdir(struct smmu_as *as, unsigned long *flags)
603 smmu_write(smmu, val, SMMU_TLB_FLUSH); 604 smmu_write(smmu, val, SMMU_TLB_FLUSH);
604 FLUSH_SMMU_REGS(as->smmu); 605 FLUSH_SMMU_REGS(as->smmu);
605 606
607 spin_unlock_irqrestore(&as->lock, flags);
608
606 return 0; 609 return 0;
607 610
608err_out: 611err_out:
612 spin_unlock_irqrestore(&as->lock, flags);
613
609 devm_kfree(smmu->dev, cnt); 614 devm_kfree(smmu->dev, cnt);
610 if (page) 615 if (page)
611 __free_page(page); 616 __free_page(page);
@@ -809,13 +814,11 @@ static int smmu_iommu_domain_init(struct iommu_domain *domain)
809 /* Look for a free AS with lock held */ 814 /* Look for a free AS with lock held */
810 for (i = 0; i < smmu->num_as; i++) { 815 for (i = 0; i < smmu->num_as; i++) {
811 as = &smmu->as[i]; 816 as = &smmu->as[i];
812 spin_lock_irqsave(&as->lock, flags);
813 if (!as->pdir_page) { 817 if (!as->pdir_page) {
814 err = alloc_pdir(as, &flags); 818 err = alloc_pdir(as);
815 if (!err) 819 if (!err)
816 goto found; 820 goto found;
817 } 821 }
818 spin_unlock_irqrestore(&as->lock, flags);
819 if (err != -EAGAIN) 822 if (err != -EAGAIN)
820 break; 823 break;
821 } 824 }
@@ -824,7 +827,7 @@ static int smmu_iommu_domain_init(struct iommu_domain *domain)
824 return err; 827 return err;
825 828
826found: 829found:
827 spin_lock(&smmu->lock); 830 spin_lock_irqsave(&smmu->lock, flags);
828 831
829 /* Update PDIR register */ 832 /* Update PDIR register */
830 smmu_write(smmu, SMMU_PTB_ASID_CUR(as->asid), SMMU_PTB_ASID); 833 smmu_write(smmu, SMMU_PTB_ASID_CUR(as->asid), SMMU_PTB_ASID);
@@ -832,12 +835,12 @@ found:
832 SMMU_MK_PDIR(as->pdir_page, as->pdir_attr), SMMU_PTB_DATA); 835 SMMU_MK_PDIR(as->pdir_page, as->pdir_attr), SMMU_PTB_DATA);
833 FLUSH_SMMU_REGS(smmu); 836 FLUSH_SMMU_REGS(smmu);
834 837
835 spin_unlock(&smmu->lock); 838 spin_unlock_irqrestore(&smmu->lock, flags);
836 839
837 spin_unlock_irqrestore(&as->lock, flags);
838 domain->priv = as; 840 domain->priv = as;
839 841
840 dev_dbg(smmu->dev, "smmu_as@%p\n", as); 842 dev_dbg(smmu->dev, "smmu_as@%p\n", as);
843
841 return 0; 844 return 0;
842} 845}
843 846