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

Commit 3f89b7e6 authored by Arun Menon's avatar Arun Menon
Browse files

msm: vidc: handle dynamic buffers in pendingq during flush



In dynamic buffer mode, if flush was received before
stream-on, driver would have incremented the ref count
for output buffers, but not yet sent to firmware. So,
after flush done, there would be no fbd from firmware
and the reference to these buffers would not be removed.
So when the buffers are dequeued, driver fails to
unmap and free the output buffers.
Subsequently, after flush done, when client queues
the same output buffers again to driver, the ref
count is increased and becomes 2. This results in
the driver holding the buffers with itself, thereby
entering in to a deadlock situation and starving the
firmware of output buffers. This results in a video
freeze.

Change-Id: I0c3d13124bd48b900e56e14666eaed2f0e7ee9d6
Signed-off-by: default avatarArun Menon <avmenon@codeaurora.org>
parent 810f6916
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
@@ -3868,6 +3868,40 @@ void msm_comm_flush_dynamic_buffers(struct msm_vidc_inst *inst)
	mutex_unlock(&inst->lock);
}

void msm_comm_flush_pending_dynamic_buffers(struct msm_vidc_inst *inst)
{
	struct buffer_info *binfo = NULL;
	struct list_head *list = NULL;

	if (!inst)
		return;

	if (inst->buffer_mode_set[CAPTURE_PORT] != HAL_BUFFER_MODE_DYNAMIC)
		return;

	if (list_empty(&inst->pendingq) || list_empty(&inst->registered_bufs))
		return;

	list = &inst->registered_bufs;

	/*
	* Dynamic Buffer mode - Since pendingq is not empty
	* no output buffers have been sent to firmware yet.
	* Hence remove reference to all pendingq o/p buffers
	* before flushing them.
	*/

	list_for_each_entry(binfo, list, list) {
		if (binfo && binfo->type ==
			V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
			dprintk(VIDC_DBG,
				"%s: binfo = %p device_addr = 0x%pa\n",
				__func__, binfo, &binfo->device_addr[0]);
			buf_ref_put(inst, binfo);
		}
	}
}

int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags)
{
	int rc =  0;
@@ -3933,6 +3967,8 @@ int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags)

	} else {
		if (!list_empty(&inst->pendingq)) {
			msm_comm_flush_pending_dynamic_buffers(inst);

			/*If flush is called after queueing buffers but before
			 * streamon driver should flush the pending queue*/
			list_for_each_safe(ptr, next, &inst->pendingq) {