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

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

Merge "msm: vidc: Add partial cache operations support"

parents 6b007898 dd15d3d0
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
@@ -78,6 +78,13 @@ static int msm_dma_get_device_address(struct dma_buf *dbuf, unsigned long align,
		 * Mapping of sg is taken care by map attachment
		 */
		attach->dma_map_attrs = DMA_ATTR_DELAYED_UNMAP;
		/*
		 * We do not need dma_map function to perform cache operations
		 * on the whole buffer size and hence pass skip sync flag.
		 * We do the required cache operations separately for the
		 * required buffer size
		 */
		attach->dma_map_attrs |= DMA_ATTR_SKIP_CPU_SYNC;
		if (res->sys_cache_present)
			attach->dma_map_attrs |=
				DMA_ATTR_IOMMU_USE_UPSTREAM_HINT;
@@ -511,6 +518,44 @@ int msm_smem_free(struct msm_smem *smem)
	return rc;
};

int msm_smem_cache_operations(struct dma_buf *dbuf,
	enum smem_cache_ops cache_op, unsigned long offset, unsigned long size)
{
	int rc = 0;

	if (!dbuf) {
		dprintk(VIDC_ERR, "%s: Invalid params\n", __func__);
		return -EINVAL;
	}

	switch (cache_op) {
	case SMEM_CACHE_CLEAN:
	case SMEM_CACHE_CLEAN_INVALIDATE:
		rc = dma_buf_begin_cpu_access_partial(dbuf, DMA_TO_DEVICE,
				offset, size);
		if (rc)
			break;
		rc = dma_buf_end_cpu_access_partial(dbuf, DMA_TO_DEVICE,
				offset, size);
		break;
	case SMEM_CACHE_INVALIDATE:
		rc = dma_buf_begin_cpu_access_partial(dbuf, DMA_TO_DEVICE,
				offset, size);
		if (rc)
			break;
		rc = dma_buf_end_cpu_access_partial(dbuf, DMA_FROM_DEVICE,
				offset, size);
		break;
	default:
		dprintk(VIDC_ERR, "%s: cache (%d) operation not supported\n",
			__func__, cache_op);
		rc = -EINVAL;
		break;
	}

	return rc;
}

struct context_bank_info *msm_smem_get_context_bank(u32 session_type,
	bool is_secure, struct msm_vidc_platform_resources *res,
	enum hal_buffer buffer_type)
+143 −0
Original line number Diff line number Diff line
@@ -2416,6 +2416,11 @@ static void handle_ebd(enum hal_command_response cmd, void *data)

	update_recon_stats(inst, &empty_buf_done->recon_stats);
	msm_vidc_clear_freq_entry(inst, mbuf->smem[0].device_addr);
	/*
	 * dma cache operations need to be performed before dma_unmap
	 * which is done inside msm_comm_put_vidc_buffer()
	 */
	msm_comm_dqbuf_cache_operations(inst, mbuf);
	/*
	 * put_buffer should be done before vb2_buffer_done else
	 * client might queue the same buffer before it is unmapped
@@ -2601,6 +2606,11 @@ static void handle_fbd(enum hal_command_response cmd, void *data)
	}
	mutex_unlock(&inst->registeredbufs.lock);

	/*
	 * dma cache operations need to be performed before dma_unmap
	 * which is done inside msm_comm_put_vidc_buffer()
	 */
	msm_comm_dqbuf_cache_operations(inst, mbuf);
	/*
	 * put_buffer should be done before vb2_buffer_done else
	 * client might queue the same buffer before it is unmapped
@@ -6103,6 +6113,137 @@ int msm_comm_flush_vidc_buffer(struct msm_vidc_inst *inst,
	return rc;
}

int msm_comm_qbuf_cache_operations(struct msm_vidc_inst *inst,
		struct msm_vidc_buffer *mbuf)
{
	int rc = 0, i;
	struct vb2_buffer *vb;
	bool skip;

	if (!inst || !mbuf) {
		dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
			__func__, inst, mbuf);
		return -EINVAL;
	}
	vb = &mbuf->vvb.vb2_buf;

	for (i = 0; i < vb->num_planes; i++) {
		unsigned long offset, size;
		enum smem_cache_ops cache_op;

		skip = true;
		if (inst->session_type == MSM_VIDC_DECODER) {
			if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
				if (!i) { /* bitstream */
					skip = false;
					offset = vb->planes[i].data_offset;
					size = vb->planes[i].bytesused;
					cache_op = SMEM_CACHE_CLEAN_INVALIDATE;
				}
			} else if (vb->type ==
					V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
				if (!i) { /* yuv */
					skip = false;
					offset = 0;
					size = vb->planes[i].length;
					cache_op = SMEM_CACHE_INVALIDATE;
				}
			}
		} else if (inst->session_type == MSM_VIDC_ENCODER) {
			if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
				if (!i) { /* yuv */
					skip = false;
					offset = vb->planes[i].data_offset;
					size = vb->planes[i].bytesused;
					cache_op = SMEM_CACHE_CLEAN_INVALIDATE;
				}
			} else if (vb->type ==
					V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
				if (!i) { /* bitstream */
					skip = false;
					offset = 0;
					size = vb->planes[i].length;
					cache_op = SMEM_CACHE_INVALIDATE;
				}
			}
		}

		if (!skip) {
			rc = msm_smem_cache_operations(mbuf->smem[i].dma_buf,
					cache_op, offset, size);
			if (rc)
				print_vidc_buffer(VIDC_ERR,
					"qbuf cache ops failed", inst, mbuf);
		}
	}

	return rc;
}

int msm_comm_dqbuf_cache_operations(struct msm_vidc_inst *inst,
		struct msm_vidc_buffer *mbuf)
{
	int rc = 0, i;
	struct vb2_buffer *vb;
	bool skip;

	if (!inst || !mbuf) {
		dprintk(VIDC_ERR, "%s: invalid params %pK %pK\n",
			__func__, inst, mbuf);
		return -EINVAL;
	}
	vb = &mbuf->vvb.vb2_buf;

	for (i = 0; i < vb->num_planes; i++) {
		unsigned long offset, size;
		enum smem_cache_ops cache_op;

		skip = true;
		if (inst->session_type == MSM_VIDC_DECODER) {
			if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
				/* bitstream and extradata */
				/* we do not need cache operations */
			} else if (vb->type ==
					V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
				if (!i) { /* yuv */
					skip = false;
					offset = vb->planes[i].data_offset;
					size = vb->planes[i].bytesused;
					cache_op = SMEM_CACHE_INVALIDATE;
				}
			}
		} else if (inst->session_type == MSM_VIDC_ENCODER) {
			if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
				/* yuv and extradata */
				/* we do not need cache operations */
			} else if (vb->type ==
					V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
				if (!i) { /* bitstream */
					skip = false;
					/*
					 * Include vp8e header bytes as well
					 * by making offset equal to zero
					 */
					offset = 0;
					size = vb->planes[i].bytesused +
						vb->planes[i].data_offset;
					cache_op = SMEM_CACHE_INVALIDATE;
				}
			}
		}

		if (!skip) {
			rc = msm_smem_cache_operations(mbuf->smem[i].dma_buf,
					cache_op, offset, size);
			if (rc)
				print_vidc_buffer(VIDC_ERR,
					"dqbuf cache ops failed", inst, mbuf);
		}
	}

	return rc;
}

struct msm_vidc_buffer *msm_comm_get_vidc_buffer(struct msm_vidc_inst *inst,
		struct vb2_buffer *vb2)
{
@@ -6191,6 +6332,8 @@ struct msm_vidc_buffer *msm_comm_get_vidc_buffer(struct msm_vidc_inst *inst,
			goto exit;
		}
	}
	/* dma cache operations need to be performed after dma_map */
	msm_comm_qbuf_cache_operations(inst, mbuf);

	/* special handling for decoder */
	if (inst->session_type == MSM_VIDC_DECODER) {
+2 −2
Original line number Diff line number Diff line
@@ -204,9 +204,9 @@ bool msm_comm_compare_device_plane(struct msm_vidc_buffer *mbuf,
bool msm_comm_compare_device_planes(struct msm_vidc_buffer *mbuf,
		u32 *planes);
int msm_comm_qbuf_cache_operations(struct msm_vidc_inst *inst,
		struct v4l2_buffer *b);
		struct msm_vidc_buffer *mbuf);
int msm_comm_dqbuf_cache_operations(struct msm_vidc_inst *inst,
			struct v4l2_buffer *b);
		struct msm_vidc_buffer *mbuf);
void print_vidc_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst,
		struct msm_vidc_buffer *mbuf);
void print_vb2_buffer(u32 tag, const char *str, struct msm_vidc_inst *inst,
+2 −0
Original line number Diff line number Diff line
@@ -514,6 +514,8 @@ int msm_smem_map_dma_buf(struct msm_vidc_inst *inst, struct msm_smem *smem);
int msm_smem_unmap_dma_buf(struct msm_vidc_inst *inst, struct msm_smem *smem);
struct dma_buf *msm_smem_get_dma_buf(int fd);
void msm_smem_put_dma_buf(void *dma_buf);
int msm_smem_cache_operations(struct dma_buf *dbuf,
	enum smem_cache_ops cache_op, unsigned long offset, unsigned long size);
void msm_vidc_fw_unload_handler(struct work_struct *work);
void msm_vidc_ssr_handler(struct work_struct *work);
/*
+11 −0
Original line number Diff line number Diff line
@@ -981,6 +981,17 @@ static int msm_vidc_setup_context_bank(struct msm_vidc_platform_resources *res,
		goto release_mapping;
	}

	/*
	 * configure device segment size and segment boundary to ensure
	 * iommu mapping returns one mapping (which is required for partial
	 * cache operations)
	 */
	if (!dev->dma_parms)
		dev->dma_parms =
			devm_kzalloc(dev, sizeof(*dev->dma_parms), GFP_KERNEL);
	dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
	dma_set_seg_boundary(dev, DMA_BIT_MASK(64));

	dprintk(VIDC_DBG, "Attached %s and created mapping\n", dev_name(dev));
	dprintk(VIDC_DBG,
		"Context bank name:%s, buffer_type: %#x, is_secure: %d, address range start: %#x, size: %#x, dev: %pK, mapping: %pK",