Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

accel: ethosu: Fix job submit error clean-up refcount underflows

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>

+19 -9
+19 -9
drivers/accel/ethosu/ethosu_job.c
··· 143 143 return ret; 144 144 } 145 145 146 - static void ethosu_job_cleanup(struct kref *ref) 146 + static void ethosu_job_err_cleanup(struct ethosu_job *job) 147 147 { 148 - struct ethosu_job *job = container_of(ref, struct ethosu_job, 149 - refcount); 150 148 unsigned int i; 151 - 152 - pm_runtime_put_autosuspend(job->dev->base.dev); 153 - 154 - dma_fence_put(job->done_fence); 155 - dma_fence_put(job->inference_done_fence); 156 149 157 150 for (i = 0; i < job->region_cnt; i++) 158 151 drm_gem_object_put(job->region_bo[i]); ··· 153 160 drm_gem_object_put(job->cmd_bo); 154 161 155 162 kfree(job); 163 + } 164 + 165 + static void ethosu_job_cleanup(struct kref *ref) 166 + { 167 + struct ethosu_job *job = container_of(ref, struct ethosu_job, 168 + refcount); 169 + 170 + pm_runtime_put_autosuspend(job->dev->base.dev); 171 + 172 + dma_fence_put(job->done_fence); 173 + dma_fence_put(job->inference_done_fence); 174 + 175 + ethosu_job_err_cleanup(job); 156 176 } 157 177 158 178 static void ethosu_job_put(struct ethosu_job *job) ··· 460 454 } 461 455 } 462 456 ret = ethosu_job_push(ejob); 457 + if (!ret) { 458 + ethosu_job_put(ejob); 459 + return 0; 460 + } 463 461 464 462 out_cleanup_job: 465 463 if (ret) 466 464 drm_sched_job_cleanup(&ejob->base); 467 465 out_put_job: 468 - ethosu_job_put(ejob); 466 + ethosu_job_err_cleanup(ejob); 469 467 470 468 return ret; 471 469 }