浏览代码

video: driver: introduce client lock

Acquire client lock for every entry point
in driver. This is needed especially for
streamoff and close calls where inst lock
is released while driver is waiting for
stop_done and close_done responses from fw.
When inst lock is released, client can send
a new ioctl call and driver state machine
can get updated leading to unexpected behaviour.

Change-Id: Ibb62c3431c88e2f1d9088d54fe7c9e53b1c284fd
Signed-off-by: Darshana Patil <[email protected]>
Darshana Patil 3 年之前
父节点
当前提交
2a687b2750

+ 3 - 0
driver/vidc/inc/msm_vidc_driver.h

@@ -519,6 +519,9 @@ bool core_lock_check(struct msm_vidc_core *core, const char *function);
 void inst_lock(struct msm_vidc_inst *inst, const char *function);
 void inst_unlock(struct msm_vidc_inst *inst, const char *function);
 bool inst_lock_check(struct msm_vidc_inst *inst, const char *function);
+bool client_lock_check(struct msm_vidc_inst *inst, const char *func);
+void client_lock(struct msm_vidc_inst *inst, const char *function);
+void client_unlock(struct msm_vidc_inst *inst, const char *function);
 int msm_vidc_update_bitstream_buffer_size(struct msm_vidc_inst *inst);
 int msm_vidc_update_meta_port_settings(struct msm_vidc_inst *inst);
 int msm_vidc_update_buffer_count(struct msm_vidc_inst *inst, u32 port);

+ 1 - 0
driver/vidc/inc/msm_vidc_inst.h

@@ -98,6 +98,7 @@ struct msm_vidc_inst {
 	struct list_head                   list;
 	struct mutex                       lock;
 	struct mutex                       request_lock;
+	struct mutex                       client_lock;
 	enum msm_vidc_inst_state           state;
 	enum msm_vidc_domain_type          domain;
 	enum msm_vidc_codec_type           codec;

+ 3 - 0
driver/vidc/src/msm_vidc.c

@@ -899,6 +899,7 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
 	kref_init(&inst->kref);
 	mutex_init(&inst->lock);
 	mutex_init(&inst->request_lock);
+	mutex_init(&inst->client_lock);
 	msm_vidc_update_debug_str(inst);
 	i_vpr_h(inst, "Opening video instance: %d\n", session_type);
 
@@ -1035,6 +1036,7 @@ int msm_vidc_close(void *instance)
 	core = inst->core;
 
 	i_vpr_h(inst, "%s()\n", __func__);
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	/* print final stats */
 	msm_vidc_print_stats(inst);
@@ -1042,6 +1044,7 @@ int msm_vidc_close(void *instance)
 	msm_vidc_remove_session(inst);
 	msm_vidc_destroy_buffers(inst);
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	cancel_response_work_sync(inst);
 	cancel_stability_work_sync(inst);
 	cancel_stats_work_sync(inst);

+ 16 - 0
driver/vidc/src/msm_vidc_driver.c

@@ -5620,6 +5620,7 @@ static void msm_vidc_close_helper(struct kref *kref)
 	if (inst->response_workq)
 		destroy_workqueue(inst->response_workq);
 	msm_vidc_remove_dangling_session(inst);
+	mutex_destroy(&inst->client_lock);
 	mutex_destroy(&inst->request_lock);
 	mutex_destroy(&inst->lock);
 	kfree(inst->capabilities);
@@ -5712,6 +5713,21 @@ void inst_unlock(struct msm_vidc_inst *inst, const char *function)
 	mutex_unlock(&inst->lock);
 }
 
+bool client_lock_check(struct msm_vidc_inst *inst, const char *func)
+{
+	return mutex_is_locked(&inst->client_lock);
+}
+
+void client_lock(struct msm_vidc_inst *inst, const char *function)
+{
+	mutex_lock(&inst->client_lock);
+}
+
+void client_unlock(struct msm_vidc_inst *inst, const char *function)
+{
+	mutex_unlock(&inst->client_lock);
+}
+
 int msm_vidc_update_bitstream_buffer_size(struct msm_vidc_inst *inst)
 {
 	struct msm_vidc_core *core;

+ 48 - 0
driver/vidc/src/msm_vidc_v4l2.c

@@ -76,6 +76,7 @@ int msm_v4l2_querycap(struct file *filp, void *fh,
 		return -EINVAL;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	rc = msm_vidc_querycap((void *)inst, cap);
 	if (rc)
@@ -83,6 +84,7 @@ int msm_v4l2_querycap(struct file *filp, void *fh,
 
 unlock:
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 
 	return rc;
@@ -100,6 +102,7 @@ int msm_v4l2_enum_fmt(struct file *filp, void *fh,
 		return -EINVAL;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	rc = msm_vidc_enum_fmt((void *)inst, f);
 	if (rc)
@@ -107,6 +110,7 @@ int msm_v4l2_enum_fmt(struct file *filp, void *fh,
 
 unlock:
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 
 	return rc;
@@ -123,6 +127,7 @@ int msm_v4l2_try_fmt(struct file *filp, void *fh, struct v4l2_format *f)
 		return -EINVAL;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	if (is_session_error(inst)) {
 		i_vpr_e(inst, "%s: inst in error state\n", __func__);
@@ -135,6 +140,7 @@ int msm_v4l2_try_fmt(struct file *filp, void *fh, struct v4l2_format *f)
 
 unlock:
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 
 	return rc;
@@ -152,6 +158,7 @@ int msm_v4l2_s_fmt(struct file *filp, void *fh,
 		return -EINVAL;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	if (is_session_error(inst)) {
 		i_vpr_e(inst, "%s: inst in error state\n", __func__);
@@ -164,6 +171,7 @@ int msm_v4l2_s_fmt(struct file *filp, void *fh,
 
 unlock:
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 
 	return rc;
@@ -181,6 +189,7 @@ int msm_v4l2_g_fmt(struct file *filp, void *fh,
 		return -EINVAL;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	rc = msm_vidc_g_fmt((void *)inst, f);
 	if (rc)
@@ -188,6 +197,7 @@ int msm_v4l2_g_fmt(struct file *filp, void *fh,
 
 unlock:
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 
 	return rc;
@@ -205,6 +215,7 @@ int msm_v4l2_s_selection(struct file *filp, void *fh,
 		return -EINVAL;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	if (is_session_error(inst)) {
 		i_vpr_e(inst, "%s: inst in error state\n", __func__);
@@ -217,6 +228,7 @@ int msm_v4l2_s_selection(struct file *filp, void *fh,
 
 unlock:
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 
 	return rc;
@@ -234,6 +246,7 @@ int msm_v4l2_g_selection(struct file *filp, void *fh,
 		return -EINVAL;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	rc = msm_vidc_g_selection((void *)inst, s);
 	if (rc)
@@ -241,6 +254,7 @@ int msm_v4l2_g_selection(struct file *filp, void *fh,
 
 unlock:
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 
 	return rc;
@@ -258,6 +272,7 @@ int msm_v4l2_s_parm(struct file *filp, void *fh,
 		return -EINVAL;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	if (is_session_error(inst)) {
 		i_vpr_e(inst, "%s: inst in error state\n", __func__);
@@ -270,6 +285,7 @@ int msm_v4l2_s_parm(struct file *filp, void *fh,
 
 unlock:
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 
 	return rc;
@@ -287,6 +303,7 @@ int msm_v4l2_g_parm(struct file *filp, void *fh,
 		return -EINVAL;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	rc = msm_vidc_g_param((void *)inst, a);
 	if (rc)
@@ -294,6 +311,7 @@ int msm_v4l2_g_parm(struct file *filp, void *fh,
 
 unlock:
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 
 	return rc;
@@ -311,6 +329,7 @@ int msm_v4l2_reqbufs(struct file *filp, void *fh,
 		return -EINVAL;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	rc = msm_vidc_reqbufs((void *)inst, b);
 	if (rc)
@@ -318,6 +337,7 @@ int msm_v4l2_reqbufs(struct file *filp, void *fh,
 
 unlock:
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 
 	return rc;
@@ -335,6 +355,7 @@ int msm_v4l2_querybuf(struct file *filp, void *fh,
 		return -EINVAL;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	rc = msm_vidc_querybuf((void *)inst, b);
 	if (rc)
@@ -342,6 +363,7 @@ int msm_v4l2_querybuf(struct file *filp, void *fh,
 
 unlock:
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 
 	return rc;
@@ -360,12 +382,14 @@ int msm_v4l2_create_bufs(struct file *filp, void *fh,
 	}
 
 	inst_lock(inst, __func__);
+	client_lock(inst, __func__);
 	rc = msm_vidc_create_bufs((void *)inst, b);
 	if (rc)
 		goto unlock;
 
 unlock:
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 
 	return rc;
@@ -384,6 +408,7 @@ int msm_v4l2_prepare_buf(struct file *filp, void *fh,
 		return -EINVAL;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	rc = msm_vidc_prepare_buf((void *)inst, vdev->v4l2_dev->mdev, b);
 	if (rc)
@@ -391,6 +416,7 @@ int msm_v4l2_prepare_buf(struct file *filp, void *fh,
 
 unlock:
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 
 	return rc;
@@ -439,6 +465,7 @@ int msm_v4l2_dqbuf(struct file *filp, void *fh,
 		return -EINVAL;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	rc = msm_vidc_dqbuf(inst, b);
 	if (rc)
@@ -446,6 +473,7 @@ int msm_v4l2_dqbuf(struct file *filp, void *fh,
 
 unlock:
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 
 	return rc;
@@ -508,6 +536,7 @@ int msm_v4l2_subscribe_event(struct v4l2_fh *fh,
 		return -EINVAL;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	if (is_session_error(inst)) {
 		i_vpr_e(inst, "%s: inst in error state\n", __func__);
@@ -520,6 +549,7 @@ int msm_v4l2_subscribe_event(struct v4l2_fh *fh,
 
 unlock:
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 
 	return rc;
@@ -538,6 +568,7 @@ int msm_v4l2_unsubscribe_event(struct v4l2_fh *fh,
 		return -EINVAL;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	rc = msm_vidc_unsubscribe_event((void *)inst, sub);
 	if (rc)
@@ -545,6 +576,7 @@ int msm_v4l2_unsubscribe_event(struct v4l2_fh *fh,
 
 unlock:
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 
 	return rc;
@@ -562,6 +594,7 @@ int msm_v4l2_try_decoder_cmd(struct file *filp, void *fh,
 		return -EINVAL;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	if (is_session_error(inst)) {
 		i_vpr_e(inst, "%s: inst in error state\n", __func__);
@@ -574,6 +607,7 @@ int msm_v4l2_try_decoder_cmd(struct file *filp, void *fh,
 
 unlock:
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 
 	return rc;
@@ -591,6 +625,7 @@ int msm_v4l2_decoder_cmd(struct file *filp, void *fh,
 		return -EINVAL;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	if (is_session_error(inst)) {
 		i_vpr_e(inst, "%s: inst in error state\n", __func__);
@@ -603,6 +638,7 @@ int msm_v4l2_decoder_cmd(struct file *filp, void *fh,
 
 unlock:
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 
 	return rc;
@@ -620,6 +656,7 @@ int msm_v4l2_try_encoder_cmd(struct file *filp, void *fh,
 		return -EINVAL;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	if (is_session_error(inst)) {
 		i_vpr_e(inst, "%s: inst in error state\n", __func__);
@@ -632,6 +669,7 @@ int msm_v4l2_try_encoder_cmd(struct file *filp, void *fh,
 
 unlock:
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 
 	return rc;
@@ -649,6 +687,7 @@ int msm_v4l2_encoder_cmd(struct file *filp, void *fh,
 		return -EINVAL;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	if (is_session_error(inst)) {
 		i_vpr_e(inst, "%s: inst in error state\n", __func__);
@@ -661,6 +700,7 @@ int msm_v4l2_encoder_cmd(struct file *filp, void *fh,
 
 unlock:
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 
 	return rc;
@@ -678,6 +718,7 @@ int msm_v4l2_enum_framesizes(struct file *filp, void *fh,
 		return -EINVAL;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	rc = msm_vidc_enum_framesizes((void *)inst, fsize);
 	if (rc)
@@ -685,6 +726,7 @@ int msm_v4l2_enum_framesizes(struct file *filp, void *fh,
 
 unlock:
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 
 	return rc;
@@ -702,6 +744,7 @@ int msm_v4l2_enum_frameintervals(struct file *filp, void *fh,
 		return -EINVAL;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	rc = msm_vidc_enum_frameintervals((void *)inst, fival);
 	if (rc)
@@ -709,6 +752,7 @@ int msm_v4l2_enum_frameintervals(struct file *filp, void *fh,
 
 unlock:
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 
 	return rc;
@@ -726,6 +770,7 @@ int msm_v4l2_queryctrl(struct file *filp, void *fh,
 		return -EINVAL;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	rc = msm_vidc_query_ctrl((void *)inst, ctrl);
 	if (rc)
@@ -733,6 +778,7 @@ int msm_v4l2_queryctrl(struct file *filp, void *fh,
 
 unlock:
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 
 	return rc;
@@ -750,6 +796,7 @@ int msm_v4l2_querymenu(struct file *filp, void *fh,
 		return -EINVAL;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	rc = msm_vidc_query_menu((void *)inst, qmenu);
 	if (rc)
@@ -757,6 +804,7 @@ int msm_v4l2_querymenu(struct file *filp, void *fh,
 
 unlock:
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 
 	return rc;

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

@@ -204,6 +204,7 @@ int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count)
 		return -EINVAL;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	if (is_session_error(inst)) {
 		i_vpr_e(inst, "%s: inst in error state\n", __func__);
@@ -337,6 +338,7 @@ unlock:
 		msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
 	}
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 	return rc;
 }
@@ -358,6 +360,7 @@ void msm_vidc_stop_streaming(struct vb2_queue *q)
 		return;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	if (q->type == INPUT_META_PLANE || q->type == OUTPUT_META_PLANE) {
 		i_vpr_h(inst, "%s: nothing to stop on %s\n",
@@ -420,6 +423,7 @@ unlock:
 		msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
 	}
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 	return;
 }
@@ -443,6 +447,7 @@ void msm_vidc_buf_queue(struct vb2_buffer *vb2)
 		return;
 	}
 
+	client_lock(inst, __func__);
 	inst_lock(inst, __func__);
 	if (is_session_error(inst)) {
 		i_vpr_e(inst, "%s: inst in error state\n", __func__);
@@ -525,6 +530,7 @@ unlock:
 		vb2_buffer_done(vb2, VB2_BUF_STATE_ERROR);
 	}
 	inst_unlock(inst, __func__);
+	client_unlock(inst, __func__);
 	put_inst(inst);
 }