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

Commit d1d399cc authored by Senthil kumar Rajagopal's avatar Senthil kumar Rajagopal Committed by Senthil Kumar Rajagopal
Browse files

msm: camera: isp: Return error if scheduling is delayed



Hardware writes into ping / pong address in alternate frames.
Software maintains a counter for sof and increments it when
sof irq is received from hardware. If scheduling is delayed,
software book-keeping logic goes wrong because hardware ping /
pong address switches back and forth while software is unable
to track it due to scheduling delay. Add logic for software
ping / pong logic and validate against hardware irq. If there
is mismatch, report error to avoid page fault issues.

Change-Id: I1797cbb3f34c8e4a0dffecbdf92e66674f02d2f1
Signed-off-by: default avatarSenthil Kumar Rajagopal <skrajago@codeaurora.org>
parent 723b2947
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -362,6 +362,7 @@ struct msm_vfe_axi_stream {
	uint32_t runtime_output_format;
	enum msm_stream_memory_input_t  memory_input;
	struct msm_isp_sw_framskip sw_skip;
	uint8_t sw_ping_pong_bit;
};

struct msm_vfe_axi_composite_info {
+36 −1
Original line number Diff line number Diff line
@@ -1090,6 +1090,7 @@ static void msm_isp_get_done_buf(struct vfe_device *vfe_dev,
			(~(pingpong_status >> stream_info->wm[i]) & 0x1)) {
			pr_debug("%s: Write master ping pong mismatch. Status: 0x%x\n",
				__func__, pingpong_status);
			msm_isp_halt_send_error(vfe_dev);
		}
	}

@@ -1102,10 +1103,43 @@ static void msm_isp_get_done_buf(struct vfe_device *vfe_dev,
				__func__, __LINE__);
		} else {
			stream_info->undelivered_request_cnt--;
			if (pingpong_bit != stream_info->sw_ping_pong_bit) {
				pr_err("%s:%d ping pong bit actual %d sw %d\n",
					__func__, __LINE__, pingpong_bit,
					stream_info->sw_ping_pong_bit);

				msm_isp_halt_send_error(vfe_dev);

			}
			stream_info->sw_ping_pong_bit ^= 1;
		}
	}
}


void msm_isp_halt_send_error(struct vfe_device *vfe_dev)
{
	uint32_t i = 0;
	struct msm_isp_event_data error_event;
	struct msm_vfe_axi_halt_cmd halt_cmd;

	memset(&halt_cmd, 0, sizeof(struct msm_vfe_axi_halt_cmd));
	memset(&error_event, 0, sizeof(struct msm_isp_event_data));
	halt_cmd.stop_camif = 1;
	halt_cmd.overflow_detected = 0;
	halt_cmd.blocking_halt = 0;

	msm_isp_axi_halt(vfe_dev, &halt_cmd);

	for (i = 0; i < MAX_NUM_STREAM; i++)
		vfe_dev->axi_data.stream_info[i].state =
			INACTIVE;
	error_event.frame_id =
		vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id;

	msm_isp_send_event(vfe_dev, ISP_EVENT_IOMMU_P_FAULT, &error_event);
}

int msm_isp_print_ping_pong_address(struct vfe_device *vfe_dev)
{
	int i, j;
@@ -2224,6 +2258,7 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev,
		msm_isp_get_stream_wm_mask(stream_info, &wm_reload_mask);
		vfe_dev->hw_info->vfe_ops.axi_ops.reload_wm(vfe_dev,
			wm_reload_mask);
		stream_info->sw_ping_pong_bit = 0;
	} else if (stream_info->undelivered_request_cnt == 2) {
		pingpong_status =
			vfe_dev->hw_info->vfe_ops.axi_ops.get_pingpong_status(
+2 −0
Original line number Diff line number Diff line
@@ -77,4 +77,6 @@ int msm_isp_drop_frame(struct vfe_device *vfe_dev,
	struct msm_vfe_axi_stream *stream_info, struct msm_isp_timestamp *ts,
	struct msm_isp_output_info *output_info);

void msm_isp_halt_send_error(struct vfe_device *vfe_dev);

#endif /* __MSM_ISP_AXI_UTIL_H__ */