author | miaohong chen <miaohong.chen@amlogic.com> | 2020-04-22 08:31:18 (GMT) |
---|---|---|
committer | Shen Liu <shen.liu@amlogic.com> | 2020-04-29 11:43:05 (GMT) |
commit | fb8fe6e1ef0314160ce02a10ee7fe3a5d89d228e (patch) | |
tree | 1193b84ba003c4e4447ab30cd9b2cb33b4631165 | |
parent | b251a63337aebfc230afca252ff7c1a3b6aa60dc (diff) | |
download | media_modules-fb8fe6e1ef0314160ce02a10ee7fe3a5d89d228e.zip media_modules-fb8fe6e1ef0314160ce02a10ee7fe3a5d89d228e.tar.gz media_modules-fb8fe6e1ef0314160ce02a10ee7fe3a5d89d228e.tar.bz2 |
vmh264: fix vmh264 kernel panic. [1/1]
PD#SWPL-24651
Problem:
kernel panic.
Both user_data_push_work and user_data_ready_notify_work
are started in the interrupt thread, and at the same time,
the userdata list will be operated,
but the mutual exclusion is not done, resulting in crash
Solution:
After consideration, cancel two work,
change to synchronous operation,
perform data push and notify operations in the interrupt thread
Verify:
u212
Change-Id: Ife48fafe1a26bb7cd999b39fec6d77e3282f0334
Signed-off-by: miaohong chen <miaohong.chen@amlogic.com>
-rw-r--r-- | drivers/frame_provider/decoder/h264_multi/vmh264.c | 83 |
1 files changed, 33 insertions, 50 deletions
diff --git a/drivers/frame_provider/decoder/h264_multi/vmh264.c b/drivers/frame_provider/decoder/h264_multi/vmh264.c index 74b543a..8fe5acb 100644 --- a/drivers/frame_provider/decoder/h264_multi/vmh264.c +++ b/drivers/frame_provider/decoder/h264_multi/vmh264.c @@ -467,11 +467,6 @@ static int vh264_vf_states(struct vframe_states *states, void *); static int vh264_event_cb(int type, void *data, void *private_data); static void vh264_work(struct work_struct *work); static void vh264_notify_work(struct work_struct *work); -static void user_data_push_work(struct work_struct *work); -#ifdef MH264_USERDATA_ENABLE -static void user_data_ready_notify_work(struct work_struct *work); -static void vmh264_wakeup_userdata_poll(void); -#endif static const char vh264_dec_id[] = "vh264-dev"; @@ -826,6 +821,12 @@ struct vdec_h264_hw_s { static u32 again_threshold = 0x40; +static void user_data_push_work(struct vdec_h264_hw_s *hw); +#ifdef MH264_USERDATA_ENABLE +void user_data_ready_notify(struct vdec_h264_hw_s *hw); +static void vmh264_wakeup_userdata_poll(void); +#endif + static void dump_bufspec(struct vdec_h264_hw_s *hw, const char *caller); static void h264_reconfig(struct vdec_h264_hw_s *hw); @@ -4965,7 +4966,7 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq) if (hw->sei_itu_data_len) { hw->sei_poc = p_H264_Dpb->mVideo.dec_picture->poc; - schedule_work(&hw->user_data_work); + user_data_push_work(hw); } if (slice_header_process_status == 1) { if ((p_H264_Dpb->mSPS.profile_idc == BASELINE) || @@ -6139,10 +6140,6 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw) vh264_local_init(hw); INIT_WORK(&hw->work, vh264_work); INIT_WORK(&hw->notify_work, vh264_notify_work); - INIT_WORK(&hw->user_data_work, user_data_push_work); -#ifdef MH264_USERDATA_ENABLE - INIT_WORK(&hw->user_data_ready_work, user_data_ready_notify_work); -#endif if (!amvdec_enable_flag) { amvdec_enable_flag = true; @@ -6341,10 +6338,6 @@ static int vh264_stop(struct vdec_h264_hw_s *hw) #endif cancel_work_sync(&hw->work); cancel_work_sync(&hw->notify_work); - cancel_work_sync(&hw->user_data_work); -#ifdef MH264_USERDATA_ENABLE - cancel_work_sync(&hw->user_data_ready_work); -#endif if (hw->stat & STAT_MC_LOAD) { if (hw->mc_cpu_addr != NULL) { @@ -6784,35 +6777,8 @@ static void vmh264_input_udc_waitqueue(struct vdec_h264_hw_s *hw, hw->userdata_info.last_wp = wp; } -static void vmh264_udc_fill_vpts(struct vdec_h264_hw_s *hw, - int frame_type, - u32 vpts, - u32 vpts_valid) -{ - struct mh264_ud_record_wait_node_t *node; - struct mh264_ud_record_wait_node_t *tmp; - struct mh264_userdata_record_t *pud_record; - struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; - - if (!list_empty(&hw->frame_uds)) { - list_for_each_entry_safe(node, tmp, &hw->frame_uds, list) { - pud_record = &node->ud_record; - pud_record->meta_info.vpts = vpts; - pud_record->meta_info.vpts_valid = vpts_valid; - pud_record->meta_info.poc_number = - p_H264_Dpb->mVideo.dec_picture->poc; - } - hw->wait_for_udr_send = 1; - schedule_work(&hw->user_data_ready_work); - } -} - - -static void user_data_ready_notify_work(struct work_struct *work) +void user_data_ready_notify(struct vdec_h264_hw_s *hw) { - struct vdec_h264_hw_s *hw = container_of(work, - struct vdec_h264_hw_s, user_data_ready_work); - struct mh264_ud_record_wait_node_t *node; struct mh264_ud_record_wait_node_t *tmp; @@ -6835,8 +6801,29 @@ static void user_data_ready_notify_work(struct work_struct *work) } hw->wait_for_udr_send = 0; - hw->dec_result = DEC_RESULT_DONE; - vdec_schedule_work(&hw->work); +} + +static void vmh264_udc_fill_vpts(struct vdec_h264_hw_s *hw, + int frame_type, + u32 vpts, + u32 vpts_valid) +{ + struct mh264_ud_record_wait_node_t *node; + struct mh264_ud_record_wait_node_t *tmp; + struct mh264_userdata_record_t *pud_record; + struct h264_dpb_stru *p_H264_Dpb = &hw->dpb; + + if (!list_empty(&hw->frame_uds)) { + list_for_each_entry_safe(node, tmp, &hw->frame_uds, list) { + pud_record = &node->ud_record; + pud_record->meta_info.vpts = vpts; + pud_record->meta_info.vpts_valid = vpts_valid; + pud_record->meta_info.poc_number = + p_H264_Dpb->mVideo.dec_picture->poc; + } + hw->wait_for_udr_send = 1; + user_data_ready_notify(hw); + } } static int vmh264_user_data_read(struct vdec_s *vdec, @@ -7054,11 +7041,8 @@ static void vmh264_wakeup_userdata_poll(void) #endif -static void user_data_push_work(struct work_struct *work) +static void user_data_push_work(struct vdec_h264_hw_s *hw) { - struct vdec_h264_hw_s *hw = container_of(work, - struct vdec_h264_hw_s, user_data_work); - struct userdata_poc_info_t user_data_poc; unsigned char *pdata; u8 *pmax_sei_data_buffer; @@ -7614,7 +7598,7 @@ static void run(struct vdec_s *vdec, unsigned long mask, } vdec->mc_type = ((1 << 16) | VFORMAT_H264); } - vdec->mc_loaded = 1; + vdec->mc_loaded = 0; } vmh264_reset_udr_mgr(hw); @@ -7688,7 +7672,6 @@ static void reset(struct vdec_s *vdec) cancel_work_sync(&hw->work); cancel_work_sync(&hw->notify_work); - cancel_work_sync(&hw->user_data_work); if (hw->stat & STAT_VDEC_RUN) { amhevc_stop(); hw->stat &= ~STAT_VDEC_RUN; |