Skip to content

Commit de71b3d

Browse files
robherringSasha Levin
authored andcommitted
accel: ethosu: Fix job submit error clean-up refcount underflows
[ Upstream commit 150bceb ] 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: 5a5e9c0 ("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> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 94b9da7 commit de71b3d

1 file changed

Lines changed: 18 additions & 8 deletions

File tree

drivers/accel/ethosu/ethosu_job.c

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -143,23 +143,29 @@ static int ethosu_job_push(struct ethosu_job *job)
143143
return ret;
144144
}
145145

146+
static void ethosu_job_err_cleanup(struct ethosu_job *job)
147+
{
148+
unsigned int i;
149+
150+
for (i = 0; i < job->region_cnt; i++)
151+
drm_gem_object_put(job->region_bo[i]);
152+
153+
drm_gem_object_put(job->cmd_bo);
154+
155+
kfree(job);
156+
}
157+
146158
static void ethosu_job_cleanup(struct kref *ref)
147159
{
148160
struct ethosu_job *job = container_of(ref, struct ethosu_job,
149161
refcount);
150-
unsigned int i;
151162

152163
pm_runtime_put_autosuspend(job->dev->base.dev);
153164

154165
dma_fence_put(job->done_fence);
155166
dma_fence_put(job->inference_done_fence);
156167

157-
for (i = 0; i < job->region_cnt; i++)
158-
drm_gem_object_put(job->region_bo[i]);
159-
160-
drm_gem_object_put(job->cmd_bo);
161-
162-
kfree(job);
168+
ethosu_job_err_cleanup(job);
163169
}
164170

165171
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
454460
}
455461
}
456462
ret = ethosu_job_push(ejob);
463+
if (!ret) {
464+
ethosu_job_put(ejob);
465+
return 0;
466+
}
457467

458468
out_cleanup_job:
459469
if (ret)
460470
drm_sched_job_cleanup(&ejob->base);
461471
out_put_job:
462-
ethosu_job_put(ejob);
472+
ethosu_job_err_cleanup(ejob);
463473

464474
return ret;
465475
}

0 commit comments

Comments
 (0)