]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
accel: ethosu: Fix job submit error clean-up refcount underflows
authorRob Herring (Arm) <robh@kernel.org>
Wed, 18 Feb 2026 22:21:55 +0000 (16:21 -0600)
committerRob Herring (Arm) <robh@kernel.org>
Thu, 5 Mar 2026 21:21:17 +0000 (15:21 -0600)
If the job submit fails before adding the job to the scheduler queue
such as when the GEM buffer bounds checks fail, then doing a
ethosu_job_put() results in a pm_runtime_put_autosuspend() without the
corresponding pm_runtime_resume_and_get(). The dma_fence_put()'s are
also unnecessary, but seem to be harmless.

Split the ethosu_job_cleanup() function into 2 parts for the before
and after the job is queued.

Fixes: 5a5e9c0228e6 ("accel: Add Arm Ethos-U NPU driver")
Reviewed-and-Tested-by: Anders Roxell <anders.roxell@linaro.org>
Link: https://patch.msgid.link/20260218-ethos-fixes-v1-1-be3fa3ea9a30@kernel.org
Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
drivers/accel/ethosu/ethosu_job.c

index 8598a36343407f01adfd9dea0917d762df401bb3..ec85f41567440322e1bd3625d7353f13e05150cc 100644 (file)
@@ -143,23 +143,29 @@ out:
        return ret;
 }
 
+static void ethosu_job_err_cleanup(struct ethosu_job *job)
+{
+       unsigned int i;
+
+       for (i = 0; i < job->region_cnt; i++)
+               drm_gem_object_put(job->region_bo[i]);
+
+       drm_gem_object_put(job->cmd_bo);
+
+       kfree(job);
+}
+
 static void ethosu_job_cleanup(struct kref *ref)
 {
        struct ethosu_job *job = container_of(ref, struct ethosu_job,
                                                refcount);
-       unsigned int i;
 
        pm_runtime_put_autosuspend(job->dev->base.dev);
 
        dma_fence_put(job->done_fence);
        dma_fence_put(job->inference_done_fence);
 
-       for (i = 0; i < job->region_cnt; i++)
-               drm_gem_object_put(job->region_bo[i]);
-
-       drm_gem_object_put(job->cmd_bo);
-
-       kfree(job);
+       ethosu_job_err_cleanup(job);
 }
 
 static void ethosu_job_put(struct ethosu_job *job)
@@ -454,12 +460,16 @@ static int ethosu_ioctl_submit_job(struct drm_device *dev, struct drm_file *file
                }
        }
        ret = ethosu_job_push(ejob);
+       if (!ret) {
+               ethosu_job_put(ejob);
+               return 0;
+       }
 
 out_cleanup_job:
        if (ret)
                drm_sched_job_cleanup(&ejob->base);
 out_put_job:
-       ethosu_job_put(ejob);
+       ethosu_job_err_cleanup(ejob);
 
        return ret;
 }