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

Commit 71d00a58 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

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

parents 0cd19211 9ab590fb
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