summaryrefslogtreecommitdiff
authormiaohong 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)
commitfb8fe6e1ef0314160ce02a10ee7fe3a5d89d228e (patch)
tree1193b84ba003c4e4447ab30cd9b2cb33b4631165
parentb251a63337aebfc230afca252ff7c1a3b6aa60dc (diff)
downloadmedia_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>
Diffstat
-rw-r--r--drivers/frame_provider/decoder/h264_multi/vmh264.c83
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;