Skip to content

Commit f4ca529

Browse files
author
Rob Clark
committed
drm/msm: Fix pagetables setup/teardown serialization
An atomic counter is not sufficient, as one task could still be in the process of tearing things down while another task increments the counter back up to one and begins setup again. The race condition existed since commit b145c6e ("drm/msm: Add support to create a local pagetable") but got bigger in commit dbbde63 ("drm/msm: Add PRR support"). Fixes: dbbde63 ("drm/msm: Add PRR support") Fixes: b145c6e ("drm/msm: Add support to create a local pagetable") Signed-off-by: Rob Clark <robin.clark@oss.qualcomm.com> Patchwork: https://patchwork.freedesktop.org/patch/664433/
1 parent 7abb543 commit f4ca529

File tree

1 file changed

+12
-4
lines changed

1 file changed

+12
-4
lines changed

drivers/gpu/drm/msm/msm_iommu.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
struct msm_iommu {
1515
struct msm_mmu base;
1616
struct iommu_domain *domain;
17-
atomic_t pagetables;
17+
18+
struct mutex init_lock; /* protects pagetables counter and prr_page */
19+
int pagetables;
1820
struct page *prr_page;
1921

2022
struct kmem_cache *pt_cache;
@@ -227,7 +229,8 @@ static void msm_iommu_pagetable_destroy(struct msm_mmu *mmu)
227229
* If this is the last attached pagetable for the parent,
228230
* disable TTBR0 in the arm-smmu driver
229231
*/
230-
if (atomic_dec_return(&iommu->pagetables) == 0) {
232+
mutex_lock(&iommu->init_lock);
233+
if (--iommu->pagetables == 0) {
231234
adreno_smmu->set_ttbr0_cfg(adreno_smmu->cookie, NULL);
232235

233236
if (adreno_smmu->set_prr_bit) {
@@ -236,6 +239,7 @@ static void msm_iommu_pagetable_destroy(struct msm_mmu *mmu)
236239
iommu->prr_page = NULL;
237240
}
238241
}
242+
mutex_unlock(&iommu->init_lock);
239243

240244
free_io_pgtable_ops(pagetable->pgtbl_ops);
241245
kfree(pagetable);
@@ -568,9 +572,12 @@ struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent, bool kernel_m
568572
* If this is the first pagetable that we've allocated, send it back to
569573
* the arm-smmu driver as a trigger to set up TTBR0
570574
*/
571-
if (atomic_inc_return(&iommu->pagetables) == 1) {
575+
mutex_lock(&iommu->init_lock);
576+
if (iommu->pagetables++ == 0) {
572577
ret = adreno_smmu->set_ttbr0_cfg(adreno_smmu->cookie, &ttbr0_cfg);
573578
if (ret) {
579+
iommu->pagetables--;
580+
mutex_unlock(&iommu->init_lock);
574581
free_io_pgtable_ops(pagetable->pgtbl_ops);
575582
kfree(pagetable);
576583
return ERR_PTR(ret);
@@ -595,6 +602,7 @@ struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent, bool kernel_m
595602
adreno_smmu->set_prr_bit(adreno_smmu->cookie, true);
596603
}
597604
}
605+
mutex_unlock(&iommu->init_lock);
598606

599607
/* Needed later for TLB flush */
600608
pagetable->parent = parent;
@@ -730,7 +738,7 @@ struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks)
730738
iommu->domain = domain;
731739
msm_mmu_init(&iommu->base, dev, &funcs, MSM_MMU_IOMMU);
732740

733-
atomic_set(&iommu->pagetables, 0);
741+
mutex_init(&iommu->init_lock);
734742

735743
ret = iommu_attach_device(iommu->domain, dev);
736744
if (ret) {

0 commit comments

Comments
 (0)