mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 19:08:57 +09:00
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 <leo.ding@rock-chips.com>
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user