Merge "msm: kgsl: Fix null pointer dereference in deferred_destroy"

This commit is contained in:
qctecmdr 2022-06-08 00:15:56 -07:00 committed by Gerrit - the friendly Code Review server
commit 9d152e5c34

View File

@ -1229,6 +1229,24 @@ static u64 kgsl_iommu_get_ttbr0(struct kgsl_pagetable *pagetable)
return pt->ttbr0; return pt->ttbr0;
} }
/* Set TTBR0 for the given context with the specific configuration */
static void kgsl_iommu_set_ttbr0(struct kgsl_iommu_context *context,
struct kgsl_mmu *mmu, const struct io_pgtable_cfg *pgtbl_cfg)
{
struct adreno_smmu_priv *adreno_smmu;
/* Quietly return if the context doesn't have a domain */
if (!context->domain)
return;
adreno_smmu = dev_get_drvdata(&context->pdev->dev);
/* Enable CX and clocks before we call into SMMU to setup registers */
kgsl_iommu_enable_clk(mmu);
adreno_smmu->set_ttbr0_cfg(adreno_smmu->cookie, pgtbl_cfg);
kgsl_iommu_disable_clk(mmu);
}
/* FIXME: This is broken for LPAC. For now return the default context bank */ /* FIXME: This is broken for LPAC. For now return the default context bank */
static int kgsl_iommu_get_context_bank(struct kgsl_pagetable *pt) static int kgsl_iommu_get_context_bank(struct kgsl_pagetable *pt)
{ {
@ -1241,9 +1259,6 @@ static int kgsl_iommu_get_context_bank(struct kgsl_pagetable *pt)
static void kgsl_iommu_destroy_default_pagetable(struct kgsl_pagetable *pagetable) static void kgsl_iommu_destroy_default_pagetable(struct kgsl_pagetable *pagetable)
{ {
struct kgsl_device *device = KGSL_MMU_DEVICE(pagetable->mmu); struct kgsl_device *device = KGSL_MMU_DEVICE(pagetable->mmu);
struct kgsl_iommu *iommu = to_kgsl_iommu(pagetable);
struct kgsl_iommu_context *context = &iommu->user_context;
struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(&context->pdev->dev);
struct kgsl_iommu_pt *pt = to_iommu_pt(pagetable); struct kgsl_iommu_pt *pt = to_iommu_pt(pagetable);
struct kgsl_global_memdesc *md; struct kgsl_global_memdesc *md;
@ -1254,8 +1269,6 @@ static void kgsl_iommu_destroy_default_pagetable(struct kgsl_pagetable *pagetabl
kgsl_iommu_default_unmap(pagetable, &md->memdesc); kgsl_iommu_default_unmap(pagetable, &md->memdesc);
} }
adreno_smmu->set_ttbr0_cfg(adreno_smmu->cookie, NULL);
kfree(pt); kfree(pt);
} }
@ -1325,25 +1338,6 @@ static int kgsl_iopgtbl_alloc(struct kgsl_iommu_context *ctx, struct kgsl_iommu_
return 0; return 0;
} }
/* Enable TTBR0 for the given context with the specific configuration */
static void kgsl_iommu_enable_ttbr0(struct kgsl_iommu_context *context,
struct kgsl_iommu_pt *pt)
{
struct adreno_smmu_priv *adreno_smmu;
struct kgsl_mmu *mmu = pt->base.mmu;
/* Quietly return if the context doesn't have a domain */
if (!context->domain)
return;
adreno_smmu = dev_get_drvdata(&context->pdev->dev);
/* Enable CX and clocks before we call into SMMU to setup registers */
kgsl_iommu_enable_clk(mmu);
adreno_smmu->set_ttbr0_cfg(adreno_smmu->cookie, &pt->info.cfg);
kgsl_iommu_disable_clk(mmu);
}
static struct kgsl_pagetable *kgsl_iommu_default_pagetable(struct kgsl_mmu *mmu) static struct kgsl_pagetable *kgsl_iommu_default_pagetable(struct kgsl_mmu *mmu)
{ {
struct kgsl_iommu *iommu = &mmu->iommu; struct kgsl_iommu *iommu = &mmu->iommu;
@ -1529,11 +1523,20 @@ static void kgsl_iommu_close(struct kgsl_mmu *mmu)
/* First put away the default pagetables */ /* First put away the default pagetables */
kgsl_mmu_putpagetable(mmu->defaultpagetable); kgsl_mmu_putpagetable(mmu->defaultpagetable);
mmu->defaultpagetable = NULL;
kgsl_mmu_putpagetable(mmu->securepagetable); kgsl_mmu_putpagetable(mmu->securepagetable);
/*
* Flush the workqueue to ensure pagetables are
* destroyed before proceeding further
*/
flush_workqueue(kgsl_driver.workqueue);
mmu->defaultpagetable = NULL;
mmu->securepagetable = NULL; mmu->securepagetable = NULL;
kgsl_iommu_set_ttbr0(&iommu->lpac_context, mmu, NULL);
kgsl_iommu_set_ttbr0(&iommu->user_context, mmu, NULL);
/* Next, detach the context banks */ /* Next, detach the context banks */
kgsl_iommu_detach_context(&iommu->user_context); kgsl_iommu_detach_context(&iommu->user_context);
kgsl_iommu_detach_context(&iommu->lpac_context); kgsl_iommu_detach_context(&iommu->lpac_context);
@ -2222,6 +2225,7 @@ static int iommu_probe_user_context(struct kgsl_device *device,
{ {
struct kgsl_iommu *iommu = KGSL_IOMMU(device); struct kgsl_iommu *iommu = KGSL_IOMMU(device);
struct kgsl_mmu *mmu = &device->mmu; struct kgsl_mmu *mmu = &device->mmu;
struct kgsl_iommu_pt *pt;
int ret; int ret;
ret = kgsl_iommu_setup_context(mmu, node, &iommu->user_context, ret = kgsl_iommu_setup_context(mmu, node, &iommu->user_context,
@ -2247,14 +2251,14 @@ static int iommu_probe_user_context(struct kgsl_device *device,
if (!test_bit(KGSL_MMU_IOPGTABLE, &mmu->features)) if (!test_bit(KGSL_MMU_IOPGTABLE, &mmu->features))
return 0; return 0;
pt = to_iommu_pt(mmu->defaultpagetable);
/* Enable TTBR0 on the default and LPAC contexts */ /* Enable TTBR0 on the default and LPAC contexts */
kgsl_iommu_enable_ttbr0(&iommu->user_context, kgsl_iommu_set_ttbr0(&iommu->user_context, mmu, &pt->info.cfg);
to_iommu_pt(mmu->defaultpagetable));
set_smmu_aperture(device, &iommu->user_context); set_smmu_aperture(device, &iommu->user_context);
kgsl_iommu_enable_ttbr0(&iommu->lpac_context, kgsl_iommu_set_ttbr0(&iommu->lpac_context, mmu, &pt->info.cfg);
to_iommu_pt(mmu->defaultpagetable));
/* FIXME: set LPAC SMMU aperture */ /* FIXME: set LPAC SMMU aperture */
return 0; return 0;