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

Commit 7b61e61f authored by George Shen's avatar George Shen
Browse files

msm: cvp: Enhance CVP release persist buf process



Do not release CVP persist buffer until all outstanding frames
are handled by firmware.

Change-Id: I4cbff7898f57db82bd3ab2ee8a9a15873e458f2d
Signed-off-by: default avatarGeorge Shen <sqiao@codeaurora.org>
parent f69d3db0
Loading
Loading
Loading
Loading
+14 −8
Original line number Diff line number Diff line
@@ -209,7 +209,8 @@ static int msm_cvp_session_process_hfi(
		return -EINVAL;
	}
	pkt_type = in_pkt->pkt_data[1];
	if (pkt_type == HFI_CMD_SESSION_CVP_SET_PERSIST_BUFFERS)
	if (pkt_type == HFI_CMD_SESSION_CVP_SET_PERSIST_BUFFERS ||
		pkt_type == HFI_CMD_SESSION_CVP_SET_MODEL_BUFFERS)
		rc = msm_cvp_map_user_persist(inst, in_pkt, offset, buf_num);
	else if (pkt_type == HFI_CMD_SESSION_CVP_RELEASE_PERSIST_BUFFERS)
		rc = msm_cvp_mark_user_persist(inst, in_pkt, offset, buf_num);
@@ -297,8 +298,10 @@ static int cvp_fence_dme(struct msm_cvp_inst *inst,
	sq = &inst->session_queue_fence;
	ktid = pkt->client_data.kdata;

	if (cvp_synx_ops(inst, CVP_INPUT_SYNX, fc, &synx_state))
	if (cvp_synx_ops(inst, CVP_INPUT_SYNX, fc, &synx_state)) {
		msm_cvp_unmap_frame(inst, pkt->client_data.kdata);
		goto exit;
	}

	rc = call_hfi_op(hdev, session_send, (void *)inst->session,
			(struct cvp_kmd_hfi_packet *)pkt);
@@ -359,8 +362,10 @@ static int cvp_fence_proc(struct msm_cvp_inst *inst,
	sq = &inst->session_queue_fence;
	ktid = pkt->client_data.kdata;

	if (cvp_synx_ops(inst, CVP_INPUT_SYNX, fc, &synx_state))
	if (cvp_synx_ops(inst, CVP_INPUT_SYNX, fc, &synx_state)) {
		msm_cvp_unmap_frame(inst, pkt->client_data.kdata);
		goto exit;
	}

	rc = call_hfi_op(hdev, session_send, (void *)inst->session,
			(struct cvp_kmd_hfi_packet *)pkt);
@@ -461,8 +466,8 @@ static int cvp_fence_thread(void *data)
	synx = (u32 *)f->synx;

	ktid = pkt->client_data.kdata & (FENCE_BIT - 1);
	dprintk(CVP_SYNX, "%s starts working on frame %llu frameID %llu\n",
		current->comm, ktid, f->frame_id);
	dprintk(CVP_SYNX, "%s on frame %llu frameID %llu ktid %llu\n",
		current->comm, ktid, f->frame_id, ktid);

	switch (f->type) {
	case HFI_CMD_SESSION_CVP_DME_FRAME:
@@ -484,8 +489,8 @@ static int cvp_fence_thread(void *data)
	list_del_init(&f->list);
	mutex_unlock(&q->lock);

	dprintk(CVP_SYNX, "%s is done with frame %llu frameID %llu\n",
		current->comm, ktid, f->frame_id);
	dprintk(CVP_SYNX, "%s is done with frame %llu frameID %llu rc %d\n",
		current->comm, ktid, f->frame_id, rc);

	cvp_free_fence_data(f);

@@ -585,7 +590,8 @@ static int msm_cvp_session_process_hfi_fence(struct msm_cvp_inst *inst,
	}


	dprintk(CVP_SYNX, "%s: frameID %llu\n", __func__, f->frame_id);
	dprintk(CVP_SYNX, "%s: frameID %llu ktid %llu\n",
			__func__, f->frame_id, pkt->client_data.kdata);

	memcpy(f->pkt, pkt, pkt->size);

+51 −43
Original line number Diff line number Diff line
@@ -127,7 +127,7 @@ int msm_cvp_map_buf_dsp(struct msm_cvp_inst *inst, struct cvp_kmd_buffer *buf)
	smem->dma_buf = dma_buf;
	smem->bitmap_index = MAX_DMABUF_NUMS;
	dprintk(CVP_DSP, "%s: dma_buf = %llx\n", __func__, dma_buf);
	rc = msm_cvp_map_smem(inst, smem);
	rc = msm_cvp_map_smem(inst, smem, "map dsp");
	if (rc) {
		print_client_buffer(CVP_ERR, "map failed", inst, buf);
		goto exit;
@@ -164,7 +164,7 @@ int msm_cvp_map_buf_dsp(struct msm_cvp_inst *inst, struct cvp_kmd_buffer *buf)

exit:
	if (smem->device_addr)
		msm_cvp_unmap_smem(smem);
		msm_cvp_unmap_smem(inst, smem, "unmap dsp");
	kmem_cache_free(cvp_driver->buf_cache, cbuf);
	cbuf = NULL;
	kmem_cache_free(cvp_driver->smem_cache, smem);
@@ -217,7 +217,7 @@ int msm_cvp_unmap_buf_dsp(struct msm_cvp_inst *inst, struct cvp_kmd_buffer *buf)
	}

	if (cbuf->smem->device_addr)
		msm_cvp_unmap_smem(cbuf->smem);
		msm_cvp_unmap_smem(inst, cbuf->smem, "unmap dsp");

	mutex_lock(&inst->cvpdspbufs.lock);
	list_del(&cbuf->list);
@@ -301,12 +301,13 @@ static int msm_cvp_session_add_smem(struct msm_cvp_inst *inst,
		set_bit(inst->dma_cache.nr, &inst->dma_cache.usage_bitmap);
		smem->bitmap_index = inst->dma_cache.nr;
		inst->dma_cache.nr++;
		i = smem->bitmap_index;
	} else {
		i = find_first_zero_bit(&inst->dma_cache.usage_bitmap,
				MAX_DMABUF_NUMS);
		if (i < MAX_DMABUF_NUMS) {
			smem2 = inst->dma_cache.entries[i];
			msm_cvp_unmap_smem(smem2);
			msm_cvp_unmap_smem(inst, smem2, "unmap cpu");
			msm_cvp_smem_put_dma_buf(smem2->dma_buf);
			kmem_cache_free(cvp_driver->smem_cache, smem2);

@@ -322,6 +323,7 @@ static int msm_cvp_session_add_smem(struct msm_cvp_inst *inst,

	atomic_inc(&smem->refcount);
	mutex_unlock(&inst->dma_cache.lock);
	dprintk(CVP_MEM, "Add entry %d into cache\n", i);

	return 0;
}
@@ -329,7 +331,7 @@ static int msm_cvp_session_add_smem(struct msm_cvp_inst *inst,
static struct msm_cvp_smem *msm_cvp_session_get_smem(struct msm_cvp_inst *inst,
						struct cvp_buf_type *buf)
{
	int rc = 0;
	int rc = 0, found = 1;
	struct msm_cvp_smem *smem = NULL;
	struct dma_buf *dma_buf = NULL;

@@ -346,13 +348,14 @@ static struct msm_cvp_smem *msm_cvp_session_get_smem(struct msm_cvp_inst *inst,

	smem = msm_cvp_session_find_smem(inst, dma_buf);
	if (!smem) {
		found = 0;
		smem = kmem_cache_zalloc(cvp_driver->smem_cache, GFP_KERNEL);
		if (!smem)
			return NULL;

		smem->dma_buf = dma_buf;
		smem->bitmap_index = MAX_DMABUF_NUMS;
		rc = msm_cvp_map_smem(inst, smem);
		rc = msm_cvp_map_smem(inst, smem, "map cpu");
		if (rc)
			goto exit;

@@ -364,13 +367,19 @@ static struct msm_cvp_smem *msm_cvp_session_get_smem(struct msm_cvp_inst *inst,
	if (buf->size > smem->size || buf->size > smem->size - buf->offset) {
		dprintk(CVP_ERR, "%s: invalid offset %d or size %d\n",
			__func__, buf->offset, buf->size);
		if (found) {
			mutex_lock(&inst->dma_cache.lock);
			atomic_dec(&smem->refcount);
			mutex_unlock(&inst->dma_cache.lock);
			return NULL;
		}
		goto exit2;
	}

	return smem;

exit2:
	msm_cvp_unmap_smem(smem);
	msm_cvp_unmap_smem(inst, smem, "unmap cpu");
exit:
	msm_cvp_smem_put_dma_buf(dma_buf);
	kmem_cache_free(cvp_driver->smem_cache, smem);
@@ -477,7 +486,7 @@ static void msm_cvp_unmap_frame_buf(struct msm_cvp_inst *inst,

		if (smem->bitmap_index >= MAX_DMABUF_NUMS) {
			/* smem not in dmamap cache */
			msm_cvp_unmap_smem(smem);
			msm_cvp_unmap_smem(inst, smem, "unmap cpu");
			dma_buf_put(smem->dma_buf);
			kmem_cache_free(cvp_driver->smem_cache, smem);
			buf->smem = NULL;
@@ -527,7 +536,7 @@ int msm_cvp_unmap_user_persist(struct msm_cvp_inst *inst,
	struct cvp_hfi_cmd_session_hdr *cmd_hdr;
	struct cvp_internal_buf *pbuf, *dummy;
	u64 ktid;
	int i, rc = 0;
	int rc = 0;
	struct msm_cvp_smem *smem = NULL;

	if (!offset || !buf_num)
@@ -536,10 +545,8 @@ int msm_cvp_unmap_user_persist(struct msm_cvp_inst *inst,
	cmd_hdr = (struct cvp_hfi_cmd_session_hdr *)in_pkt;
	ktid = cmd_hdr->client_data.kdata & (FENCE_BIT - 1);

	for (i = 0; i < buf_num; i++) {
	mutex_lock(&inst->persistbufs.lock);
		list_for_each_entry_safe(pbuf, dummy, &inst->persistbufs.list,
				list) {
	list_for_each_entry_safe(pbuf, dummy, &inst->persistbufs.list, list) {
		if (pbuf->ktid == ktid && pbuf->ownership == CLIENT) {
			list_del(&pbuf->list);
			smem = pbuf->smem;
@@ -550,7 +557,8 @@ int msm_cvp_unmap_user_persist(struct msm_cvp_inst *inst,

			if (smem->bitmap_index >= MAX_DMABUF_NUMS) {
				/* smem not in dmamap cache */
					msm_cvp_unmap_smem(smem);
				msm_cvp_unmap_smem(inst, smem,
						"unmap cpu");
				dma_buf_put(smem->dma_buf);
				kmem_cache_free(
					cvp_driver->smem_cache,
@@ -563,11 +571,9 @@ int msm_cvp_unmap_user_persist(struct msm_cvp_inst *inst,
			}

			kmem_cache_free(cvp_driver->buf_cache, pbuf);
				break;
		}
	}
	mutex_unlock(&inst->persistbufs.lock);
	}
	return rc;
}

@@ -599,8 +605,10 @@ int msm_cvp_mark_user_persist(struct msm_cvp_inst *inst,
		mutex_lock(&inst->persistbufs.lock);
		list_for_each_entry_safe(pbuf, dummy, &inst->persistbufs.list,
				list) {
			if (pbuf->fd == buf->fd && pbuf->size == buf->size &&
					pbuf->ownership == CLIENT) {
			if (pbuf->ownership == CLIENT) {
				if (pbuf->fd == buf->fd &&
					pbuf->size == buf->size)
					buf->fd = pbuf->smem->device_addr;
				rc = 1;
				break;
			}
@@ -612,7 +620,6 @@ int msm_cvp_mark_user_persist(struct msm_cvp_inst *inst,
			rc = -EFAULT;
			break;
		}
		buf->fd = pbuf->smem->device_addr;
		pbuf->ktid = ktid;
		rc = 0;
	}
@@ -675,6 +682,7 @@ int msm_cvp_map_frame(struct msm_cvp_inst *inst,

	frame->ktid = ktid;
	frame->nr = 0;
	frame->pkt_type = cmd_hdr->packet_type;

	for (i = 0; i < buf_num; i++) {
		buf = (struct cvp_buf_type *)&in_pkt->pkt_data[offset];
@@ -728,7 +736,7 @@ int msm_cvp_session_deinit_buffers(struct msm_cvp_inst *inst)
		} else {
			print_smem(CVP_WARN, "in use", inst, smem);
		}
		msm_cvp_unmap_smem(smem);
		msm_cvp_unmap_smem(inst, smem, "unmap cpu");
		msm_cvp_smem_put_dma_buf(smem->dma_buf);
		kmem_cache_free(cvp_driver->smem_cache, smem);
		inst->dma_cache.entries[i] = NULL;
@@ -748,7 +756,7 @@ int msm_cvp_session_deinit_buffers(struct msm_cvp_inst *inst)
				"%s: failed dsp deregistration fd=%d rc=%d",
				__func__, cbuf->fd, rc);

		msm_cvp_unmap_smem(cbuf->smem);
		msm_cvp_unmap_smem(inst, cbuf->smem, "unmap dsp");
		msm_cvp_smem_put_dma_buf(cbuf->smem->dma_buf);
		list_del(&cbuf->list);
		kmem_cache_free(cvp_driver->buf_cache, cbuf);
+6 −2
Original line number Diff line number Diff line
@@ -132,6 +132,7 @@ struct msm_cvp_frame {
	struct cvp_internal_buf bufs[MAX_FRAME_BUFFER_NUMS];
	u32 nr;
	u64 ktid;
	u32 pkt_type;
};

void print_cvp_buffer(u32 tag, const char *str,
@@ -155,8 +156,11 @@ struct context_bank_info *msm_cvp_smem_get_context_bank(bool is_secure,
				struct msm_cvp_platform_resources *res,
				unsigned long ion_flags);
int msm_cvp_map_smem(struct msm_cvp_inst *inst,
			struct msm_cvp_smem *smem);
int msm_cvp_unmap_smem(struct msm_cvp_smem *smem);
			struct msm_cvp_smem *smem,
			const char *str);
int msm_cvp_unmap_smem(struct msm_cvp_inst *inst,
			struct msm_cvp_smem *smem,
			const char *str);
struct dma_buf *msm_cvp_smem_get_dma_buf(int fd);
void msm_cvp_smem_put_dma_buf(void *dma_buf);
int msm_cvp_smem_cache_operations(struct dma_buf *dbuf,
+55 −0
Original line number Diff line number Diff line
@@ -250,13 +250,68 @@ void *msm_cvp_open(int core_id, int session_type)
}
EXPORT_SYMBOL(msm_cvp_open);

static void msm_cvp_clean_sess_queue(struct msm_cvp_inst *inst,
		struct cvp_session_queue *sq)
{
	struct cvp_session_msg *mptr, *dummy;
	u64 ktid;

	spin_lock(&sq->lock);
	if (sq->msg_count && sq->state != QUEUE_ACTIVE) {
		list_for_each_entry_safe(mptr, dummy, &sq->msgs, node) {
			ktid = mptr->pkt.client_data.kdata;
			if (ktid) {
				list_del_init(&mptr->node);
				sq->msg_count--;
				msm_cvp_unmap_frame(inst, ktid);
				kmem_cache_free(cvp_driver->msg_cache, mptr);
			}
		}
	}
	spin_unlock(&sq->lock);
}

static void msm_cvp_cleanup_instance(struct msm_cvp_inst *inst)
{
	bool empty;
	int max_retries;
	struct msm_cvp_frame *frame;
	struct cvp_session_queue *sq, *sqf;

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

	sqf = &inst->session_queue_fence;
	sq = &inst->session_queue;

	max_retries =  inst->core->resources.msm_cvp_hw_rsp_timeout >> 1;

wait:
	mutex_lock(&inst->frames.lock);
	empty = list_empty(&inst->frames.list);
	if (!empty && max_retries > 0) {
		mutex_unlock(&inst->frames.lock);
		usleep_range(1000, 2000);
		msm_cvp_clean_sess_queue(inst, sqf);
		msm_cvp_clean_sess_queue(inst, sq);
		max_retries--;
		goto wait;
	}
	mutex_unlock(&inst->frames.lock);

	if (!empty) {
		dprintk(CVP_WARN,
			"Failed to process frames before session close\n");
		mutex_lock(&inst->frames.lock);
		list_for_each_entry(frame, &inst->frames.list, list)
			dprintk(CVP_WARN, "Unprocessed frame %d\n",
				frame->pkt_type);
		mutex_unlock(&inst->frames.lock);
		cvp_dump_fence_queue(inst);
	}

	if (cvp_release_arp_buffers(inst))
		dprintk(CVP_ERR,
			"Failed to release persist buffers\n");
+35 −0
Original line number Diff line number Diff line
@@ -9,6 +9,41 @@
#include "msm_cvp_core.h"
#include "msm_cvp_dsp.h"

void cvp_dump_fence_queue(struct msm_cvp_inst *inst)
{
	struct cvp_fence_queue *q;
	struct cvp_fence_command *f;
	struct synx_session ssid;
	int i;

	q = &inst->fence_cmd_queue;
	ssid = inst->synx_session_id;
	mutex_lock(&q->lock);
	dprintk(CVP_WARN, "inst %x fence q mode %d, ssid %d\n",
			hash32_ptr(inst->session), q->mode, ssid.client_id);

	dprintk(CVP_WARN, "fence cmdq wait list:\n");
	list_for_each_entry(f, &q->wait_list, list) {
		dprintk(CVP_WARN, "frame pkt type 0x%x\n", f->pkt->packet_type);
		for (i = 0; i < f->output_index; i++)
			dprintk(CVP_WARN, "idx %d client hdl %d, state %d\n",
				i, f->synx[i],
				synx_get_status(ssid, f->synx[i]));

	}

	dprintk(CVP_WARN, "fence cmdq schedule list:\n");
	list_for_each_entry(f, &q->sched_list, list) {
		dprintk(CVP_WARN, "frame pkt type 0x%x\n", f->pkt->packet_type);
		for (i = 0; i < f->output_index; i++)
			dprintk(CVP_WARN, "idx %d client hdl %d, state %d\n",
				i, f->synx[i],
				synx_get_status(ssid, f->synx[i]));

	}
	mutex_unlock(&q->lock);
}

static int cvp_import_synx_deprecate(struct msm_cvp_inst *inst, u32 type,
		u32 *fence, u32 *synx)
{
Loading