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

Commit 9ab590fb authored by Arun Menon's avatar Arun Menon
Browse files

msm: vidc: Re-use scratch buffer during port reconfig



During port reconfig, if new scratch buffer requirements
are satisfied by existing scratch buffers, then
driver should reuse the same buffers. By avoiding
free and re-allocation of buffers we will reduce
port reconfiguration latency.

Change-Id: Ice43d1c94a002e1f38b03f2c320ded5a47fd1ef7
Signed-off-by: default avatarArun Menon <avmenon@codeaurora.org>
parent d3b0eac5
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1647,7 +1647,7 @@ int msm_vdec_cmd(struct msm_vidc_inst *inst, struct v4l2_decoder_cmd *dec)
					"Failed to recover from session_error: %d\n",
					rc);
		}
		rc = msm_comm_release_scratch_buffers(inst);
		rc = msm_comm_release_scratch_buffers(inst, false);
		if (rc)
			dprintk(VIDC_ERR,
				"Failed to release scratch buffers: %d\n", rc);
+1 −1
Original line number Diff line number Diff line
@@ -2861,7 +2861,7 @@ int msm_venc_cmd(struct msm_vidc_inst *inst, struct v4l2_encoder_cmd *enc)
					V4L2_EVENT_MSM_VIDC_CLOSE_DONE);
			return rc;
		}
		rc = msm_comm_release_scratch_buffers(inst);
		rc = msm_comm_release_scratch_buffers(inst, false);
		if (rc)
			dprintk(VIDC_ERR, "Failed to release scratch buf:%d\n",
				rc);
+1 −1
Original line number Diff line number Diff line
@@ -1362,7 +1362,7 @@ static void cleanup_instance(struct msm_vidc_inst *inst)
		}
		if (!list_empty(&inst->internalbufs)) {
			mutex_unlock(&inst->lock);
			if (msm_comm_release_scratch_buffers(inst))
			if (msm_comm_release_scratch_buffers(inst, false))
				dprintk(VIDC_ERR,
					"Failed to release scratch buffers\n");

+261 −160
Original line number Diff line number Diff line
@@ -2780,173 +2780,207 @@ err_no_mem:
	return rc;
}

static int set_scratch_buffers(struct msm_vidc_inst *inst,
	enum hal_buffer buffer_type)
static inline char *get_internal_buffer_name(enum hal_buffer buffer_type)
{
	switch (buffer_type) {
	case HAL_BUFFER_INTERNAL_SCRATCH: return "scratch";
	case HAL_BUFFER_INTERNAL_SCRATCH_1: return "scratch_1";
	case HAL_BUFFER_INTERNAL_SCRATCH_2: return "scratch_2";
	case HAL_BUFFER_INTERNAL_PERSIST: return "persist";
	case HAL_BUFFER_INTERNAL_PERSIST_1: return "persist_1";
	default: return "unknown";
	}
}

static int set_internal_buf_on_fw(struct msm_vidc_inst *inst,
				enum hal_buffer buffer_type,
				struct msm_smem *handle, bool reuse)
{
	int rc = 0;
	struct msm_smem *handle;
	struct internal_buf *binfo;
	struct vidc_buffer_addr_info buffer_info;
	u32 smem_flags = 0;
	struct hal_buffer_requirements *scratch_buf;
	int i;
	struct hfi_device *hdev;
	int rc = 0;

	hdev = inst->core->device;

	scratch_buf = get_buff_req_buffer(inst, buffer_type);
	if (!scratch_buf) {
		dprintk(VIDC_DBG,
			"This scratch buffer not required, buffer_type: %x\n",
			buffer_type);
		return 0;
	if (!inst || !inst->core || !inst->core->device || !handle) {
		dprintk(VIDC_ERR, "%s - invalid params\n", __func__);
		return -EINVAL;
	}
	dprintk(VIDC_DBG,
		"scratch: num = %d, size = %d\n",
		scratch_buf->buffer_count_actual,
		scratch_buf->buffer_size);

	if (inst->flags & VIDC_SECURE)
		smem_flags |= SMEM_SECURE;
	hdev = inst->core->device;

	if (scratch_buf->buffer_size) {
		for (i = 0; i < scratch_buf->buffer_count_actual;
				i++) {
			handle = msm_comm_smem_alloc(inst,
				scratch_buf->buffer_size, 1, smem_flags,
				buffer_type, 0);
			if (!handle) {
				dprintk(VIDC_ERR,
					"Failed to allocate scratch memory\n");
				rc = -ENOMEM;
				goto err_no_mem;
			}
	rc = msm_comm_smem_cache_operations(inst,
					handle, SMEM_CACHE_CLEAN);
	if (rc) {
		dprintk(VIDC_WARN,
				"Failed to clean cache may cause undefined behavior\n");
			"Failed to clean cache. May cause undefined behavior\n");
	}
			binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
			if (!binfo) {
				dprintk(VIDC_ERR, "Out of memory\n");
				rc = -ENOMEM;
				goto fail_kzalloc;
			}
			binfo->handle = handle;
			buffer_info.buffer_size = scratch_buf->buffer_size;

	buffer_info.buffer_size = handle->size;
	buffer_info.buffer_type = buffer_type;
			binfo->buffer_type = buffer_type;
	buffer_info.num_buffers = 1;
	buffer_info.align_device_addr = handle->device_addr;
			dprintk(VIDC_DBG, "Scratch buffer address: 0x%pa\n",
	dprintk(VIDC_DBG, "%s %s buffer : 0x%pa\n",
				reuse ? "Reusing" : "Allocated",
				get_internal_buffer_name(buffer_type),
				&buffer_info.align_device_addr);

	rc = call_hfi_op(hdev, session_set_buffers,
		(void *) inst->session, &buffer_info);
	if (rc) {
		dprintk(VIDC_ERR,
			"vidc_hal_session_set_buffers failed\n");
				goto fail_set_buffers;
		return rc;
	}
	return 0;
}

static bool reuse_scratch_buffers(struct msm_vidc_inst *inst,
			enum hal_buffer buffer_type)
{
	struct internal_buf *buf;
	int rc = 0;
	bool reused = false;

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

	mutex_lock(&inst->lock);
			list_add_tail(&binfo->list, &inst->internalbufs);
			mutex_unlock(&inst->lock);
	list_for_each_entry(buf, &inst->internalbufs, list) {
		if (!buf->handle) {
			reused = false;
			break;
		}

		if (buf->buffer_type != buffer_type)
			continue;

		rc = set_internal_buf_on_fw(inst, buffer_type,
				buf->handle, true);
		if (rc) {
			dprintk(VIDC_ERR,
				"%s: session_set_buffers failed\n", __func__);
			reused = false;
			break;
		}
		reused = true;
	}
	return rc;
fail_set_buffers:
	kfree(binfo);
fail_kzalloc:
	msm_comm_smem_free(inst, handle);
err_no_mem:
	return rc;
	mutex_unlock(&inst->lock);
	return reused;
}

static int set_persist_buffers(struct msm_vidc_inst *inst,
	enum hal_buffer buffer_type)
static int allocate_and_set_internal_bufs(struct msm_vidc_inst *inst,
			struct hal_buffer_requirements *internal_bufreq,
			struct list_head *buflist)
{
	int rc = 0;
	struct msm_smem *handle;
	struct internal_buf *binfo;
	struct vidc_buffer_addr_info buffer_info;
	u32 smem_flags = 0;
	struct hal_buffer_requirements *persist_buf;
	int i;
	struct hfi_device *hdev;
	int rc = 0;
	int i = 0;

	hdev = inst->core->device;
	if (!inst || !internal_bufreq || !buflist)
		return -EINVAL;

	persist_buf = get_buff_req_buffer(inst, buffer_type);
	if (!persist_buf) {
		dprintk(VIDC_DBG,
			"This persist buffer not required, buffer_type: %x\n",
			buffer_type);
	if (!internal_bufreq->buffer_size)
		return 0;
	}

	dprintk(VIDC_DBG,
		"persist: num = %d, size = %d\n",
		persist_buf->buffer_count_actual,
		persist_buf->buffer_size);
	if (!list_empty(&inst->persistbufs)) {
		dprintk(VIDC_ERR,
			"Persist buffers already allocated\n");
		return rc;
	}

	if (inst->flags & VIDC_SECURE)
		smem_flags |= SMEM_SECURE;

	if (persist_buf->buffer_size) {
		for (i = 0; i < persist_buf->buffer_count_actual; i++) {
			handle = msm_comm_smem_alloc(inst,
				persist_buf->buffer_size, 1, smem_flags,
				buffer_type, 0);
	for (i = 0; i < internal_bufreq->buffer_count_actual; i++) {
		handle = msm_comm_smem_alloc(inst, internal_bufreq->buffer_size,
				1, smem_flags, internal_bufreq->buffer_type, 0);
		if (!handle) {
			dprintk(VIDC_ERR,
					"Failed to allocate persist memory\n");
				"Failed to allocate scratch memory\n");
			rc = -ENOMEM;
			goto err_no_mem;
		}
			rc = msm_comm_smem_cache_operations(inst,
					handle, SMEM_CACHE_CLEAN);
			if (rc) {
				dprintk(VIDC_WARN,
				"Failed to clean cache may cause undefined behavior\n");
			}

		binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
		if (!binfo) {
			dprintk(VIDC_ERR, "Out of memory\n");
			rc = -ENOMEM;
			goto fail_kzalloc;
		}

		binfo->handle = handle;
			buffer_info.buffer_size = persist_buf->buffer_size;
			buffer_info.buffer_type = buffer_type;
			binfo->buffer_type = buffer_type;
			buffer_info.num_buffers = 1;
			buffer_info.align_device_addr = handle->device_addr;
			dprintk(VIDC_DBG, "Persist buffer address: 0x%pa\n",
					&buffer_info.align_device_addr);
			rc = call_hfi_op(hdev, session_set_buffers,
					(void *) inst->session, &buffer_info);
			if (rc) {
				dprintk(VIDC_ERR,
					"vidc_hal_session_set_buffers failed\n");
		binfo->buffer_type = internal_bufreq->buffer_type;

		rc = set_internal_buf_on_fw(inst, internal_bufreq->buffer_type,
				handle, false);
		if (rc)
			goto fail_set_buffers;
			}

		mutex_lock(&inst->lock);
			list_add_tail(&binfo->list, &inst->persistbufs);
		list_add_tail(&binfo->list, buflist);
		mutex_unlock(&inst->lock);
	}
	}
	return rc;

fail_set_buffers:
	kfree(binfo);
fail_kzalloc:
	msm_comm_smem_free(inst, handle);
err_no_mem:
	return rc;

}

static int set_scratch_buffers(struct msm_vidc_inst *inst,
	enum hal_buffer buffer_type)
{
	struct hal_buffer_requirements *scratch_buf;

	scratch_buf = get_buff_req_buffer(inst, buffer_type);
	if (!scratch_buf) {
		dprintk(VIDC_DBG,
			"This scratch buffer not required, buffer_type: %x\n",
			buffer_type);
		return 0;
	}
	dprintk(VIDC_DBG,
		"scratch: num = %d, size = %d\n",
		scratch_buf->buffer_count_actual,
		scratch_buf->buffer_size);

	/*
	* Try reusing existing scratch buffers first.
	* If it's not possible to reuse, allocate new buffers.
	*/
	if (reuse_scratch_buffers(inst, buffer_type))
		return 0;

	return allocate_and_set_internal_bufs(inst, scratch_buf,
				&inst->internalbufs);
}

static int set_persist_buffers(struct msm_vidc_inst *inst,
	enum hal_buffer buffer_type)
{
	struct hal_buffer_requirements *persist_buf;

	persist_buf = get_buff_req_buffer(inst, buffer_type);
	if (!persist_buf) {
		dprintk(VIDC_DBG,
			"This persist buffer not required, buffer_type: %x\n",
			buffer_type);
		return 0;
	}

	dprintk(VIDC_DBG,
		"persist: num = %d, size = %d\n",
		persist_buf->buffer_count_actual,
		persist_buf->buffer_size);
	if (!list_empty(&inst->persistbufs)) {
		dprintk(VIDC_ERR,
			"Persist buffers already allocated\n");
		return 0;
	}

	return allocate_and_set_internal_bufs(inst, persist_buf,
				&inst->persistbufs);
}

int msm_comm_try_state(struct msm_vidc_inst *inst, int state)
@@ -3522,7 +3556,51 @@ int msm_comm_release_output_buffers(struct msm_vidc_inst *inst)
	return rc;
}

int msm_comm_release_scratch_buffers(struct msm_vidc_inst *inst)
static enum hal_buffer scratch_buf_sufficient(struct msm_vidc_inst *inst,
					enum hal_buffer buffer_type)
{
	struct hal_buffer_requirements *bufreq = NULL;
	struct internal_buf *buf;
	int count = 0;

	if (!inst) {
		dprintk(VIDC_ERR, "%s - invalid param\n", __func__);
		goto not_sufficient;
	}

	bufreq = get_buff_req_buffer(inst, buffer_type);
	if (!bufreq)
		goto not_sufficient;

	/* Check if current scratch buffers are sufficient */
	mutex_lock(&inst->lock);
	list_for_each_entry(buf, &inst->internalbufs, list) {
		if (!buf->handle) {
			dprintk(VIDC_ERR, "%s: invalid buf handle\n", __func__);
			mutex_unlock(&inst->lock);
			goto not_sufficient;
		}
		if (buf->buffer_type == buffer_type &&
			buf->handle->size >= bufreq->buffer_size)
			count++;
	}
	mutex_unlock(&inst->lock);

	if (count != bufreq->buffer_count_actual)
		goto not_sufficient;

	dprintk(VIDC_DBG,
		"Existing scratch buffer is sufficient for buffer type 0x%x\n",
		buffer_type);

	return buffer_type;

not_sufficient:
	return HAL_BUFFER_NONE;
}

int msm_comm_release_scratch_buffers(struct msm_vidc_inst *inst,
					bool check_for_reuse)
{
	struct msm_smem *handle;
	struct list_head *ptr, *next;
@@ -3531,6 +3609,7 @@ int msm_comm_release_scratch_buffers(struct msm_vidc_inst *inst)
	int rc = 0;
	struct msm_vidc_core *core;
	struct hfi_device *hdev;
	enum hal_buffer sufficiency = HAL_BUFFER_NONE;
	if (!inst) {
		dprintk(VIDC_ERR,
				"Invalid instance pointer = %p\n", inst);
@@ -3547,11 +3626,27 @@ int msm_comm_release_scratch_buffers(struct msm_vidc_inst *inst)
		dprintk(VIDC_ERR, "Invalid device pointer = %p\n", hdev);
		return -EINVAL;
	}

	if (check_for_reuse) {
		sufficiency |= scratch_buf_sufficient(inst,
					HAL_BUFFER_INTERNAL_SCRATCH);

		sufficiency |= scratch_buf_sufficient(inst,
					HAL_BUFFER_INTERNAL_SCRATCH_1);

		sufficiency |= scratch_buf_sufficient(inst,
					HAL_BUFFER_INTERNAL_SCRATCH_2);
	}

	mutex_lock(&inst->lock);
	if (!list_empty(&inst->internalbufs)) {
	list_for_each_safe(ptr, next, &inst->internalbufs) {
		buf = list_entry(ptr, struct internal_buf,
				list);
		if (!buf || !buf->handle) {
			dprintk(VIDC_ERR, "%s - buf->handle NULL\n", __func__);
			rc = -EINVAL;
			goto exit;
		}
		handle = buf->handle;
		buffer_info.buffer_size = handle->size;
		buffer_info.buffer_type = buf->buffer_type;
@@ -3580,13 +3675,19 @@ int msm_comm_release_scratch_buffers(struct msm_vidc_inst *inst)
			}
			mutex_lock(&inst->lock);
		}

		/*If scratch buffers can be reused, do not free the buffers*/
		if (sufficiency & buf->buffer_type)
			continue;

		list_del(&buf->list);
		mutex_unlock(&inst->lock);
		msm_comm_smem_free(inst, buf->handle);
		kfree(buf);
		mutex_lock(&inst->lock);
	}
	}

exit:
	mutex_unlock(&inst->lock);
	return rc;
}
@@ -3719,7 +3820,7 @@ int msm_comm_set_scratch_buffers(struct msm_vidc_inst *inst)
		return -EINVAL;
	}

	if (msm_comm_release_scratch_buffers(inst))
	if (msm_comm_release_scratch_buffers(inst, true))
		dprintk(VIDC_WARN, "Failed to release scratch buffers\n");

	rc = set_scratch_buffers(inst, HAL_BUFFER_INTERNAL_SCRATCH);
@@ -3736,7 +3837,7 @@ int msm_comm_set_scratch_buffers(struct msm_vidc_inst *inst)

	return rc;
error:
	msm_comm_release_scratch_buffers(inst);
	msm_comm_release_scratch_buffers(inst, false);
	return rc;
}

+2 −1
Original line number Diff line number Diff line
@@ -40,7 +40,8 @@ void msm_comm_scale_clocks_and_bus(struct msm_vidc_inst *inst);
void msm_comm_init_dcvs(struct msm_vidc_inst *inst);
void msm_comm_init_dcvs_load(struct msm_vidc_inst *inst);
int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags);
int msm_comm_release_scratch_buffers(struct msm_vidc_inst *inst);
int msm_comm_release_scratch_buffers(struct msm_vidc_inst *inst,
					bool check_for_reuse);
int msm_comm_release_persist_buffers(struct msm_vidc_inst *inst);
int msm_comm_release_output_buffers(struct msm_vidc_inst *inst);
int msm_comm_force_cleanup(struct msm_vidc_inst *inst);
Loading