From cbb101b4ee098f0eeb306ae3a3a7c1f7d4dac870 Mon Sep 17 00:00:00 2001 From: Hui Zhang Date: Mon, 22 Oct 2018 22:19:05 +0800 Subject: [PATCH] media_module: optimization for vdec schedule debug and fw load[1/1] PD#SWPL-895 Problem: optimization for vdec schedule debug and fw load Solution: 1) change vdec_core_thread priority 2) add reload flag in vdec to check if reload fw at every run 3) add mc_type to check if fw need reload at every run Verify: Verified p212 Change-Id: Ic14f14831bf59d913450228ba07e0f94dde5347e Signed-off-by: Hui Zhang --- .../frame_provider/decoder/avs2/vavs2.c | 4 +- .../decoder/h264_multi/vmh264.c | 46 +++++++++++-------- .../frame_provider/decoder/h265/vh265.c | 37 +++++++++------ .../decoder/mjpeg/vmjpeg_multi.c | 24 ++++++---- .../decoder/mpeg12/vmpeg12_multi.c | 27 +++++++---- .../decoder/mpeg4/vmpeg4_multi.c | 27 +++++++---- .../frame_provider/decoder/utils/vdec.c | 28 ++++++++--- .../frame_provider/decoder/utils/vdec.h | 2 +- .../frame_provider/decoder/vp9/vvp9.c | 28 +++++++---- 9 files changed, 142 insertions(+), 81 deletions(-) diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/avs2/vavs2.c b/drivers/amlogic/media_modules/frame_provider/decoder/avs2/vavs2.c index 17a6e5e022f3..e79758ffccef 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/avs2/vavs2.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/avs2/vavs2.c @@ -5662,8 +5662,10 @@ static void run(struct vdec_s *vdec, unsigned long mask, dec->dec_result = DEC_RESULT_FORCE_EXIT; vdec_schedule_work(&dec->work); return; - } else + } else { vdec->mc_loaded = 1; + vdec->mc_type = VFORMAT_AVS2; + } if (avs2_hw_ctx_restore(dec) < 0) { diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c index 5eaeee98a506..21e77b6934fb 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h264_multi/vmh264.c @@ -6856,36 +6856,44 @@ static void run(struct vdec_s *vdec, unsigned long mask, size); start_process_time(hw); + if (vdec->mc_loaded) { + /*firmware have load before, + and not changes to another. + ignore reload. + */ + } else { - ret = amvdec_vdec_loadmc_ex(VFORMAT_H264, "mh264", vdec, hw->fw->data); - if (ret < 0) { - amvdec_enable_flag = false; - amvdec_disable(); - - dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "MH264 the %s fw loading failed, err: %x\n", - tee_enabled() ? "TEE" : "local", ret); - hw->dec_result = DEC_RESULT_FORCE_EXIT; - vdec_schedule_work(&hw->work); - return; - } - - if (hw->mmu_enable) { - ret = amhevc_loadmc_ex(VFORMAT_H264, "mh264_mmu", - hw->fw_mmu->data); + ret = amvdec_vdec_loadmc_ex(VFORMAT_H264, "mh264", vdec, hw->fw->data); if (ret < 0) { amvdec_enable_flag = false; - amhevc_disable(); + amvdec_disable(); dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, - "MH264_MMU the %s fw loading failed, err: %x\n", + "MH264 the %s fw loading failed, err: %x\n", tee_enabled() ? "TEE" : "local", ret); hw->dec_result = DEC_RESULT_FORCE_EXIT; vdec_schedule_work(&hw->work); return; } - } + vdec->mc_type = VFORMAT_H264; + if (hw->mmu_enable) { + ret = amhevc_loadmc_ex(VFORMAT_H264, "mh264_mmu", + hw->fw_mmu->data); + if (ret < 0) { + amvdec_enable_flag = false; + amhevc_disable(); + dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR, + "MH264_MMU the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); + hw->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&hw->work); + return; + } + vdec->mc_type = ((1 << 16) | VFORMAT_H264); + } + vdec->mc_loaded = 1; + } vmh264_reset_udr_mgr(hw); if (vh264_hw_ctx_restore(hw) < 0) { diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.c b/drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.c index c4a6b9e40b8c..c88782789597 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/h265/vh265.c @@ -10239,23 +10239,30 @@ static void run(struct vdec_s *vdec, unsigned long mask, "\n"); } } + if (vdec->mc_loaded) { + /*firmware have load before, + and not changes to another. + ignore reload. + */ + } else { + if (hevc->mmu_enable) + loadr = amhevc_vdec_loadmc_ex(VFORMAT_HEVC, vdec, + "h265_mmu", hevc->fw->data); + else + loadr = amhevc_vdec_loadmc_ex(VFORMAT_HEVC, vdec, + NULL, hevc->fw->data); - if (hevc->mmu_enable) - loadr = amhevc_vdec_loadmc_ex(VFORMAT_HEVC, vdec, - "h265_mmu", hevc->fw->data); - else - loadr = amhevc_vdec_loadmc_ex(VFORMAT_HEVC, vdec, - NULL, hevc->fw->data); - - if (loadr < 0) { - amhevc_disable(); - hevc_print(hevc, 0, "H265: the %s fw loading failed, err: %x\n", - tee_enabled() ? "TEE" : "local", loadr); - hevc->dec_result = DEC_RESULT_FORCE_EXIT; - vdec_schedule_work(&hevc->work); - return; + if (loadr < 0) { + amhevc_disable(); + hevc_print(hevc, 0, "H265: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", loadr); + hevc->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&hevc->work); + return; + } + vdec->mc_loaded = 1; + vdec->mc_type = VFORMAT_HEVC; } - if (vh265_hw_ctx_restore(hevc) < 0) { vdec_schedule_work(&hevc->work); return; diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg_multi.c b/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg_multi.c index 001f14c500cb..e19f1e9bc9bf 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg_multi.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mjpeg/vmjpeg_multi.c @@ -923,14 +923,22 @@ static void run(struct vdec_s *vdec, unsigned long mask, } hw->input_empty = 0; hw->dec_result = DEC_RESULT_NONE; - - ret = amvdec_vdec_loadmc_ex(VFORMAT_MJPEG, "mmjpeg", vdec, hw->fw->data); - if (ret < 0) { - pr_err("[%d] MMJPEG: the %s fw loading failed, err: %x\n", - vdec->id, tee_enabled() ? "TEE" : "local", ret); - hw->dec_result = DEC_RESULT_FORCE_EXIT; - vdec_schedule_work(&hw->work); - return; + if (vdec->mc_loaded) { + /*firmware have load before, + and not changes to another. + ignore reload. + */ + } else { + ret = amvdec_vdec_loadmc_ex(VFORMAT_MJPEG, "mmjpeg", vdec, hw->fw->data); + if (ret < 0) { + pr_err("[%d] MMJPEG: the %s fw loading failed, err: %x\n", + vdec->id, tee_enabled() ? "TEE" : "local", ret); + hw->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&hw->work); + return; + } + vdec->mc_loaded = 1; + vdec->mc_type = VFORMAT_MJPEG; } /* if (amvdec_vdec_loadmc_buf_ex(vdec, hw->fw->data, hw->fw->len) < 0) { pr_err("%s: Error amvdec_loadmc fail\n", __func__); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12_multi.c b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12_multi.c index 865c248f7a8b..31731bfab9ae 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12_multi.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12_multi.c @@ -1670,17 +1670,24 @@ void (*callback)(struct vdec_s *, void *), hw->chunk->offset, hw->chunk->size); hw->dec_result = DEC_RESULT_NONE; - - ret = amvdec_vdec_loadmc_buf_ex(VFORMAT_MPEG12, "mmpeg12", vdec, - hw->fw->data, hw->fw->len); - if (ret < 0) { - pr_err("[%d] %s: the %s fw loading failed, err: %x\n", vdec->id, - hw->fw->name, tee_enabled() ? "TEE" : "local", ret); - hw->dec_result = DEC_RESULT_FORCE_EXIT; - vdec_schedule_work(&hw->work); - return; + if (vdec->mc_loaded) { + /*firmware have load before, + and not changes to another. + ignore reload. + */ + } else { + ret = amvdec_vdec_loadmc_buf_ex(VFORMAT_MPEG12, "mmpeg12", vdec, + hw->fw->data, hw->fw->len); + if (ret < 0) { + pr_err("[%d] %s: the %s fw loading failed, err: %x\n", vdec->id, + hw->fw->name, tee_enabled() ? "TEE" : "local", ret); + hw->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&hw->work); + return; + } + vdec->mc_loaded = 1; + vdec->mc_type = VFORMAT_MPEG12; } - if (vmpeg12_hw_ctx_restore(hw) < 0) { hw->dec_result = DEC_RESULT_ERROR; debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR, diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4_multi.c b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4_multi.c index 063cae10ce27..5240fcac1d4c 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4_multi.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg4/vmpeg4_multi.c @@ -1675,17 +1675,24 @@ static void run(struct vdec_s *vdec, unsigned long mask, READ_PARSER_REG(PARSER_VIDEO_WP)); hw->dec_result = DEC_RESULT_NONE; - - ret = amvdec_vdec_loadmc_buf_ex(VFORMAT_MPEG4,hw->fw->name, vdec, - hw->fw->data, hw->fw->len); - if (ret < 0) { - pr_err("[%d] %s: the %s fw loading failed, err: %x\n", vdec->id, - hw->fw->name, tee_enabled() ? "TEE" : "local", ret); - hw->dec_result = DEC_RESULT_FORCE_EXIT; - schedule_work(&hw->work); - return; + if (vdec->mc_loaded) { + /*firmware have load before, + and not changes to another. + ignore reload. + */ + } else { + ret = amvdec_vdec_loadmc_buf_ex(VFORMAT_MPEG4,hw->fw->name, vdec, + hw->fw->data, hw->fw->len); + if (ret < 0) { + pr_err("[%d] %s: the %s fw loading failed, err: %x\n", vdec->id, + hw->fw->name, tee_enabled() ? "TEE" : "local", ret); + hw->dec_result = DEC_RESULT_FORCE_EXIT; + schedule_work(&hw->work); + return; + } + vdec->mc_loaded = 1; + vdec->mc_type = VFORMAT_MPEG4; } - if (vmpeg4_hw_ctx_restore(hw) < 0) { hw->dec_result = DEC_RESULT_ERROR; mmpeg4_debug_print(DECODE_ID(hw), 0, diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c index e43f8f9f2e5f..037e1b3e4c31 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.c @@ -81,6 +81,11 @@ static int keep_vdec_mem; static unsigned int debug_trace_num = 16 * 20; static int step_mode; static unsigned int clk_config; +/* + &1: sched_priority to MAX_RT_PRIO -1. + &2: always reload firmware. + */ +static unsigned int debug; static int hevc_max_reset_count; #define MAX_INSTANCE_MUN 9 @@ -122,6 +127,7 @@ struct vdec_core_s { unsigned long sched_mask; struct vdec_isr_context_s isr_context[VDEC_IRQ_MAX]; int power_ref_count[VDEC_MAX]; + void *last_vdec; }; static struct vdec_core_s *vdec_core; @@ -1738,7 +1744,7 @@ int vdec_reset(struct vdec_s *vdec) if (vdec->slave) vdec->slave->reset(vdec->slave); } - + vdec->mc_loaded = 0;/*clear for reload firmware*/ vdec_input_release(&vdec->input); vdec_input_init(&vdec->input, vdec); @@ -1754,6 +1760,7 @@ int vdec_reset(struct vdec_s *vdec) vf_reg_provider(&vdec->slave->vframe_provider); vf_notify_receiver(vdec->slave->vf_provider_name, VFRAME_EVENT_PROVIDER_START, vdec->slave); + vdec->slave->mc_loaded = 0;/*clear for reload firmware*/ } vdec_connect(vdec); @@ -2091,13 +2098,13 @@ void vdec_prepare_run(struct vdec_s *vdec, unsigned long mask) static int vdec_core_thread(void *data) { struct vdec_core_s *core = (struct vdec_core_s *)data; - - struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1}; + struct vdec_s *lastvdec; + struct sched_param param = {.sched_priority = MAX_RT_PRIO/2}; sched_setscheduler(current, SCHED_FIFO, ¶m); allow_signal(SIGTERM); - + lastvdec = NULL; while (down_interruptible(&core->sem) == 0) { struct vdec_s *vdec, *tmp, *worker; unsigned long sched_mask = 0; @@ -2242,7 +2249,12 @@ static int vdec_core_thread(void *data) /* vdec's sched_mask is only set from core thread */ vdec->sched_mask |= mask; - + if (lastvdec) { + if ((lastvdec != vdec) && (lastvdec->mc_type != vdec->mc_type)) + vdec->mc_loaded = 0;/*clear for reload firmware*/ + } + if (debug & 2) + vdec->mc_loaded = 0;/*alway reload firmware*/ vdec_set_status(vdec, VDEC_STATUS_ACTIVE); core->sched_mask |= mask; @@ -3830,8 +3842,9 @@ static int vdec_probe(struct platform_device *pdev) vdec_core->thread = kthread_run(vdec_core_thread, vdec_core, "vdec-core"); - vdec_core->vdec_core_wq = create_singlethread_workqueue("threadvdec"); - + vdec_core->vdec_core_wq = alloc_ordered_workqueue("%s",__WQ_LEGACY | + WQ_MEM_RECLAIM |WQ_HIGHPRI/*high priority*/, "vdec-work"); + /*work queue priority lower than vdec-core.*/ return 0; } @@ -3945,6 +3958,7 @@ EXPORT_SYMBOL(force_hevc_clock_cntl); module_param(force_hevc_clock_cntl, uint, 0664); */ +module_param(debug, uint, 0664); module_param(debug_trace_num, uint, 0664); module_param(hevc_max_reset_count, int, 0664); module_param(clk_config, uint, 0664); diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.h b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.h index d3a64aa47911..1d67cd11c588 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.h +++ b/drivers/amlogic/media_modules/frame_provider/decoder/utils/vdec.h @@ -200,7 +200,7 @@ struct vdec_s { /* mc cache */ u32 mc[4096 * 4]; bool mc_loaded; - + u32 mc_type; /* frame provider/receiver interface */ char vf_provider_name[VDEC_PROVIDER_NAME_SIZE]; struct vframe_provider_s vframe_provider; diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.c b/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.c index 484ba43e6095..ed08f2dd57e6 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/vp9/vvp9.c @@ -8779,16 +8779,24 @@ static void run_front(struct vdec_s *vdec) } vp9_print_cont(pbi, 0, "\r\n"); } - - ret = amhevc_loadmc_ex(VFORMAT_VP9, NULL, pbi->fw->data); - if (ret < 0) { - amhevc_disable(); - vp9_print(pbi, PRINT_FLAG_ERROR, - "VP9: the %s fw loading failed, err: %x\n", - tee_enabled() ? "TEE" : "local", ret); - pbi->dec_result = DEC_RESULT_FORCE_EXIT; - vdec_schedule_work(&pbi->work); - return; + if (vdec->mc_loaded) { + /*firmware have load before, + and not changes to another. + ignore reload. + */ + } else { + ret = amhevc_loadmc_ex(VFORMAT_VP9, NULL, pbi->fw->data); + if (ret < 0) { + amhevc_disable(); + vp9_print(pbi, PRINT_FLAG_ERROR, + "VP9: the %s fw loading failed, err: %x\n", + tee_enabled() ? "TEE" : "local", ret); + pbi->dec_result = DEC_RESULT_FORCE_EXIT; + vdec_schedule_work(&pbi->work); + return; + } + vdec->mc_loaded = 1; + vdec->mc_type = VFORMAT_VP9; } if (vp9_hw_ctx_restore(pbi) < 0) {