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

Commit 38b1e119 authored by Govindaraj Rajagopal's avatar Govindaraj Rajagopal
Browse files

msm: vidc: queue batched buffers upon timeout



Client expects all the buffers to be returned in certain scenarios
but driver does not return due to decode batching feature. Add
delayed_work functionality to queue batched buffers to video hardware
upon timeout, so that all the buffers will be returned to client.

Change-Id: I926de1da93d941ff2a64bfec1bbd351de2f3a601
Signed-off-by: default avatarGovindaraj Rajagopal <grajagop@codeaurora.org>
parent ac0ba4c8
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -555,6 +555,12 @@ static int msm_vidc_probe_vidc_device(struct platform_device *pdev)
		goto err_cores_exceeded;
	}

	core->vidc_core_workq = create_singlethread_workqueue(
			"vidc_core_workq");
	if (!core->vidc_core_workq) {
		dprintk(VIDC_ERR, "%s: create core workq failed\n", __func__);
		goto err_core_workq;
	}
	mutex_lock(&vidc_driver->lock);
	list_add_tail(&core->list, &vidc_driver->cores);
	mutex_unlock(&vidc_driver->lock);
@@ -581,6 +587,9 @@ static int msm_vidc_probe_vidc_device(struct platform_device *pdev)
	return rc;

err_fail_sub_device_probe:
	if (core->vidc_core_workq)
		destroy_workqueue(core->vidc_core_workq);
err_core_workq:
	vidc_hfi_deinitialize(core->hfi_type, core->device);
err_cores_exceeded:
	if (core->resources.cvp_internal) {
@@ -662,6 +671,8 @@ static int msm_vidc_remove(struct platform_device *pdev)
		return -EINVAL;
	}

	if (core->vidc_core_workq)
		destroy_workqueue(core->vidc_core_workq);
	vidc_hfi_deinitialize(core->hfi_type, core->device);
	if (core->resources.cvp_internal) {
		device_remove_file(&core->vdev[MSM_VIDC_CVP].vdev.dev,
+3 −0
Original line number Diff line number Diff line
@@ -1536,6 +1536,7 @@ void *msm_vidc_open(int core_id, int session_type)
	INIT_MSM_VIDC_LIST(&inst->etb_data);
	INIT_MSM_VIDC_LIST(&inst->fbd_data);

	INIT_DELAYED_WORK(&inst->batch_work, msm_vidc_batch_handler);
	kref_init(&inst->kref);

	inst->session_type = session_type;
@@ -1696,6 +1697,8 @@ static void msm_vidc_cleanup_instance(struct msm_vidc_inst *inst)
	}
	mutex_unlock(&inst->registeredbufs.lock);

	cancel_batch_work(inst);

	msm_comm_free_freq_table(inst);

	msm_comm_free_input_cr_table(inst);
+108 −28
Original line number Diff line number Diff line
@@ -4351,6 +4351,35 @@ static int msm_comm_qbuf_to_hfi(struct msm_vidc_inst *inst,
	return rc;
}

void msm_vidc_batch_handler(struct work_struct *work)
{
	int rc = 0;
	struct msm_vidc_inst *inst;

	inst = container_of(work, struct msm_vidc_inst, batch_work.work);

	inst = get_inst(get_vidc_core(MSM_VIDC_CORE_VENUS), inst);
	if (!inst) {
		dprintk(VIDC_ERR, "%s: invalid params\n", __func__);
		return;
	}

	if (inst->state == MSM_VIDC_CORE_INVALID) {
		dprintk(VIDC_ERR, "%s: invalid state\n", __func__);
		goto exit;
	}

	dprintk(VIDC_HIGH, "%s: %x: queue pending batch buffers\n",
		__func__, hash32_ptr(inst->session));

	rc = msm_comm_qbufs_batch(inst, NULL);
	if (rc)
		dprintk(VIDC_ERR, "%s: batch qbufs failed\n", __func__);

exit:
	put_inst(inst);
}

static int msm_comm_qbuf_superframe_to_hfi(struct msm_vidc_inst *inst,
		struct msm_vidc_buffer *mbuf)
{
@@ -4562,6 +4591,45 @@ int msm_comm_qbufs(struct msm_vidc_inst *inst)
	return rc;
}

int msm_comm_qbufs_batch(struct msm_vidc_inst *inst,
		struct msm_vidc_buffer *mbuf)
{
	int rc = 0;
	struct msm_vidc_buffer *buf;

	rc = msm_comm_scale_clocks_and_bus(inst);
	if (rc)
		dprintk(VIDC_ERR, "%s: scale clocks failed\n", __func__);

	mutex_lock(&inst->registeredbufs.lock);
	list_for_each_entry(buf, &inst->registeredbufs.list, list) {
		/* Don't queue if buffer is not OUTPUT_MPLANE */
		if (buf->vvb.vb2_buf.type != OUTPUT_MPLANE)
			goto loop_end;
		/* Don't queue if buffer is not a deferred buffer */
		if (!(buf->flags & MSM_VIDC_FLAG_DEFERRED))
			goto loop_end;
		/* Don't queue if RBR event is pending on this buffer */
		if (buf->flags & MSM_VIDC_FLAG_RBR_PENDING)
			goto loop_end;

		print_vidc_buffer(VIDC_HIGH, "batch-qbuf", inst, buf);
		rc = msm_comm_qbuf_to_hfi(inst, buf);
		if (rc) {
			dprintk(VIDC_ERR, "%s: Failed batch qbuf to hfi: %d\n",
				__func__, rc);
			break;
		}
loop_end:
		/* Queue pending buffers till the current buffer only */
		if (buf == mbuf)
			break;
	}
	mutex_unlock(&inst->registeredbufs.lock);

	return rc;
}

/*
 * msm_comm_qbuf_decode_batch - count the buffers which are not queued to
 *              firmware yet (count includes rbr pending buffers too) and
@@ -4574,9 +4642,8 @@ int msm_comm_qbuf_decode_batch(struct msm_vidc_inst *inst,
{
	int rc = 0;
	u32 count = 0;
	struct msm_vidc_buffer *buf;

	if (!inst || !mbuf) {
	if (!inst || !inst->core || !mbuf) {
		dprintk(VIDC_ERR, "%s: Invalid arguments\n", __func__);
		return -EINVAL;
	}
@@ -4601,41 +4668,53 @@ int msm_comm_qbuf_decode_batch(struct msm_vidc_inst *inst,
		if (count < inst->batch.size) {
			print_vidc_buffer(VIDC_HIGH,
				"batch-qbuf deferred", inst, mbuf);
			schedule_batch_work(inst);
			return 0;
		}

		/*
		 * Batch completed - queing bufs to firmware.
		 * so cancel pending work if any.
		 */
		cancel_batch_work(inst);
	}

	rc = msm_comm_scale_clocks_and_bus(inst);
	rc = msm_comm_qbufs_batch(inst, mbuf);
	if (rc)
		dprintk(VIDC_ERR, "%s: scale clocks failed\n", __func__);

	mutex_lock(&inst->registeredbufs.lock);
	list_for_each_entry(buf, &inst->registeredbufs.list, list) {
		/* Don't queue if buffer is not CAPTURE_MPLANE */
		if (buf->vvb.vb2_buf.type != OUTPUT_MPLANE)
			goto loop_end;
		/* Don't queue if buffer is not a deferred buffer */
		if (!(buf->flags & MSM_VIDC_FLAG_DEFERRED))
			goto loop_end;
		/* Don't queue if RBR event is pending on this buffer */
		if (buf->flags & MSM_VIDC_FLAG_RBR_PENDING)
			goto loop_end;

		print_vidc_buffer(VIDC_HIGH, "batch-qbuf", inst, buf);
		rc = msm_comm_qbuf_to_hfi(inst, buf);
		if (rc) {
		dprintk(VIDC_ERR, "%s: Failed qbuf to hfi: %d\n",
			__func__, rc);
			break;

	return rc;
}
loop_end:
		/* Queue pending buffers till the current buffer only */
		if (buf == mbuf)
			break;

int schedule_batch_work(struct msm_vidc_inst *inst)
{
	struct msm_vidc_core *core;
	struct msm_vidc_platform_resources *res;

	if (!inst || !inst->core) {
		dprintk(VIDC_ERR, "%s: Invalid arguments\n", __func__);
		return -EINVAL;
	}
	mutex_unlock(&inst->registeredbufs.lock);
	core = inst->core;
	res = &core->resources;

	return rc;
	cancel_delayed_work(&inst->batch_work);
	queue_delayed_work(core->vidc_core_workq, &inst->batch_work,
		msecs_to_jiffies(res->batch_timeout));

	return 0;
}

int cancel_batch_work(struct msm_vidc_inst *inst)
{
	if (!inst) {
		dprintk(VIDC_ERR, "%s: Invalid arguments\n", __func__);
		return -EINVAL;
	}
	cancel_delayed_work(&inst->batch_work);

	return 0;
}

int msm_comm_try_get_bufreqs(struct msm_vidc_inst *inst)
@@ -5331,6 +5410,7 @@ int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags)

	msm_clock_data_reset(inst);

	cancel_batch_work(inst);
	if (inst->state == MSM_VIDC_CORE_INVALID) {
		dprintk(VIDC_ERR,
				"Core %pK and inst %pK are in bad state\n",
+5 −0
Original line number Diff line number Diff line
@@ -286,12 +286,17 @@ void msm_comm_store_mark_data(struct msm_vidc_list *data_list,
void msm_comm_fetch_mark_data(struct msm_vidc_list *data_list,
		u32 index, u32 *mark_data, u32 *mark_target);
int msm_comm_release_mark_data(struct msm_vidc_inst *inst);
int msm_comm_qbufs_batch(struct msm_vidc_inst *inst,
		struct msm_vidc_buffer *mbuf);
int msm_comm_qbuf_decode_batch(struct msm_vidc_inst *inst,
		struct msm_vidc_buffer *mbuf);
int schedule_batch_work(struct msm_vidc_inst *inst);
int cancel_batch_work(struct msm_vidc_inst *inst);
int msm_comm_num_queued_bufs(struct msm_vidc_inst *inst, u32 type);
int msm_comm_set_index_extradata(struct msm_vidc_inst *inst,
		uint32_t extradata_id, uint32_t value);
int msm_comm_set_extradata(struct msm_vidc_inst *inst, uint32_t extradata_id,
		uint32_t value);
bool msm_comm_check_for_inst_overload(struct msm_vidc_core *core);
void msm_vidc_batch_handler(struct work_struct *work);
#endif
+2 −0
Original line number Diff line number Diff line
@@ -442,6 +442,7 @@ struct msm_vidc_core {
	struct msm_vidc_capability *capabilities;
	struct delayed_work fw_unload_work;
	struct work_struct ssr_work;
	struct workqueue_struct *vidc_core_workq;
	enum hal_ssr_trigger_type ssr_type;
	bool smmu_fault_handled;
	bool trigger_ssr;
@@ -518,6 +519,7 @@ struct msm_vidc_inst {
	struct msm_vidc_codec_data *codec_data;
	struct hal_hdr10_pq_sei hdr10_sei_params;
	struct batch_mode batch;
	struct delayed_work batch_work;
	struct msm_vidc_inst_smem_ops *smem_ops;
	int (*buffer_size_calculators)(struct msm_vidc_inst *inst);
};
Loading