]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
drm/msm/a6xx: Avoid freeing gmu resources multiple times
authorSean Paul <seanpaul@chromium.org>
Thu, 23 May 2019 17:16:40 +0000 (13:16 -0400)
committerSean Paul <seanpaul@chromium.org>
Fri, 24 May 2019 13:52:40 +0000 (09:52 -0400)
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: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20190523171653.138678-1-sean@poorly.run
drivers/gpu/drm/msm/adreno/a6xx_gmu.c
drivers/gpu/drm/msm/adreno/a6xx_gmu.h

index 38e2cfa9cec797f41fc6ca173c3140a9b95564ec..aa84edb25d91363ed4e48288097bd0acc83b3a83 100644 (file)
@@ -74,7 +74,7 @@ bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu)
        u32 val;
 
        /* 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;
 
        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)
        u32 val;
 
        /* 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;
 
        val = gmu_read(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS);
@@ -695,7 +695,7 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
        struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
        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;
 
        gmu->hung = false;
@@ -765,7 +765,7 @@ bool a6xx_gmu_isidle(struct a6xx_gmu *gmu)
 {
        u32 reg;
 
-       if (!gmu->mmio)
+       if (!gmu->initialized)
                return true;
 
        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)
 {
        struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
 
-       if (IS_ERR_OR_NULL(gmu->mmio))
+       if (!gmu->initialized)
                return;
 
        a6xx_gmu_stop(a6xx_gpu);
@@ -1245,6 +1245,8 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
        iommu_detach_device(gmu->domain, gmu->dev);
 
        iommu_domain_free(gmu->domain);
+
+       gmu->initialized = false;
 }
 
 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 */
        a6xx_hfi_init(gmu);
 
+       gmu->initialized = true;
+
        return 0;
 err:
        a6xx_gmu_memory_free(gmu, gmu->hfi);
index bedd8e6a63aa2d42d8461a1921b770799c94feb3..39a26dd6367440d77f3b95bccbeadf61ce717f26 100644 (file)
@@ -75,6 +75,7 @@ struct a6xx_gmu {
 
        struct a6xx_hfi_queue queues[2];
 
+       bool initialized;
        bool hung;
 };