The change referenced by the Fixes tag releases the indirect CSD GEM
reference from v3d_cpu_job_free(), the CPU job kref destructor.

However, the indirect CSD GEM object is looked up while parsing CPU job
extensions, before v3d_job_init() has successfully installed that
destructor. If v3d_setup_csd_jobs_and_bos() fails, if a later extension
fails, or if v3d_job_init() itself fails, the CPU job can be cleaned up
or deallocated without running v3d_cpu_job_free().

Drop the indirect CSD GEM reference on those pre-init error paths and
clear the pointer after doing so.

Fixes: 6eb6e5acafa4 ("drm/v3d: Release indirect CSD GEM reference on CPU job 
free")
Signed-off-by: Guangshuo Li <[email protected]>
---
 drivers/gpu/drm/v3d/v3d_submit.c | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/v3d/v3d_submit.c b/drivers/gpu/drm/v3d/v3d_submit.c
index 1db43c6a078d..8ed95a203810 100644
--- a/drivers/gpu/drm/v3d/v3d_submit.c
+++ b/drivers/gpu/drm/v3d/v3d_submit.c
@@ -476,6 +476,7 @@ v3d_get_cpu_indirect_csd_params(struct drm_file *file_priv,
        struct v3d_dev *v3d = v3d_priv->v3d;
        struct drm_v3d_indirect_csd indirect_csd;
        struct v3d_indirect_csd_info *info = &job->indirect_csd;
+       int ret;
 
        if (!v3d_validate_cpu_job(file_priv, job))
                return -EINVAL;
@@ -496,9 +497,15 @@ v3d_get_cpu_indirect_csd_params(struct drm_file *file_priv,
 
        info->indirect = drm_gem_object_lookup(file_priv, 
indirect_csd.indirect);
 
-       return v3d_setup_csd_jobs_and_bos(file_priv, v3d, &indirect_csd.submit,
-                                         &info->job, &info->clean_job,
-                                         NULL, &info->acquire_ctx);
+       ret = v3d_setup_csd_jobs_and_bos(file_priv, v3d, &indirect_csd.submit,
+                                        &info->job, &info->clean_job,
+                                        NULL, &info->acquire_ctx);
+       if (ret && info->indirect) {
+               drm_gem_object_put(info->indirect);
+               info->indirect = NULL;
+       }
+
+       return ret;
 }
 
 /* Get data for the query timestamp job submission. */
@@ -1311,6 +1318,10 @@ v3d_submit_cpu_ioctl(struct drm_device *dev, void *data,
                ret = v3d_get_extensions(file_priv, args->extensions, &se, 
cpu_job);
                if (ret) {
                        drm_dbg(dev, "Failed to get extensions.\n");
+                       if (cpu_job->indirect_csd.indirect) {
+                               
drm_gem_object_put(cpu_job->indirect_csd.indirect);
+                               cpu_job->indirect_csd.indirect = NULL;
+                       }
                        goto fail;
                }
        }
@@ -1333,6 +1344,10 @@ v3d_submit_cpu_ioctl(struct drm_device *dev, void *data,
        ret = v3d_job_init(v3d, file_priv, &cpu_job->base,
                           v3d_cpu_job_free, 0, &se, V3D_CPU);
        if (ret) {
+               if (cpu_job->indirect_csd.indirect) {
+                       drm_gem_object_put(cpu_job->indirect_csd.indirect);
+                       cpu_job->indirect_csd.indirect = NULL;
+               }
                v3d_job_deallocate((void *)&cpu_job);
                goto fail;
        }
-- 
2.43.0

Reply via email to