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

Commit 9336b250 authored by Harsh Shah's avatar Harsh Shah Committed by Gerrit - the friendly Code Review server
Browse files

msm: camera: isp: Resolve timing error in request frame



Cfg Ping/Pong should happen before reset framedrop to avoid
invalid buffer writes.

Change-Id: I08ce351b72cec2b558a7db6568b827799b04f79e
Signed-off-by: default avatarHarsh Shah <harshs@codeaurora.org>
parent c0d1ec7b
Loading
Loading
Loading
Loading
+86 −80
Original line number Diff line number Diff line
@@ -472,30 +472,30 @@ void msm_isp_update_framedrop_reg(struct vfe_device *vfe_dev,
				msm_isp_cfg_framedrop_reg(vfe_dev, stream_info);
			}
		}
		if (stream_info->stream_type == BURST_STREAM &&
			(SRC_TO_INTF(stream_info->stream_src) == frame_src)) {
		if (stream_info->stream_type != BURST_STREAM)
			continue;

		if (stream_info->runtime_framedrop_update_burst) {
			stream_info->runtime_framedrop_update_burst = 0;

			stream_info->runtime_burst_frame_count =
				stream_info->runtime_init_frame_drop +
					(stream_info->runtime_num_burst_capture
					- 1) *
				(stream_info->runtime_num_burst_capture - 1) *
				(stream_info->framedrop_period + 1) + 1;
			msm_isp_cfg_framedrop_reg(vfe_dev, stream_info);
		} else {
			if (stream_info->runtime_burst_frame_count > 0)
				stream_info->runtime_burst_frame_count--;

			if ((stream_info->runtime_burst_frame_count <
				BURST_SKIP_THRESHOLD) &&
					(stream_info->runtime_burst_frame_count
					>= 0)) {
				(stream_info->runtime_burst_frame_count >= 0)) {
				msm_isp_cfg_framedrop_reg(vfe_dev,
					stream_info);
			}
		}
	}
}
}

void msm_isp_reset_framedrop(struct vfe_device *vfe_dev,
	struct msm_vfe_axi_stream *stream_info)
@@ -997,22 +997,6 @@ void msm_isp_axi_cfg_update(struct vfe_device *vfe_dev,
			&axi_data->axi_cfg_update[frame_src]);
}

static int msm_isp_cfg_pong_address(struct vfe_device *vfe_dev,
		struct msm_vfe_axi_stream *stream_info)
{
	int i, rc = -1;
	struct msm_isp_buffer *buf = stream_info->buf[0];
	if (!buf)
		return rc;
	for (i = 0; i < stream_info->num_planes; i++)
		vfe_dev->hw_info->vfe_ops.axi_ops.update_ping_pong_addr(
			vfe_dev, stream_info->wm[i],
			VFE_PONG_FLAG, buf->mapped_info[i].paddr +
			stream_info->plane_cfg[i].plane_addr_offset);
	stream_info->buf[1] = buf;
	return 0;
}

static void msm_isp_get_done_buf(struct vfe_device *vfe_dev,
	struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status,
	struct msm_isp_buffer **done_buf)
@@ -1077,7 +1061,8 @@ int msm_isp_print_ping_pong_address(struct vfe_device *vfe_dev)
}

static int msm_isp_cfg_ping_pong_address(struct vfe_device *vfe_dev,
	struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status)
	struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status,
	uint8_t valid_address)
{
	int i, rc = -1;
	struct msm_isp_buffer *buf = NULL;
@@ -1085,6 +1070,7 @@ static int msm_isp_cfg_ping_pong_address(struct vfe_device *vfe_dev,
	struct msm_vfe_frame_request_queue *queue_req;
	uint32_t pingpong_bit;
	uint32_t stream_idx = HANDLE_TO_IDX(stream_info->stream_handle);
	dma_addr_t paddr;

	if (stream_idx >= MAX_NUM_STREAM) {
		pr_err("%s: Invalid stream_idx", __func__);
@@ -1099,24 +1085,26 @@ static int msm_isp_cfg_ping_pong_address(struct vfe_device *vfe_dev,
		if (!queue_req)
			return 0;

		queue_req->cmd_used = 0;
		bufq_handle = stream_info->
			bufq_handle[queue_req->buff_queue_id];
		list_del(&queue_req->list);
		stream_info->request_q_cnt--;

		if (!bufq_handle) {
		if (!bufq_handle || stream_info->request_q_cnt <= 0) {
			pr_err("%s: Drop request. Shared stream is stopped.\n",
				__func__);
			return -EINVAL;
		}
		queue_req->cmd_used = 0;
		list_del(&queue_req->list);
		stream_info->request_q_cnt--;
	}

	if (valid_address == 1) {
		rc = vfe_dev->buf_mgr->ops->get_buf(vfe_dev->buf_mgr,
			vfe_dev->pdev->id, bufq_handle, &buf);

		if (rc < 0) {
		vfe_dev->error_info.stream_framedrop_count[stream_idx]++;
			vfe_dev->error_info.
				stream_framedrop_count[stream_idx]++;
			vfe_dev->error_info.framedrop_flag = 1;
			return rc;
		}
@@ -1126,12 +1114,19 @@ static int msm_isp_cfg_ping_pong_address(struct vfe_device *vfe_dev,
			rc = -EINVAL;
			goto buf_error;
		}
	}

	for (i = 0; i < stream_info->num_planes; i++) {
		if (valid_address == 1)
			paddr = buf->mapped_info[i].paddr +
				stream_info->plane_cfg[i].plane_addr_offset;
		else
			paddr = 0xDEADBEEF;

	for (i = 0; i < stream_info->num_planes; i++)
		vfe_dev->hw_info->vfe_ops.axi_ops.update_ping_pong_addr(
			vfe_dev, stream_info->wm[i],
			pingpong_status, buf->mapped_info[i].paddr +
			stream_info->plane_cfg[i].plane_addr_offset);
			pingpong_status, paddr);
	}

	pingpong_bit = (~(pingpong_status >> stream_info->wm[0]) & 0x1);
	stream_info->buf[pingpong_bit] = buf;
@@ -1475,9 +1470,11 @@ static int msm_isp_init_stream_ping_pong_reg(
	struct msm_vfe_axi_stream *stream_info)
{
	int rc = 0;
	uint8_t valid_address;

	/*Set address for both PING & PONG register */
	rc = msm_isp_cfg_ping_pong_address(vfe_dev,
		stream_info, VFE_PING_FLAG);
		stream_info, VFE_PING_FLAG, 1);
	if (rc < 0) {
		pr_err("%s: No free buffer for ping\n",
			   __func__);
@@ -1490,21 +1487,18 @@ static int msm_isp_init_stream_ping_pong_reg(
	 */
	if (stream_info->stream_type == BURST_STREAM &&
		stream_info->runtime_num_burst_capture <= 1) {
		rc = msm_isp_cfg_pong_address(vfe_dev, stream_info);
		if (rc < 0) {
			pr_err("%s: No free buffer for pong\n",
				   __func__);
			return rc;
		}
	} else {
		valid_address = 0;
	} else
		valid_address = 1;

	rc = msm_isp_cfg_ping_pong_address(vfe_dev,
			stream_info, VFE_PONG_FLAG);
		stream_info, VFE_PONG_FLAG, valid_address);
	if (rc < 0) {
		pr_err("%s: No free buffer for pong\n",
			__func__);
		return rc;
	}
	}

	return rc;
}

@@ -1960,12 +1954,10 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev,
	stream_cfg_cmd.frame_skip_pattern = NO_SKIP;
	stream_cfg_cmd.init_frame_drop = 0;
	stream_cfg_cmd.burst_count = stream_info->request_q_cnt;
	msm_isp_calculate_framedrop(&vfe_dev->axi_data, &stream_cfg_cmd);
	msm_isp_reset_framedrop(vfe_dev, stream_info);

	if (stream_info->undelivered_request_cnt == 1) {
		rc = msm_isp_cfg_ping_pong_address(vfe_dev, stream_info,
			VFE_PING_FLAG);
			VFE_PING_FLAG, 1);
		if (rc) {
			spin_unlock_irqrestore(&stream_info->lock, flags);
			pr_err("%s:%d fail to set ping pong address\n",
@@ -1982,7 +1974,7 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev,
				vfe_dev);

		rc = msm_isp_cfg_ping_pong_address(vfe_dev, stream_info,
			pingpong_status);
			pingpong_status, 1);
		if (rc) {
			spin_unlock_irqrestore(&stream_info->lock, flags);
			pr_err("%s:%d fail to set ping pong address\n",
@@ -1991,6 +1983,9 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev,
		}
	}

	msm_isp_calculate_framedrop(&vfe_dev->axi_data, &stream_cfg_cmd);
	msm_isp_reset_framedrop(vfe_dev, stream_info);

	spin_unlock_irqrestore(&stream_info->lock, flags);

	return rc;
@@ -2210,6 +2205,7 @@ void msm_isp_process_axi_irq(struct vfe_device *vfe_dev,
	struct msm_vfe_axi_composite_info *comp_info;
	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
	unsigned long flags;
	uint8_t valid_address;

	comp_mask = vfe_dev->hw_info->vfe_ops.axi_ops.
		get_comp_mask(irq_status0, irq_status1);
@@ -2245,6 +2241,8 @@ void msm_isp_process_axi_irq(struct vfe_device *vfe_dev,

			ISP_DBG("%s: stream id %x frame id: 0x%x\n", __func__,
				stream_info->stream_id, stream_info->frame_id);

			spin_lock_irqsave(&stream_info->lock, flags);
			stream_info->frame_id++;

			if (stream_info->stream_type == BURST_STREAM) {
@@ -2254,14 +2252,17 @@ void msm_isp_process_axi_irq(struct vfe_device *vfe_dev,
				stream_info->runtime_num_burst_capture--;
			}

			spin_lock_irqsave(&stream_info->lock, flags);
			msm_isp_get_done_buf(vfe_dev, stream_info,
				pingpong_status, &done_buf);
			if (stream_info->stream_type == CONTINUOUS_STREAM ||
				stream_info->runtime_num_burst_capture > 1) {
				valid_address = 1;
			} else
				valid_address = 0;

			rc = msm_isp_cfg_ping_pong_address(vfe_dev,
					stream_info, pingpong_status);
			}
				stream_info, pingpong_status, valid_address);

			spin_unlock_irqrestore(&stream_info->lock, flags);

			if (done_buf && !rc)
@@ -2289,6 +2290,8 @@ void msm_isp_process_axi_irq(struct vfe_device *vfe_dev,

			ISP_DBG("%s: stream id %x frame id: 0x%x\n", __func__,
				stream_info->stream_id, stream_info->frame_id);

			spin_lock_irqsave(&stream_info->lock, flags);
			stream_info->frame_id++;

			if (stream_info->stream_type == BURST_STREAM) {
@@ -2298,14 +2301,17 @@ void msm_isp_process_axi_irq(struct vfe_device *vfe_dev,
				stream_info->runtime_num_burst_capture--;
			}

			spin_lock_irqsave(&stream_info->lock, flags);
			msm_isp_get_done_buf(vfe_dev, stream_info,
						pingpong_status, &done_buf);
			if (stream_info->stream_type == CONTINUOUS_STREAM ||
				stream_info->runtime_num_burst_capture > 1) {
				valid_address = 1;
			} else
				valid_address = 0;

			rc = msm_isp_cfg_ping_pong_address(vfe_dev,
					stream_info, pingpong_status);
			}
				stream_info, pingpong_status, valid_address);

			spin_unlock_irqrestore(&stream_info->lock, flags);

			if (done_buf && !rc)