Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 54865848 authored by Praneeth Paladugu's avatar Praneeth Paladugu
Browse files

msm: vidc: Fix race condition in STOP command



When clients send ETB's to driver, driver may defer them due
to instance not being moved to START_DONE yet. But the Stop
command may send ETB directly to HW without instance moving
to START_DONE. This results in unknown behavior from HW.
Hence before sending EOS ETB to HW, check the state. If not
reached right state, defer it same as ETB. Send these pending
EOS buffers when inst moved to START_DONE after sending pending
ETB's.

CRs-Fixed: 2095440
Change-Id: I510373ee8b13a13d8841171fd074b161ca8f5fd4
Signed-off-by: default avatarPraneeth Paladugu <ppaladug@codeaurora.org>
parent 2f89b761
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -1024,6 +1024,14 @@ static int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count)
		goto stream_start_failed;
	}

	rc = msm_vidc_send_pending_eos_buffers(inst);
	if (rc) {
		dprintk(VIDC_ERR,
			"Failed : Send pending EOS buffs for Inst = %pK, %d\n",
				inst, rc);
		goto stream_start_failed;
	}

stream_start_failed:
	if (rc) {
		struct msm_vidc_buffer *temp, *next;
+45 −18
Original line number Diff line number Diff line
@@ -3625,6 +3625,42 @@ int msm_comm_try_state(struct msm_vidc_inst *inst, int state)
	return rc;
}

int msm_vidc_send_pending_eos_buffers(struct msm_vidc_inst *inst)
{
	struct vidc_frame_data data = {0};
	struct hfi_device *hdev;
	struct eos_buf *binfo = NULL, *temp = NULL;
	int rc = 0;

	if (!inst || !inst->core || !inst->core->device) {
		dprintk(VIDC_ERR, "%s: Invalid arguments\n", __func__);
		return -EINVAL;
	}

	mutex_lock(&inst->eosbufs.lock);
	list_for_each_entry_safe(binfo, temp, &inst->eosbufs.list, list) {
		data.alloc_len = binfo->smem.size;
		data.device_addr = binfo->smem.device_addr;
		data.clnt_data = data.device_addr;
		data.buffer_type = HAL_BUFFER_INPUT;
		data.filled_len = 0;
		data.offset = 0;
		data.flags = HAL_BUFFERFLAG_EOS;
		data.timestamp = LLONG_MAX;
		data.extradata_addr = data.device_addr;
		data.extradata_size = 0;
		dprintk(VIDC_DBG, "Queueing EOS buffer %pK\n",
				(void *)(u64)data.device_addr);
		hdev = inst->core->device;

		rc = call_hfi_op(hdev, session_etb, inst->session,
				&data);
	}
	mutex_unlock(&inst->eosbufs.lock);

	return rc;
}

int msm_vidc_comm_cmd(void *instance, union msm_v4l2_cmd *cmd)
{
	struct msm_vidc_inst *inst = instance;
@@ -3697,9 +3733,7 @@ int msm_vidc_comm_cmd(void *instance, union msm_v4l2_cmd *cmd)
	}
	case V4L2_DEC_CMD_STOP:
	{
		struct vidc_frame_data data = {0};
		struct hfi_device *hdev;
		struct eos_buf *binfo;
		struct eos_buf *binfo = NULL;
		u32 smem_flags = 0;

		get_inst(inst->core, inst);
@@ -3726,6 +3760,7 @@ int msm_vidc_comm_cmd(void *instance, union msm_v4l2_cmd *cmd)
		if (rc) {
			dprintk(VIDC_ERR,
				"Failed to allocate output memory\n");
			rc = -ENOMEM;
			goto exit;
		}

@@ -3733,22 +3768,14 @@ int msm_vidc_comm_cmd(void *instance, union msm_v4l2_cmd *cmd)
		list_add_tail(&binfo->list, &inst->eosbufs.list);
		mutex_unlock(&inst->eosbufs.lock);

		data.alloc_len = binfo->smem.size;
		data.device_addr = binfo->smem.device_addr;
		data.clnt_data = data.device_addr;
		data.buffer_type = HAL_BUFFER_INPUT;
		data.filled_len = 0;
		data.offset = 0;
		data.flags = HAL_BUFFERFLAG_EOS;
		data.timestamp = LLONG_MAX;
		data.extradata_addr = data.device_addr;
		data.extradata_size = 0;
		dprintk(VIDC_DBG, "Queueing EOS buffer %pK\n",
			(void *)(u64)data.device_addr);
		hdev = inst->core->device;
		if (inst->state != MSM_VIDC_START_DONE) {
			dprintk(VIDC_DBG,
				"Inst = %pK is not ready for EOS\n", inst);
			goto exit;
		}

		rc = msm_vidc_send_pending_eos_buffers(inst);

		rc = call_hfi_op(hdev, session_etb, inst->session,
				&data);
exit:
		put_inst(inst);
		break;
+1 −0
Original line number Diff line number Diff line
@@ -103,6 +103,7 @@ void msm_comm_print_inst_info(struct msm_vidc_inst *inst);
int msm_comm_v4l2_to_hal(int id, int value);
int msm_comm_hal_to_v4l2(int id, int value);
int msm_comm_session_continue(void *instance);
int msm_vidc_send_pending_eos_buffers(struct msm_vidc_inst *inst);
enum hal_uncompressed_format msm_comm_get_hal_uncompressed(int fourcc);
u32 get_frame_size_nv12(int plane, u32 height, u32 width);
u32 get_frame_size_nv12_ubwc(int plane, u32 height, u32 width);