diff options
| author | Myeonghun Pak <mhun512@gmail.com> | 2026-09-25 15:17:05 -0400 |
|---|---|---|
| committer | Hans Verkuil <hverkuil+cisco@kernel.org> | 2026-10-04 17:32:42 +0200 |
| commit | ec95ae226f240ed657834fe4114abb7067e1af2d (patch) | |
| tree | 35203bf84ad3b098ed171a6570d7f0b131f2ba85 /drivers/media | |
| parent | a67578c0179850e80cf08b1e0b8b1eb857f0fc46 (diff) | |
media: amphion: drain message work before releasing core state
vpu_core_unregister() frees core->msg_buffer before cancelling the message
workers, although core->msg_fifo still uses the buffer as its backing
storage. A queued worker can read it after it has been freed.
Drain the core and instance message work first, then release core->vpu
and the FIFO buffer. This follows the ordering in vpu_core_suspend().
Fixes: 9f599f351e86 ("media: amphion: add vpu core driver")
Cc: stable@vger.kernel.org
Co-developed-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Myeonghun Pak <mhun512@gmail.com>
Reviewed-by: Ming Qian <ming.qian@oss.nxp.com>
Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Diffstat (limited to 'drivers/media')
| -rw-r--r-- | drivers/media/platform/amphion/vpu_core.c | 15 |
1 files changed, 8 insertions, 7 deletions
diff --git a/drivers/media/platform/amphion/vpu_core.c b/drivers/media/platform/amphion/vpu_core.c index 85cc4a14f8ed..a0c58ec97a42 100644 --- a/drivers/media/platform/amphion/vpu_core.c +++ b/drivers/media/platform/amphion/vpu_core.c @@ -299,22 +299,23 @@ static void vpu_core_put_vpu(struct vpu_core *core) core->vpu->put_vpu(core->vpu); } +static void vpu_core_cancel_work(struct vpu_core *core); + static int vpu_core_unregister(struct device *dev, struct vpu_core *core) { list_del_init(&core->list); - vpu_core_put_vpu(core); - core->vpu = NULL; - kfree(core->msg_buffer); - core->msg_buffer = NULL; - if (core->workqueue) { - cancel_work_sync(&core->msg_work); - cancel_delayed_work_sync(&core->msg_delayed_work); + vpu_core_cancel_work(core); destroy_workqueue(core->workqueue); core->workqueue = NULL; } + vpu_core_put_vpu(core); + core->vpu = NULL; + kfree(core->msg_buffer); + core->msg_buffer = NULL; + return 0; } |
