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

Commit d65a1eeb authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: cvp: Fix buffer unmap issue"

parents 2ea943da e24c83aa
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -480,10 +480,18 @@ static int hfi_process_session_cvp_msg(u32 device_id,
		if (pkt->packet_type == HFI_MSG_SESSION_CVP_DFS
			|| pkt->packet_type == HFI_MSG_SESSION_CVP_DME
			|| pkt->packet_type == HFI_MSG_SESSION_CVP_ICA
			|| pkt->packet_type == HFI_MSG_SESSION_CVP_FD)
			|| pkt->packet_type == HFI_MSG_SESSION_CVP_FD) {
			u64 ktid;
			u32 kdata1, kdata2;

			kdata1 = pkt->client_data.kdata1;
			kdata2 = pkt->client_data.kdata2;
			ktid = ((u64)kdata2 << 32) | kdata1;
			msm_cvp_unmap_buf_cpu(inst, ktid);

			return _deprecated_hfi_msg_process(device_id,
				pkt, info, inst);

		}
		dprintk(CVP_ERR, "Invalid deprecate_bitmask %#x\n",
					inst->deprecate_bitmask);
	}
+124 −1
Original line number Diff line number Diff line
@@ -369,6 +369,75 @@ static void __msm_cvp_cache_operations(struct msm_cvp_internal_buffer *cbuf)
				cbuf->buf.offset, cbuf->buf.size);
}

static int msm_cvp_map_buf_user_persist(struct msm_cvp_inst *inst,
					struct cvp_buf_type *in_buf,
					u32 *iova)
{
	int rc = 0;
	struct cvp_internal_buf *cbuf;
	struct dma_buf *dma_buf;

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

	if (in_buf->fd > 0) {
		dma_buf = msm_cvp_smem_get_dma_buf(in_buf->fd);
		if (!dma_buf) {
			dprintk(CVP_ERR, "%s: Invalid fd=%d", __func__,
				in_buf->fd);
			return -EINVAL;
		}
		in_buf->dbuf = dma_buf;
		msm_cvp_smem_put_dma_buf(dma_buf);
	}

	rc = msm_cvp_session_get_iova_addr(inst, in_buf, iova);
	if (!rc && *iova != 0)
		return 0;
	cbuf = kzalloc(sizeof(*cbuf), GFP_KERNEL);
	if (!cbuf)
		return -ENOMEM;

	cbuf->smem.buffer_type = in_buf->flags;
	cbuf->smem.fd = in_buf->fd;
	cbuf->smem.size = in_buf->size;
	cbuf->smem.flags = 0;
	cbuf->smem.offset = 0;
	cbuf->smem.dma_buf = in_buf->dbuf;
	cbuf->buffer_ownership = CLIENT;

	rc = msm_cvp_smem_map_dma_buf(inst, &cbuf->smem);
	if (rc) {
		dprintk(CVP_ERR,
		"%s: %x : fd %d %s size %d",
		"map persist failed", hash32_ptr(inst->session), cbuf->smem.fd,
		cbuf->smem.dma_buf->name, cbuf->smem.size);
		goto exit;
	}

	/* Assign mapped dma_buf back because it could be zero previously */
	in_buf->dbuf = cbuf->smem.dma_buf;

	mutex_lock(&inst->persistbufs.lock);
	list_add_tail(&cbuf->list, &inst->persistbufs.list);
	mutex_unlock(&inst->persistbufs.lock);

	*iova = cbuf->smem.device_addr;

	dprintk(CVP_DBG,
	"%s: %x : fd %d %s size %d", "map persist", hash32_ptr(inst->session),
	cbuf->smem.fd, cbuf->smem.dma_buf->name, cbuf->smem.size);
	return rc;

exit:
	kfree(cbuf);
	cbuf = NULL;

	return rc;
}

static int msm_cvp_map_buf_cpu(struct msm_cvp_inst *inst,
				struct cvp_buf_type *in_buf,
				u32 *iova,
@@ -625,6 +694,56 @@ static int msm_cvp_session_receive_hfi(struct msm_cvp_inst *inst,
	return rc;
}

static int msm_cvp_map_user_persist(struct msm_cvp_inst *inst,
	struct cvp_kmd_hfi_packet *in_pkt,
	unsigned int offset, unsigned int buf_num)
{
	struct cvp_buf_desc *buf_ptr;
	struct cvp_buf_type *new_buf;
	int i, rc = 0;
	unsigned int iova;

	if (!offset || !buf_num)
		return 0;

	for (i = 0; i < buf_num; i++) {
		buf_ptr = (struct cvp_buf_desc *)
				&in_pkt->pkt_data[offset];

		offset += sizeof(*new_buf) >> 2;
		new_buf = (struct cvp_buf_type *)buf_ptr;

		/*
		 * Make sure fd or dma_buf field doesn't have any
		 * garbage value.
		 */
		if (inst->session_type == MSM_CVP_USER) {
			new_buf->dbuf = 0;
		} else if (inst->session_type == MSM_CVP_KERNEL) {
			new_buf->fd = -1;
		} else if (inst->session_type >= MSM_CVP_UNKNOWN) {
			dprintk(CVP_ERR,
				"%s: unknown session type %d\n",
				__func__, inst->session_type);
			return -EINVAL;
		}

		if (new_buf->fd <= 0 && !new_buf->dbuf)
			continue;

		rc = msm_cvp_map_buf_user_persist(inst, new_buf, &iova);
		if (rc) {
			dprintk(CVP_ERR,
				"%s: buf %d register failed.\n",
				__func__, i);

			return rc;
		}
		new_buf->fd = iova;
	}
	return rc;
}

static int msm_cvp_map_buf(struct msm_cvp_inst *inst,
	struct cvp_kmd_hfi_packet *in_pkt,
	unsigned int offset, unsigned int buf_num)
@@ -818,7 +937,11 @@ static int msm_cvp_session_process_hfi(
		buf_num = in_buf_num;
	}

	if (in_pkt->pkt_data[1] == HFI_CMD_SESSION_CVP_SET_PERSIST_BUFFERS)
		rc = msm_cvp_map_user_persist(inst, in_pkt, offset, buf_num);
	else
		rc = msm_cvp_map_buf(inst, in_pkt, offset, buf_num);

	if (rc)
		goto exit;

+43 −26
Original line number Diff line number Diff line
@@ -1657,6 +1657,7 @@ static int allocate_and_set_internal_bufs(struct msm_cvp_inst *inst,
	}

	binfo->buffer_type = HFI_BUFFER_INTERNAL_PERSIST_1;
	binfo->buffer_ownership = DRIVER;

	rc = set_internal_buf_on_fw(inst, &binfo->smem, false);
	if (rc)
@@ -1713,6 +1714,7 @@ int cvp_comm_release_persist_buffers(struct msm_cvp_inst *inst)
	int rc = 0;
	struct msm_cvp_core *core;
	struct cvp_hfi_device *hdev;
	int all_released;

	if (!inst) {
		dprintk(CVP_ERR, "Invalid instance pointer = %pK\n", inst);
@@ -1731,6 +1733,8 @@ int cvp_comm_release_persist_buffers(struct msm_cvp_inst *inst)
	}

	dprintk(CVP_DBG, "release persist buffer!\n");
	all_released = 0;

	mutex_lock(&inst->persistbufs.lock);
	list_for_each_safe(ptr, next, &inst->persistbufs.list) {
		buf = list_entry(ptr, struct cvp_internal_buf, list);
@@ -1740,12 +1744,9 @@ int cvp_comm_release_persist_buffers(struct msm_cvp_inst *inst)
			mutex_unlock(&inst->persistbufs.lock);
			return -EINVAL;
		}
		if (inst->state > MSM_CVP_CLOSE_DONE) {
			list_del(&buf->list);
			msm_cvp_smem_free(handle);
			kfree(buf);
			continue;
		}

		/* Workaround for FW: release buffer means release all */
		if (inst->state <= MSM_CVP_CLOSE_DONE && !all_released) {
			buffer_info.buffer_size = handle->size;
			buffer_info.buffer_type = buf->buffer_type;
			buffer_info.num_buffers = 1;
@@ -1768,8 +1769,24 @@ int cvp_comm_release_persist_buffers(struct msm_cvp_inst *inst)
						buffer_info.align_device_addr,
						buffer_info.buffer_size);
			}
			all_released = 1;
		}
		list_del(&buf->list);

		if (buf->buffer_ownership == DRIVER) {
			dprintk(CVP_DBG,
			"%s: %x : fd %d %s size %d",
			"free arp", hash32_ptr(inst->session), buf->smem.fd,
			buf->smem.dma_buf->name, buf->smem.size);
			msm_cvp_smem_free(handle);
		} else if (buf->buffer_ownership == CLIENT) {
			dprintk(CVP_DBG,
			"%s: %x : fd %d %s size %d",
			"unmap persist", hash32_ptr(inst->session),
			buf->smem.fd, buf->smem.dma_buf->name, buf->smem.size);
			msm_cvp_smem_unmap_dma_buf(inst, &buf->smem);
		}

		kfree(buf);
	}
	mutex_unlock(&inst->persistbufs.lock);
+1 −0
Original line number Diff line number Diff line
@@ -45,4 +45,5 @@ int cvp_comm_set_arp_buffers(struct msm_cvp_inst *inst);
int cvp_comm_release_persist_buffers(struct msm_cvp_inst *inst);
void print_client_buffer(u32 tag, const char *str,
		struct msm_cvp_inst *inst, struct cvp_kmd_buffer *cbuf);
void msm_cvp_unmap_buf_cpu(struct msm_cvp_inst *inst, u64 ktid);
#endif