Commit 606ec90f authored by Sean Paul's avatar Sean Paul

drm/msm/a6xx: Avoid freeing gmu resources multiple times

The driver checks for gmu->mmio as a sign that the device has been
initialized, however there are failures in probe below the mmio init.
If one of those is hit, mmio will be non-null but freed.

In that case, a6xx_gmu_probe will return an error to a6xx_gpu_init which
will in turn call a6xx_gmu_remove which checks gmu->mmio and tries to free
resources for a second time. This causes a great boom.

Fix this by adding an initialized member to gmu which is set on
successful probe and cleared on removal.

Changes in v2:
- None

Cc: Jordan Crouse <jcrouse@codeaurora.org>
Reviewed-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: default avatarSean Paul <seanpaul@chromium.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20190523171653.138678-1-sean@poorly.run
parent a188339c
...@@ -74,7 +74,7 @@ bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu) ...@@ -74,7 +74,7 @@ bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu)
u32 val; u32 val;
/* This can be called from gpu state code so make sure GMU is valid */ /* This can be called from gpu state code so make sure GMU is valid */
if (IS_ERR_OR_NULL(gmu->mmio)) if (!gmu->initialized)
return false; return false;
val = gmu_read(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS); val = gmu_read(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS);
...@@ -90,7 +90,7 @@ bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu) ...@@ -90,7 +90,7 @@ bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu)
u32 val; u32 val;
/* This can be called from gpu state code so make sure GMU is valid */ /* This can be called from gpu state code so make sure GMU is valid */
if (IS_ERR_OR_NULL(gmu->mmio)) if (!gmu->initialized)
return false; return false;
val = gmu_read(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS); val = gmu_read(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS);
...@@ -695,7 +695,7 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu) ...@@ -695,7 +695,7 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
struct a6xx_gmu *gmu = &a6xx_gpu->gmu; struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
int status, ret; int status, ret;
if (WARN(!gmu->mmio, "The GMU is not set up yet\n")) if (WARN(!gmu->initialized, "The GMU is not set up yet\n"))
return 0; return 0;
gmu->hung = false; gmu->hung = false;
...@@ -765,7 +765,7 @@ bool a6xx_gmu_isidle(struct a6xx_gmu *gmu) ...@@ -765,7 +765,7 @@ bool a6xx_gmu_isidle(struct a6xx_gmu *gmu)
{ {
u32 reg; u32 reg;
if (!gmu->mmio) if (!gmu->initialized)
return true; return true;
reg = gmu_read(gmu, REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS); reg = gmu_read(gmu, REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS);
...@@ -1227,7 +1227,7 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu) ...@@ -1227,7 +1227,7 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
{ {
struct a6xx_gmu *gmu = &a6xx_gpu->gmu; struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
if (IS_ERR_OR_NULL(gmu->mmio)) if (!gmu->initialized)
return; return;
a6xx_gmu_stop(a6xx_gpu); a6xx_gmu_stop(a6xx_gpu);
...@@ -1245,6 +1245,8 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu) ...@@ -1245,6 +1245,8 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
iommu_detach_device(gmu->domain, gmu->dev); iommu_detach_device(gmu->domain, gmu->dev);
iommu_domain_free(gmu->domain); iommu_domain_free(gmu->domain);
gmu->initialized = false;
} }
int a6xx_gmu_probe(struct a6xx_gpu *a6xx_gpu, struct device_node *node) int a6xx_gmu_probe(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
...@@ -1309,6 +1311,8 @@ int a6xx_gmu_probe(struct a6xx_gpu *a6xx_gpu, struct device_node *node) ...@@ -1309,6 +1311,8 @@ int a6xx_gmu_probe(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
/* Set up the HFI queues */ /* Set up the HFI queues */
a6xx_hfi_init(gmu); a6xx_hfi_init(gmu);
gmu->initialized = true;
return 0; return 0;
err: err:
a6xx_gmu_memory_free(gmu, gmu->hfi); a6xx_gmu_memory_free(gmu, gmu->hfi);
......
...@@ -75,6 +75,7 @@ struct a6xx_gmu { ...@@ -75,6 +75,7 @@ struct a6xx_gmu {
struct a6xx_hfi_queue queues[2]; struct a6xx_hfi_queue queues[2];
bool initialized;
bool hung; bool hung;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment