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 Signed-off-by: Ijae Kim Signed-off-by: Myeonghun Pak Reviewed-by: Ming Qian --- drivers/media/platform/amphion/vpu_core.c | 15 ++++++++------- 1 file 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; } -- 2.53.0