msm: vidc: fix lock issue in msm_comm_get_mbs_per_sec()

Forward thread acquired v4l2_ctrl->handler->lock in
v4l2_s_ctrl() and waiting for response from response thread.
Response thread was blocked on core->lock which was acquired
by second forward thread. The second forward thread acquired
core->lock and called v4l2_g_ctrl() in msm_comm_get_mbs_per_sec()
where it was blocked on same v4l2_ctrl->handler->lock and hence
response thread was not unblocked. Resolve the deadlock issue
by avoiding v4l2_g_ctrl() call in msm_comm_get_mbs_per_sec().

CRs-Fixed: 1095539
Change-Id: I73c2a74f1bb86f2b0359be54ed4f7675051db7b0
Signed-off-by: Maheshwar Ajja <majja@codeaurora.org>
This commit is contained in:
Maheshwar Ajja 2016-11-29 13:14:11 -08:00
parent d43553d47d
commit 076fd7d351
4 changed files with 53 additions and 24 deletions

View file

@ -1903,6 +1903,7 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst)
inst->buffer_mode_set[OUTPUT_PORT] = HAL_BUFFER_MODE_STATIC;
inst->buffer_mode_set[CAPTURE_PORT] = HAL_BUFFER_MODE_STATIC;
inst->prop.fps = DEFAULT_FPS;
inst->operating_rate = 0;
memcpy(&inst->fmts[OUTPUT_PORT], &vdec_formats[2],
sizeof(struct msm_vidc_format));
memcpy(&inst->fmts[CAPTURE_PORT], &vdec_formats[0],
@ -2501,8 +2502,25 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
*/
hal_property.enable = !(ctrl->val);
pdata = &hal_property;
switch (ctrl->val) {
case V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_DISABLE:
inst->flags &= ~VIDC_REALTIME;
break;
case V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_ENABLE:
inst->flags |= VIDC_REALTIME;
break;
default:
dprintk(VIDC_WARN,
"inst(%pK) invalid priority ctrl value %#x\n",
inst, ctrl->val);
break;
}
break;
case V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE:
dprintk(VIDC_DBG,
"inst(%pK) operating rate changed from %d to %d\n",
inst, inst->operating_rate >> 16, ctrl->val >> 16);
inst->operating_rate = ctrl->val;
break;
default:
break;

View file

@ -3166,8 +3166,25 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
*/
enable.enable = !(ctrl->val);
pdata = &enable;
switch (ctrl->val) {
case V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_DISABLE:
inst->flags &= ~VIDC_REALTIME;
break;
case V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_ENABLE:
inst->flags |= VIDC_REALTIME;
break;
default:
dprintk(VIDC_WARN,
"inst(%pK) invalid priority ctrl value %#x\n",
inst, ctrl->val);
break;
}
break;
case V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE:
dprintk(VIDC_DBG,
"inst(%pK) operating rate changed from %d to %d\n",
inst, inst->operating_rate >> 16, ctrl->val >> 16);
inst->operating_rate = ctrl->val;
break;
case V4L2_CID_MPEG_VIDC_VIDEO_VENC_BITRATE_TYPE:
{
@ -3558,6 +3575,7 @@ int msm_venc_inst_init(struct msm_vidc_inst *inst)
inst->buffer_mode_set[CAPTURE_PORT] = HAL_BUFFER_MODE_STATIC;
inst->prop.fps = DEFAULT_FPS;
inst->capability.pixelprocess_capabilities = 0;
inst->operating_rate = 0;
memcpy(&inst->fmts[CAPTURE_PORT], &venc_formats[4],
sizeof(struct msm_vidc_format));
memcpy(&inst->fmts[OUTPUT_PORT], &venc_formats[0],

View file

@ -107,6 +107,11 @@ static inline bool is_low_power_session(struct msm_vidc_inst *inst)
return !!(inst->flags & VIDC_LOW_POWER);
}
static inline bool is_realtime_session(struct msm_vidc_inst *inst)
{
return !!(inst->flags & VIDC_REALTIME);
}
int msm_comm_g_ctrl(struct msm_vidc_inst *inst, struct v4l2_control *ctrl)
{
return v4l2_g_ctrl(&inst->ctrl_handler, ctrl);
@ -257,16 +262,6 @@ int msm_comm_ctrl_deinit(struct msm_vidc_inst *inst)
return 0;
}
static inline bool is_non_realtime_session(struct msm_vidc_inst *inst)
{
int rc = 0;
struct v4l2_control ctrl = {
.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY
};
rc = msm_comm_g_ctrl(inst, &ctrl);
return (!rc && ctrl.value);
}
enum multi_stream msm_comm_get_stream_output_mode(struct msm_vidc_inst *inst)
{
switch (msm_comm_g_ctrl_for_id(inst,
@ -282,8 +277,7 @@ enum multi_stream msm_comm_get_stream_output_mode(struct msm_vidc_inst *inst)
static int msm_comm_get_mbs_per_sec(struct msm_vidc_inst *inst)
{
int output_port_mbs, capture_port_mbs;
int fps, rc;
struct v4l2_control ctrl;
int fps;
output_port_mbs = inst->in_reconfig ?
NUM_MBS_PER_FRAME(inst->reconfig_width,
@ -294,19 +288,19 @@ static int msm_comm_get_mbs_per_sec(struct msm_vidc_inst *inst)
capture_port_mbs = NUM_MBS_PER_FRAME(inst->prop.width[CAPTURE_PORT],
inst->prop.height[CAPTURE_PORT]);
ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE;
rc = msm_comm_g_ctrl(inst, &ctrl);
if (!rc && ctrl.value) {
fps = (ctrl.value >> 16) ? ctrl.value >> 16 : 1;
if (inst->operating_rate) {
fps = (inst->operating_rate >> 16) ?
inst->operating_rate >> 16 : 1;
/*
* Check if operating rate is less than fps.
* If Yes, then use fps to scale clocks
*/
fps = fps > inst->prop.fps ? fps : inst->prop.fps;
return max(output_port_mbs, capture_port_mbs) * fps;
} else
} else {
return max(output_port_mbs, capture_port_mbs) * inst->prop.fps;
}
}
int msm_comm_get_inst_load(struct msm_vidc_inst *inst,
enum load_calc_quirks quirks)
@ -344,7 +338,7 @@ int msm_comm_get_inst_load(struct msm_vidc_inst *inst,
* ----------------|----------------------|------------------------|
*/
if (is_non_realtime_session(inst) &&
if (!is_realtime_session(inst) &&
(quirks & LOAD_CALC_IGNORE_NON_REALTIME_LOAD)) {
if (!inst->prop.fps) {
dprintk(VIDC_INFO, "instance:%pK fps = 0\n", inst);
@ -523,7 +517,6 @@ static int msm_comm_vote_bus(struct msm_vidc_core *core)
list_for_each_entry(inst, &core->instances, list) {
int codec = 0, yuv = 0;
struct v4l2_control ctrl;
codec = inst->session_type == MSM_VIDC_DECODER ?
inst->fmts[OUTPUT_PORT].fourcc :
@ -540,11 +533,9 @@ static int msm_comm_vote_bus(struct msm_vidc_core *core)
vote_data[i].height = max(inst->prop.height[CAPTURE_PORT],
inst->prop.height[OUTPUT_PORT]);
ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE;
rc = msm_comm_g_ctrl(inst, &ctrl);
if (!rc && ctrl.value)
vote_data[i].fps = (ctrl.value >> 16) ?
ctrl.value >> 16 : 1;
if (inst->operating_rate)
vote_data[i].fps = (inst->operating_rate >> 16) ?
inst->operating_rate >> 16 : 1;
else
vote_data[i].fps = inst->prop.fps;

View file

@ -230,6 +230,7 @@ enum msm_vidc_modes {
VIDC_TURBO = BIT(1),
VIDC_THUMBNAIL = BIT(2),
VIDC_LOW_POWER = BIT(3),
VIDC_REALTIME = BIT(4),
};
struct msm_vidc_core {
@ -298,6 +299,7 @@ struct msm_vidc_inst {
atomic_t in_flush;
u32 pic_struct;
u32 colour_space;
u32 operating_rate;
};
extern struct msm_vidc_drv *vidc_driver;