diff options
Diffstat (limited to 'drivers/gpu/drm/msm/msm_iommu.c')
| -rw-r--r-- | drivers/gpu/drm/msm/msm_iommu.c | 16 | 
1 files changed, 12 insertions, 4 deletions
| diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c index 55c29f49b788..76cdd5ea06a0 100644 --- a/drivers/gpu/drm/msm/msm_iommu.c +++ b/drivers/gpu/drm/msm/msm_iommu.c @@ -14,7 +14,9 @@  struct msm_iommu {  	struct msm_mmu base;  	struct iommu_domain *domain; -	atomic_t pagetables; + +	struct mutex init_lock;  /* protects pagetables counter and prr_page */ +	int pagetables;  	struct page *prr_page;  	struct kmem_cache *pt_cache; @@ -227,7 +229,8 @@ static void msm_iommu_pagetable_destroy(struct msm_mmu *mmu)  	 * If this is the last attached pagetable for the parent,  	 * disable TTBR0 in the arm-smmu driver  	 */ -	if (atomic_dec_return(&iommu->pagetables) == 0) { +	mutex_lock(&iommu->init_lock); +	if (--iommu->pagetables == 0) {  		adreno_smmu->set_ttbr0_cfg(adreno_smmu->cookie, NULL);  		if (adreno_smmu->set_prr_bit) { @@ -236,6 +239,7 @@ static void msm_iommu_pagetable_destroy(struct msm_mmu *mmu)  			iommu->prr_page = NULL;  		}  	} +	mutex_unlock(&iommu->init_lock);  	free_io_pgtable_ops(pagetable->pgtbl_ops);  	kfree(pagetable); @@ -568,9 +572,12 @@ struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent, bool kernel_m  	 * If this is the first pagetable that we've allocated, send it back to  	 * the arm-smmu driver as a trigger to set up TTBR0  	 */ -	if (atomic_inc_return(&iommu->pagetables) == 1) { +	mutex_lock(&iommu->init_lock); +	if (iommu->pagetables++ == 0) {  		ret = adreno_smmu->set_ttbr0_cfg(adreno_smmu->cookie, &ttbr0_cfg);  		if (ret) { +			iommu->pagetables--; +			mutex_unlock(&iommu->init_lock);  			free_io_pgtable_ops(pagetable->pgtbl_ops);  			kfree(pagetable);  			return ERR_PTR(ret); @@ -595,6 +602,7 @@ struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent, bool kernel_m  			adreno_smmu->set_prr_bit(adreno_smmu->cookie, true);  		}  	} +	mutex_unlock(&iommu->init_lock);  	/* Needed later for TLB flush */  	pagetable->parent = parent; @@ -730,7 +738,7 @@ struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks)  	iommu->domain = domain;  	msm_mmu_init(&iommu->base, dev, &funcs, MSM_MMU_IOMMU); -	atomic_set(&iommu->pagetables, 0); +	mutex_init(&iommu->init_lock);  	ret = iommu_attach_device(iommu->domain, dev);  	if (ret) { | 
