ソースを参照

video: driver: fix list usage without init

If workqueue creation fails, driver is accessing buffer lists
in session close sequence, which is not yet inited and leading
to NULL ptr dereferrence issue, while traversing uninitialized
list. So added change to avoid accessing list without init
completion.

Change-Id: Icb3aa6b7edaf27e73873ec289d6a921a2613e77e
Signed-off-by: Govindaraj Rajagopal <[email protected]>
Govindaraj Rajagopal 4 年 前
コミット
d9518d9182

+ 1 - 1
driver/vidc/inc/msm_vidc_internal.h

@@ -828,7 +828,7 @@ struct msm_vidc_timestamp {
 struct msm_vidc_timestamps {
 	struct list_head       list;
 	u32                    count;
-	u32                    rank;
+	u64                    rank;
 };
 
 struct msm_vidc_pool {

+ 0 - 2
driver/vidc/src/msm_vdec.c

@@ -1365,8 +1365,6 @@ int msm_vdec_streamoff_input(struct msm_vidc_inst *inst)
 	if (rc)
 		return rc;
 
-	msm_vidc_flush_ts(inst);
-
 	return 0;
 }
 

+ 15 - 18
driver/vidc/src/msm_vidc.c

@@ -799,24 +799,6 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
 	msm_vidc_update_debug_str(inst);
 
 	i_vpr_h(inst, "Opening video instance: %d\n", session_type);
-
-	inst->response_workq = create_singlethread_workqueue("response_workq");
-	if (!inst->response_workq) {
-		i_vpr_e(inst, "%s: create input_psc_workq failed\n", __func__);
-		goto error;
-	}
-
-	inst->capabilities = kzalloc(
-		sizeof(struct msm_vidc_inst_capability), GFP_KERNEL);
-	if (!inst->capabilities) {
-		i_vpr_e(inst,
-			"%s: inst capability allocation failed\n", __func__);
-		goto error;
-	}
-
-	INIT_DELAYED_WORK(&inst->response_work,
-			handle_session_response_work_handler);
-
 	INIT_LIST_HEAD(&inst->response_works);
 	INIT_LIST_HEAD(&inst->pool.buffers.list);
 	INIT_LIST_HEAD(&inst->pool.mappings.list);
@@ -863,6 +845,21 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
 	for (i = 0; i < MAX_SIGNAL; i++)
 		init_completion(&inst->completions[i]);
 
+	inst->response_workq = create_singlethread_workqueue("response_workq");
+	if (!inst->response_workq) {
+		i_vpr_e(inst, "%s: create input_psc_workq failed\n", __func__);
+		goto error;
+	}
+
+	INIT_DELAYED_WORK(&inst->response_work, handle_session_response_work_handler);
+
+	inst->capabilities = kzalloc(sizeof(struct msm_vidc_inst_capability), GFP_KERNEL);
+	if (!inst->capabilities) {
+		i_vpr_e(inst,
+			"%s: inst capability allocation failed\n", __func__);
+		goto error;
+	}
+
 	if (is_decode_session(inst))
 		rc = msm_vdec_inst_init(inst);
 	else if (is_encode_session(inst))

+ 5 - 2
driver/vidc/src/msm_vidc_driver.c

@@ -40,6 +40,8 @@ extern struct msm_vidc_core *g_core;
 #define SSR_ADDR_ID 0xFFFFFFFF00000000
 #define SSR_ADDR_SHIFT 32
 
+#define FPS_WINDOW 10
+
 struct msm_vidc_cap_name {
 	enum msm_vidc_inst_capability_type cap;
 	char *name;
@@ -2017,6 +2019,7 @@ int msm_vidc_flush_ts(struct msm_vidc_inst *inst)
 		msm_vidc_put_ts(inst, ts);
 	}
 	inst->timestamps.count = 0;
+	inst->timestamps.rank = 0;
 
 	return 0;
 }
@@ -2046,7 +2049,7 @@ int msm_vidc_update_timestamp(struct msm_vidc_inst *inst, u64 timestamp)
 	inst->timestamps.count++;
 
 	/* keep sliding window of 10 ts nodes */
-	if (inst->timestamps.count > 10) {
+	if (inst->timestamps.count > FPS_WINDOW) {
 		ts = msm_vidc_get_least_rank_ts(inst);
 		if (!ts) {
 			i_vpr_e(inst, "%s: least rank ts is NULL\n", __func__);
@@ -4547,7 +4550,7 @@ void msm_vidc_destroy_buffers(struct msm_vidc_inst *inst)
 	}
 
 	list_for_each_entry_safe(ts, dummy_ts, &inst->timestamps.list, sort.list) {
-		i_vpr_e(inst, "%s: removing ts: val %lld, rank %%lld\n",
+		i_vpr_e(inst, "%s: removing ts: val %lld, rank %lld\n",
 			__func__, ts->sort.val, ts->rank);
 		list_del(&ts->sort.list);
 		msm_vidc_put_ts(inst, ts);

+ 7 - 6
driver/vidc/src/msm_vidc_vb2.c

@@ -266,22 +266,23 @@ void msm_vidc_stop_streaming(struct vb2_queue *q)
 			rc = msm_vdec_streamoff_input(inst);
 		else if (is_encode_session(inst))
 			rc = msm_venc_streamoff_input(inst);
-		else
-			goto error;
 	} else if (q->type == OUTPUT_MPLANE) {
 		if (is_decode_session(inst))
 			rc = msm_vdec_streamoff_output(inst);
 		else if (is_encode_session(inst))
 			rc = msm_venc_streamoff_output(inst);
-		else
-			goto error;
 	} else {
 		i_vpr_e(inst, "%s: invalid type %d\n", q->type);
 		goto error;
 	}
+	if (rc)
+		goto error;
+
+	/* Input port streamoff - flush timestamps list*/
+	if (q->type == INPUT_MPLANE)
+		msm_vidc_flush_ts(inst);
 
-	if (!rc)
-		i_vpr_h(inst, "Streamoff: %d successful\n", q->type);
+	i_vpr_h(inst, "Streamoff: %d successful\n", q->type);
 	return;
 
 error:

+ 1 - 1
driver/vidc/src/venus_hfi_response.c

@@ -1281,7 +1281,7 @@ static int handle_session_property(struct msm_vidc_inst *inst,
 				__func__, pkt->port, pkt->type);
 			break;
 		}
-		i_vpr_e(inst, "received prop_no_output attached input\n");
+		i_vpr_h(inst, "received no_output property\n");
 		inst->hfi_frame_info.no_output = 1;
 		break;
 	case HFI_PROP_WORST_COMPRESSION_RATIO: