From 8ac72c875ad5b54aa85e68ddf4e76793b60419c4 Mon Sep 17 00:00:00 2001 From: Ding Wei Date: Thu, 24 Feb 2022 10:55:59 +0800 Subject: [PATCH] video: rockchip: mpp: Fix issue for multi-core jpeg encoder tips: 1. each task may work different core, thus, if use session->mpp then it will be change when each alloc task. 2. alloc_task and isr are in the different thread, so, the session->mpp will be overwrite when following task alloc. 3. based above, use task->mpp instead of session->mpp is the better. backtrace when error: [ 36.421939 ][ T160 ] mpp_vepu2 fdba4000.jpege-core: no current task [ 36.623432 ][ C6 ] Unable to handle kernel NULL pointerdereference at virtual address 0000000000000102 [ 36.624290 ][ C6 ] Mem abort info: [ 36.624615 ][ C6 ] ESR = 0x96000005 [ 36.624966 ][ C6 ] EC = 0x25: DABT (current EL), IL = 32 bits [ 36.625509 ][ C6 ] SET = 0, FnV = 0 [ 36.625856 ][ C6 ] EA = 0, S1PTW = 0 [ 36.626212 ][ C6 ] Data abort info: [ 36.626546 ][ C6 ] ISV = 0, ISS = 0x00000005 [ 36.626953 ][ C6 ] CM = 0, WnR = 0 [ 36.627292 ][ C6 ] user pgtable: 4k pages, 39-bit VAs,pgdp=0000000107211000 [ 36.627934 ][ C6 ] [0000000000000102] pgd=0000000000000000,p4d=0000000000000000, pud=0000000000000000 [ 36.628797 ][ C6 ] Internal error: Oops: 96000005 [#1] PREEMPT SMP [ 36.629365 ][ C6 ] Modules linked in: bcmdhd r8168 [ 36.629843 ][ C6 ] CPU: 6 PID: 0 Comm: swapper/6 Not tainted5.10.66 #1092 [ 36.630472 ][ C6 ] Hardware name: Rockchip RK3588 EVB1 LP4 V10Board (DT) [ 36.631095 ][ C6 ] pstate: 20400089 (nzCv daIf +PAN -UAO -TCOBTYPE=--) [ 36.631721 ][ C6 ] pc : __queue_work+0x24/0x538 [ 36.632154 ][ C6 ] lr : delayed_work_timer_fn+0x24/0x34 Change-Id: I610f16ec33ef29217975779ba5d09c7274009c61 Signed-off-by: Ding Wei --- drivers/video/rockchip/mpp/mpp_common.c | 15 +++----- drivers/video/rockchip/mpp/mpp_vepu2.c | 50 +++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 13 deletions(-) diff --git a/drivers/video/rockchip/mpp/mpp_common.c b/drivers/video/rockchip/mpp/mpp_common.c index 2032819afbab..6fdd3d4e79a1 100644 --- a/drivers/video/rockchip/mpp/mpp_common.c +++ b/drivers/video/rockchip/mpp/mpp_common.c @@ -498,13 +498,7 @@ void mpp_free_task(struct kref *ref) session->index, task->task_index, task->state, atomic_read(&task->abort_request)); - mpp = session->mpp; - if (!mpp) { - mpp_err("task %d:%d mpp is null.\n", - session->index, task->task_index); - return; - } - + mpp = mpp_get_task_used_device(task, session); if (mpp->dev_ops->free_task) mpp->dev_ops->free_task(session, task); @@ -537,8 +531,8 @@ static void mpp_task_timeout_work(struct work_struct *work_s) mpp_err("session %p, session->mpp is null.\n", session); return; } - mpp = session->mpp; + mpp = mpp_get_task_used_device(task, session); /* hardware maybe dead, reset it */ mpp_reset_up_read(mpp->reset_group); mpp_dev_reset(mpp); @@ -571,6 +565,9 @@ static int mpp_process_task_default(struct mpp_session *session, mpp_err("alloc_task failed.\n"); return -ENOMEM; } + /* ensure current device */ + mpp = mpp_get_task_used_device(task, session); + kref_init(&task->ref); init_waitqueue_head(&task->wait); atomic_set(&task->abort_request, 0); @@ -1701,7 +1698,7 @@ int mpp_translate_reg_address(struct mpp_session *session, cnt = session->trans_count; tbl = session->trans_table; } else { - struct mpp_dev *mpp = session->mpp; + struct mpp_dev *mpp = mpp_get_task_used_device(task, session); struct mpp_trans_info *trans_info = mpp->var->trans_info; cnt = trans_info[fmt].count; diff --git a/drivers/video/rockchip/mpp/mpp_vepu2.c b/drivers/video/rockchip/mpp/mpp_vepu2.c index 37dbb7e80bc6..618e4061bcce 100644 --- a/drivers/video/rockchip/mpp/mpp_vepu2.c +++ b/drivers/video/rockchip/mpp/mpp_vepu2.c @@ -328,15 +328,57 @@ static struct vepu_dev *vepu_core_balance(struct vepu_ccu *ccu) static void *vepu_ccu_alloc_task(struct mpp_session *session, struct mpp_task_msgs *msgs) { - struct vepu_dev *enc = to_vepu_dev(session->mpp); + int ret; + struct mpp_task *mpp_task = NULL; + struct vepu_task *task = NULL; + struct mpp_dev *mpp = session->mpp; + struct vepu_dev *enc = to_vepu_dev(mpp); - /* if multi-cores, choose one for current task */ + mpp_debug_enter(); + + task = kzalloc(sizeof(*task), GFP_KERNEL); + if (!task) + return NULL; + + mpp_task = &task->mpp_task; + /* if multicore, choose one for current task */ if (enc->ccu) { enc = vepu_core_balance(enc->ccu); - session->mpp = &enc->mpp; + mpp_task->mpp = &enc->mpp; + mpp = mpp_task->mpp; + mpp_debug(DEBUG_TASK_INFO, "%s\n", dev_name(mpp->dev)); } - return vepu_alloc_task(session, msgs); + mpp_task_init(session, mpp_task); + mpp_task->hw_info = mpp->var->hw_info; + mpp_task->reg = task->reg; + /* extract reqs for current task */ + ret = vepu_extract_task_msg(task, msgs); + if (ret) + goto fail; + /* process fd in register */ + if (!(msgs->flags & MPP_FLAGS_REG_FD_NO_TRANS)) { + ret = vepu_process_reg_fd(session, task, msgs); + if (ret) + goto fail; + } + task->clk_mode = CLK_MODE_NORMAL; + /* get resolution info */ + task->width = VEPU2_GET_WIDTH(task->reg[VEPU2_REG_ENC_EN_INDEX]); + task->height = VEPU2_GET_HEIGHT(task->reg[VEPU2_REG_ENC_EN_INDEX]); + task->pixels = task->width * task->height; + mpp_debug(DEBUG_TASK_INFO, "width=%d, height=%d\n", task->width, task->height); + + mpp_debug_leave(); + + return mpp_task; + +fail: + mpp_task_dump_mem_region(mpp, mpp_task); + mpp_task_dump_reg(mpp, mpp_task); + mpp_task_finalize(session, mpp_task); + kfree(task); + return NULL; } static int vepu_run(struct mpp_dev *mpp,