From 3f36210b0b67b585ea971d4dfad6329859d6d395 Mon Sep 17 00:00:00 2001 From: "shihong.zheng" Date: Fri, 5 Jan 2018 17:30:56 +0800 Subject: [PATCH] mpeg12: fix crash in timer when change clk PD#155701 timer soft-irq cann't mutex_lock,add schedule work to change source clk. Change-Id: I199e3e480523ae546b91155113dc269b45e7beea Signed-off-by: shihong.zheng --- .../frame_provider/decoder/mpeg12/vmpeg12.c | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.c b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.c index 1390bd350ea5..eecb729d8da3 100644 --- a/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.c +++ b/drivers/amlogic/media_modules/frame_provider/decoder/mpeg12/vmpeg12.c @@ -186,6 +186,7 @@ static u32 first_i_frame_ready; static struct work_struct userdata_push_work; static struct work_struct notify_work; static struct work_struct reset_work; +static struct work_struct set_clk_work; static bool is_reset; static inline int pool_index(struct vframe_s *vf) @@ -739,6 +740,18 @@ static void reset_do_work(struct work_struct *work) amvdec_start(); } +static void vmpeg12_set_clk(struct work_struct *work) +{ + if (frame_dur > 0 && saved_resolution != + frame_width * frame_height * (96000 / frame_dur)) { + int fps = 96000 / frame_dur; + + saved_resolution = frame_width * frame_height * fps; + vdec_source_changed(VFORMAT_MPEG12, + frame_width, frame_height, fps); + } +} + static void vmpeg_put_timer_func(unsigned long arg) { struct timer_list *timer = (struct timer_list *)arg; @@ -793,14 +806,7 @@ static void vmpeg_put_timer_func(unsigned long arg) } } - if (frame_dur > 0 && saved_resolution != - frame_width * frame_height * (96000 / frame_dur)) { - int fps = 96000 / frame_dur; - - saved_resolution = frame_width * frame_height * fps; - vdec_source_changed(VFORMAT_MPEG12, - frame_width, frame_height, fps); - } + schedule_work(&set_clk_work); timer->expires = jiffies + PUT_INTERVAL; @@ -1185,6 +1191,7 @@ static int amvdec_mpeg12_probe(struct platform_device *pdev) INIT_WORK(&userdata_push_work, userdata_push_do_work); INIT_WORK(¬ify_work, vmpeg12_notify_work); INIT_WORK(&reset_work, reset_do_work); + INIT_WORK(&set_clk_work, vmpeg12_set_clk); amlog_level(LOG_LEVEL_INFO, "amvdec_mpeg12 probe end.\n"); @@ -1196,6 +1203,7 @@ static int amvdec_mpeg12_remove(struct platform_device *pdev) cancel_work_sync(&userdata_push_work); cancel_work_sync(¬ify_work); cancel_work_sync(&reset_work); + cancel_work_sync(&set_clk_work); if (stat & STAT_VDEC_RUN) { amvdec_stop();