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

Commit fc6278f0 authored by Jing Zhou's avatar Jing Zhou
Browse files

msm: camera: isp: Debug double add state check



Add changes to track buffer being added to list. Add error
messages if buffer is found to be added twice. Add state checking
in the isp driver.

Change-Id: I1504e8984db3578009b8944719bbd559ad57d63d
Signed-off-by: default avatarHarsh Shah <harshs@codeaurora.org>
Signed-off-by: default avatarJing Zhou <jzhou70@codeaurora.org>
parent 7427cd00
Loading
Loading
Loading
Loading
+259 −119
Original line number Diff line number Diff line
@@ -39,6 +39,70 @@
#define BUF_DEBUG_FULL 0
#define MAX_LIST_COUNT 100

static int msm_buf_check_head_sanity(struct msm_isp_bufq *bufq)
{
	int rc = 0;
	struct list_head *prev = NULL;
	struct list_head *next = NULL;

	if (!bufq) {
		pr_err("%s: Error! Invalid bufq\n", __func__);
		return -EINVAL;
	}

	prev = bufq->head.prev;
	next = bufq->head.next;

	if (!prev) {
		pr_err("%s: Error! bufq->head.prev is NULL\n", __func__);
		return -EINVAL;
	}

	if (!next) {
		pr_err("%s: Error! bufq->head.next is NULL\n", __func__);
		return -EINVAL;
	}

	if (prev->next != &bufq->head) {
		pr_err("%s: Error! head prev->next is %p should be %p\n",
			__func__, prev->next, &bufq->head);
		return -EINVAL;
	}

	if (next->prev != &bufq->head) {
		pr_err("%s: Error! head next->prev is %p should be %p\n",
			__func__, next->prev, &bufq->head);
		return -EINVAL;
	}

	prev = bufq->share_head.prev;
	next = bufq->share_head.next;

	if (!prev) {
		pr_err("%s: Error! bufq->share_head.prev is NULL\n", __func__);
		return -EINVAL;
	}

	if (!next) {
		pr_err("%s: Error! bufq->share_head.next is NULL\n", __func__);
		return -EINVAL;
	}

	if (prev->next != &bufq->share_head) {
		pr_err("%s: Error! share_head prev->next is %p should be %p\n",
			__func__, prev->next, &bufq->share_head);
		return -EINVAL;
	}

	if (next->prev != &bufq->share_head) {
		pr_err("%s: Error! share_head next->prev is %p should be %p\n",
			__func__, next->prev, &bufq->share_head);
		return -EINVAL;
	}

	return rc;
}

struct msm_isp_bufq *msm_isp_get_bufq(
	struct msm_isp_buf_mgr *buf_mgr,
	uint32_t bufq_handle)
@@ -425,6 +489,20 @@ static int msm_isp_buf_unprepare(struct msm_isp_buf_mgr *buf_mgr,
	return 0;
}

static void msm_isp_debug_list(struct msm_isp_bufq *bufq,
	struct msm_isp_buffer *buf_info)
{
	int i = 0;

	pr_err("%s: stream_id %x buf_info last_put_id = %d\n", __func__,
		bufq->stream_id,
		buf_info->buf_debug.put_state_last);
	for (i = 0; i < 2; i++) {
		pr_err("%s i %d put_state %d\n", __func__, i,
			buf_info->buf_debug.put_state[i]);
	}
}

static int msm_isp_get_buf(struct msm_isp_buf_mgr *buf_mgr, uint32_t id,
	uint32_t bufq_handle, struct msm_isp_buffer **buf_info,
	uint32_t *buf_cnt)
@@ -432,7 +510,7 @@ static int msm_isp_get_buf(struct msm_isp_buf_mgr *buf_mgr, uint32_t id,
	int rc = -1;
	unsigned long flags;
	unsigned int list_count = 0;
	struct msm_isp_buffer *temp_buf_info;
	struct msm_isp_buffer *temp_buf_info = NULL;
	struct msm_isp_bufq *bufq = NULL;
	struct vb2_buffer *vb2_buf = NULL;

@@ -458,6 +536,12 @@ static int msm_isp_get_buf(struct msm_isp_buf_mgr *buf_mgr, uint32_t id,
	*buf_info = NULL;
	*buf_cnt = 0;
	if (bufq->buf_type == ISP_SHARE_BUF) {
		if (msm_buf_check_head_sanity(bufq) < 0) {
			spin_unlock_irqrestore(&bufq->bufq_lock, flags);
			WARN(1, "%s buf_handle 0x%x is in bad state\n",
				__func__, bufq->bufq_handle);
				return -EFAULT;
		}
		list_count = 0;
		list_for_each_entry(temp_buf_info,
			&bufq->share_head, share_list) {
@@ -466,9 +550,11 @@ static int msm_isp_get_buf(struct msm_isp_buf_mgr *buf_mgr, uint32_t id,
				temp_buf_info->buf_get_count++;
				*buf_cnt = temp_buf_info->buf_get_count;
				if (temp_buf_info->buf_get_count ==
					bufq->buf_client_count)
					list_del(
					bufq->buf_client_count) {
					list_del_init(
					&temp_buf_info->share_list);
				}

				if (temp_buf_info->buf_reuse_flag) {
					kfree(temp_buf_info);
				} else {
@@ -500,7 +586,17 @@ static int msm_isp_get_buf(struct msm_isp_buf_mgr *buf_mgr, uint32_t id,
		list_for_each_entry(temp_buf_info, &bufq->head, list) {
			if (temp_buf_info->state ==
					MSM_ISP_BUFFER_STATE_QUEUED) {
				list_del(&temp_buf_info->list);
				list_del_init(&temp_buf_info->list);
				if (msm_buf_check_head_sanity(bufq) < 0) {
					spin_unlock_irqrestore(
						&bufq->bufq_lock, flags);
					WARN(1, "%s buf_handle 0x%x buf_idx %d buf_reuse_flag %d\n",
						__func__,
						bufq->bufq_handle,
						temp_buf_info->buf_idx,
						temp_buf_info->buf_reuse_flag);
					return -EFAULT;
				}
				*buf_info = temp_buf_info;
				break;
			}
@@ -556,20 +652,59 @@ static int msm_isp_get_buf(struct msm_isp_buf_mgr *buf_mgr, uint32_t id,
				temp_buf_info->buf_get_count = 1;
				list_add_tail(&temp_buf_info->share_list,
					&bufq->share_head);
				if (msm_buf_check_head_sanity(bufq) < 0) {
					spin_unlock_irqrestore(
						&bufq->bufq_lock, flags);
					WARN(1, "%s buf_handle 0x%x buf_idx %d buf_reuse_flag %d\n",
						__func__,
						bufq->bufq_handle,
						temp_buf_info->buf_idx,
						temp_buf_info->buf_reuse_flag);
					return -EFAULT;
				}
			} else
				rc = -ENOMEM;
		}
	} else {
		(*buf_info)->state = MSM_ISP_BUFFER_STATE_DEQUEUED;
		if (bufq->buf_type == ISP_SHARE_BUF) {
			list_for_each_entry(temp_buf_info,
				&bufq->share_head, share_list) {
				if (temp_buf_info->buf_idx ==
					(*buf_info)->buf_idx) {
					msm_isp_debug_list(bufq, temp_buf_info);
					spin_unlock_irqrestore(
					&bufq->bufq_lock, flags);
					WARN(1, "%s ERROR! Double ADD found\n",
						__func__);
					return -EFAULT;
				}
			}
			memset((*buf_info)->buf_used, 0,
				   sizeof(uint8_t) * bufq->buf_client_count);
			(*buf_info)->buf_used[id] = 1;
			(*buf_info)->buf_get_count = 1;
			(*buf_info)->buf_put_count = 0;
			(*buf_info)->buf_reuse_flag = 0;
			if (!list_empty(&(*buf_info)->share_list)) {
				spin_unlock_irqrestore(&bufq->bufq_lock, flags);
				WARN(1, "%s: buf %x/%x double add\n",
					__func__, bufq_handle,
					(*buf_info)->buf_idx);
				return -EFAULT;

			}
			list_add_tail(&(*buf_info)->share_list,
						  &bufq->share_head);
			if (msm_buf_check_head_sanity(bufq) < 0) {
				spin_unlock_irqrestore(&bufq->bufq_lock, flags);
				WARN(1, "%s buf_handle 0x%x buf_idx %d buf_reuse_flag %d\n",
					__func__,
					bufq->bufq_handle,
					(*buf_info)->buf_idx,
					(*buf_info)->buf_reuse_flag);
				return -EFAULT;
			}
		}
		rc = 0;
	}
@@ -577,11 +712,10 @@ static int msm_isp_get_buf(struct msm_isp_buf_mgr *buf_mgr, uint32_t id,
	return rc;
}

static int msm_isp_put_buf(struct msm_isp_buf_mgr *buf_mgr,
static int msm_isp_put_buf_unsafe(struct msm_isp_buf_mgr *buf_mgr,
	uint32_t bufq_handle, uint32_t buf_index)
{
	int rc = -1;
	unsigned long flags;
	struct msm_isp_bufq *bufq = NULL;
	struct msm_isp_buffer *buf_info = NULL;

@@ -597,23 +731,27 @@ static int msm_isp_put_buf(struct msm_isp_buf_mgr *buf_mgr,
		return rc;
	}

	spin_lock_irqsave(&bufq->bufq_lock, flags);

	buf_info->buf_get_count = 0;
	buf_info->buf_put_count = 0;
	memset(buf_info->buf_used, 0, sizeof(buf_info->buf_used));

	switch (buf_info->state) {
	case MSM_ISP_BUFFER_STATE_PREPARED:
		if (MSM_ISP_BUFFER_SRC_SCRATCH == BUF_SRC(bufq->stream_id))
			list_add_tail(&buf_info->list, &bufq->head);
	case MSM_ISP_BUFFER_STATE_DEQUEUED:
	case MSM_ISP_BUFFER_STATE_DIVERTED:
		if (MSM_ISP_BUFFER_SRC_NATIVE == BUF_SRC(bufq->stream_id))
		if (BUF_SRC(bufq->stream_id)) {
			if (!list_empty(&buf_info->list)) {
				WARN(1, "%s: buf %x/%x double add\n",
					__func__, bufq_handle, buf_index);
				return -EFAULT;
			}
			list_add_tail(&buf_info->list, &bufq->head);
		else if (MSM_ISP_BUFFER_SRC_HAL == BUF_SRC(bufq->stream_id))
			if (msm_buf_check_head_sanity(bufq) < 0) {
				WARN(1, "%s buf_handle 0x%x buf_idx %d buf_reuse_flag %d\n",
					__func__,
					bufq->bufq_handle,
					buf_info->buf_idx,
					buf_info->buf_reuse_flag);
				return -EFAULT;
			}
		} else {
			buf_mgr->vb2_ops->put_buf(buf_info->vb2_buf,
				bufq->session_id, bufq->stream_id);
		}
		buf_info->state = MSM_ISP_BUFFER_STATE_QUEUED;
		rc = 0;
		break;
@@ -622,22 +760,22 @@ static int msm_isp_put_buf(struct msm_isp_buf_mgr *buf_mgr,
		rc = 0;
		break;
	case MSM_ISP_BUFFER_STATE_QUEUED:
		rc = 0;
		break;
	case MSM_ISP_BUFFER_STATE_DEQUEUED:
	case MSM_ISP_BUFFER_STATE_DIVERTED:
	default:
		pr_err("%s: incorrect state = %d",
			__func__, buf_info->state);
		break;
		WARN(1, "%s: bufq 0x%x, buf idx 0x%x, incorrect state = %d",
			__func__, bufq_handle, buf_index, buf_info->state);
		return -EFAULT;
	}
	spin_unlock_irqrestore(&bufq->bufq_lock, flags);

	return rc;
}

static int msm_isp_put_buf_unsafe(struct msm_isp_buf_mgr *buf_mgr,
static int msm_isp_put_buf(struct msm_isp_buf_mgr *buf_mgr,
	uint32_t bufq_handle, uint32_t buf_index)
{
	int rc = -1;
	unsigned long flags;
	struct msm_isp_bufq *bufq = NULL;
	struct msm_isp_buffer *buf_info = NULL;

@@ -653,36 +791,22 @@ static int msm_isp_put_buf_unsafe(struct msm_isp_buf_mgr *buf_mgr,
		return rc;
	}

	switch (buf_info->state) {
	case MSM_ISP_BUFFER_STATE_PREPARED:
	case MSM_ISP_BUFFER_STATE_DEQUEUED:
	case MSM_ISP_BUFFER_STATE_DIVERTED:
		if (BUF_SRC(bufq->stream_id))
			list_add_tail(&buf_info->list, &bufq->head);
		else
			buf_mgr->vb2_ops->put_buf(buf_info->vb2_buf,
				bufq->session_id, bufq->stream_id);
		buf_info->state = MSM_ISP_BUFFER_STATE_QUEUED;
		rc = 0;
		break;
	case MSM_ISP_BUFFER_STATE_DISPATCHED:
		buf_info->state = MSM_ISP_BUFFER_STATE_QUEUED;
		rc = 0;
		break;
	case MSM_ISP_BUFFER_STATE_QUEUED:
		rc = 0;
		break;
	default:
		pr_err("%s: incorrect state = %d",
			__func__, buf_info->state);
		break;
	}
	spin_lock_irqsave(&bufq->bufq_lock, flags);

	buf_info->buf_get_count = 0;
	buf_info->buf_put_count = 0;
	memset(buf_info->buf_used, 0, sizeof(buf_info->buf_used));

	rc = msm_isp_put_buf_unsafe(buf_mgr, bufq_handle, buf_index);

	spin_unlock_irqrestore(&bufq->bufq_lock, flags);

	return rc;
}

static int msm_isp_update_put_buf_cnt(struct msm_isp_buf_mgr *buf_mgr,
	uint32_t bufq_handle, uint32_t buf_index, uint32_t frame_id)
	uint32_t bufq_handle, uint32_t buf_index, struct timeval *tv,
	uint32_t frame_id)
{
	int rc = -1;
	struct msm_isp_bufq *bufq = NULL;
@@ -709,8 +833,7 @@ static int msm_isp_update_put_buf_cnt(struct msm_isp_buf_mgr *buf_mgr,
	}

	state = buf_info->state;
	if (state == MSM_ISP_BUFFER_STATE_DEQUEUED ||
		state == MSM_ISP_BUFFER_STATE_DIVERTED) {
	if (state == MSM_ISP_BUFFER_STATE_DEQUEUED) {
		if (bufq->buf_type == ISP_SHARE_BUF) {
			buf_info->buf_put_count++;
			if (buf_info->buf_put_count != ISP_SHARE_BUF_CLIENT) {
@@ -722,6 +845,14 @@ static int msm_isp_update_put_buf_cnt(struct msm_isp_buf_mgr *buf_mgr,
	} else {
		pr_warn("%s: Invalid state, stream id %x, state %d\n", __func__,
			bufq->stream_id, state);
		spin_unlock_irqrestore(&bufq->bufq_lock, flags);
		dump_stack();
		return rc;
	}

	if (MSM_ISP_BUFFER_SRC_NATIVE == BUF_SRC(bufq->stream_id)) {
		buf_info->state = MSM_ISP_BUFFER_STATE_DIVERTED;
		buf_info->tv = tv;
	}
	spin_unlock_irqrestore(&bufq->bufq_lock, flags);
	return 0;
@@ -751,32 +882,37 @@ static int msm_isp_buf_done(struct msm_isp_buf_mgr *buf_mgr,

	spin_lock_irqsave(&bufq->bufq_lock, flags);
	state = buf_info->state;
	spin_unlock_irqrestore(&bufq->bufq_lock, flags);

	if (state == MSM_ISP_BUFFER_STATE_DEQUEUED ||
		state == MSM_ISP_BUFFER_STATE_DIVERTED) {
		spin_lock_irqsave(&bufq->bufq_lock, flags);
	if (MSM_ISP_BUFFER_SRC_HAL == BUF_SRC(bufq->stream_id)) {
		if (state == MSM_ISP_BUFFER_STATE_DEQUEUED) {
			buf_info->state = MSM_ISP_BUFFER_STATE_DISPATCHED;
			spin_unlock_irqrestore(&bufq->bufq_lock, flags);
		if (MSM_ISP_BUFFER_SRC_HAL == BUF_SRC(bufq->stream_id)) {
			buf_info->vb2_buf->v4l2_buf.timestamp = *tv;
			buf_info->vb2_buf->v4l2_buf.sequence  = frame_id;
			buf_info->vb2_buf->v4l2_buf.reserved  = output_format;
			buf_mgr->vb2_ops->buf_done(buf_info->vb2_buf,
				bufq->session_id, bufq->stream_id);
		} else {
			pr_err("%s: Error wrong buf done %d\n", __func__,
				state);
			rc = msm_isp_put_buf(buf_mgr, buf_info->bufq_handle,
						buf_info->buf_idx);
			if (rc < 0) {
				pr_err("%s: Buf put failed\n", __func__);
				return rc;
			}
			spin_unlock_irqrestore(&bufq->bufq_lock, flags);
		}
		goto done;
	}

	return 0;
	/*
	 * For native buffer put the diverted buffer back to queue since caller
	 * is not going to send it to CPP, this is error case like
	 * drop_frame/empty_buffer
	 */
	if (state == MSM_ISP_BUFFER_STATE_DIVERTED) {
		buf_info->state = MSM_ISP_BUFFER_STATE_PREPARED;
		rc = msm_isp_put_buf_unsafe(buf_mgr, buf_info->bufq_handle,
			buf_info->buf_idx);
		if (rc < 0)
			pr_err("%s: Buf put failed\n", __func__);
	}
	spin_unlock_irqrestore(&bufq->bufq_lock, flags);
done:
	return rc;
}

static int msm_isp_flush_buf(struct msm_isp_buf_mgr *buf_mgr,
@@ -802,15 +938,27 @@ static int msm_isp_flush_buf(struct msm_isp_buf_mgr *buf_mgr,
		}
		if (flush_type == MSM_ISP_BUFFER_FLUSH_DIVERTED &&
			buf_info->state == MSM_ISP_BUFFER_STATE_DIVERTED) {
			buf_info->state = MSM_ISP_BUFFER_STATE_QUEUED;
			buf_info->state = MSM_ISP_BUFFER_STATE_PREPARED;
			msm_isp_put_buf_unsafe(buf_mgr,
					bufq_handle, buf_info->buf_idx);
		} else if (flush_type == MSM_ISP_BUFFER_FLUSH_ALL) {
			if (buf_info->state == MSM_ISP_BUFFER_STATE_DIVERTED) {
				CDBG("%s: no need to queue Diverted buffer\n",
					__func__);
			} else if (buf_info->state ==
				MSM_ISP_BUFFER_STATE_DEQUEUED) {
				msm_isp_put_buf_unsafe(buf_mgr,
				buf_info->buf_debug.put_state[
					buf_info->buf_debug.put_state_last]
					= MSM_ISP_BUFFER_STATE_FLUSH;
				buf_info->buf_debug.put_state_last ^= 1;
				buf_info->state = MSM_ISP_BUFFER_STATE_PREPARED;
				rc = msm_isp_put_buf_unsafe(buf_mgr,
					bufq_handle, buf_info->buf_idx);
				if (rc == -EFAULT) {
					spin_unlock_irqrestore(&bufq->bufq_lock,
						flags);
					return rc;
				}
			}
		}
	}
@@ -819,55 +967,20 @@ static int msm_isp_flush_buf(struct msm_isp_buf_mgr *buf_mgr,
		while (!list_empty(&bufq->share_head)) {
			buf_info = list_entry((&bufq->share_head)->next,
				typeof(*buf_info), share_list);
			list_del(&(buf_info->share_list));
			if (buf_info->buf_reuse_flag)
				kfree(buf_info);
		 }
	}
			list_del_init(&(buf_info->share_list));
			if (msm_buf_check_head_sanity(bufq) < 0) {
				spin_unlock_irqrestore(&bufq->bufq_lock, flags);
	return 0;
}

static int msm_isp_buf_divert(struct msm_isp_buf_mgr *buf_mgr,
	uint32_t bufq_handle, uint32_t buf_index,
	struct timeval *tv, uint32_t frame_id)
{
	int rc = -1;
	struct msm_isp_bufq *bufq = NULL;
	struct msm_isp_buffer *buf_info = NULL;
	unsigned long flags;

	bufq = msm_isp_get_bufq(buf_mgr, bufq_handle);
	if (!bufq) {
		pr_err("Invalid bufq\n");
		return rc;
				WARN(1, "%s buf_handle 0x%x buf_idx %d buf_reuse_flag %d\n",
					__func__,
					bufq->bufq_handle,
					buf_info->buf_idx,
					buf_info->buf_reuse_flag);
				return -EFAULT;
			}

	buf_info = msm_isp_get_buf_ptr(buf_mgr, bufq_handle, buf_index);
	if (!buf_info) {
		pr_err("%s: buf not found\n", __func__);
		return rc;
	}

	spin_lock_irqsave(&bufq->bufq_lock, flags);
	if (bufq->buf_type != ISP_SHARE_BUF ||
		buf_info->buf_put_count == 0) {
		buf_info->frame_id = frame_id;
	}

	if (bufq->buf_type == ISP_SHARE_BUF) {
		buf_info->buf_put_count++;
		if (buf_info->buf_put_count != ISP_SHARE_BUF_CLIENT) {
			rc = buf_info->buf_put_count;
			spin_unlock_irqrestore(&bufq->bufq_lock, flags);
			return rc;
			if (buf_info->buf_reuse_flag)
				kfree(buf_info);
		 }
	}

	if (buf_info->state == MSM_ISP_BUFFER_STATE_DEQUEUED) {
		buf_info->state = MSM_ISP_BUFFER_STATE_DIVERTED;
		buf_info->tv = tv;
	}
	spin_unlock_irqrestore(&bufq->bufq_lock, flags);
	return 0;
}
@@ -901,19 +1014,40 @@ static int msm_isp_buf_enqueue(struct msm_isp_buf_mgr *buf_mgr,
			return rc;
		}
		if (info->dirty_buf) {
			buf_info->buf_debug.put_state[
				buf_info->buf_debug.put_state_last]
				= MSM_ISP_BUFFER_STATE_PUT_BUF;
			buf_info->buf_debug.put_state_last ^= 1;
			buf_info->state = MSM_ISP_BUFFER_STATE_PREPARED;
			rc = msm_isp_put_buf(buf_mgr,
				info->handle, info->buf_idx);
		} else {
			if (BUF_SRC(bufq->stream_id))
				pr_err("%s: Invalid native buffer state\n",
					__func__);
			else
			else {
				buf_info->buf_debug.put_state[
					buf_info->buf_debug.put_state_last] =
					MSM_ISP_BUFFER_STATE_PUT_BUF;
				buf_info->buf_debug.put_state_last ^= 1;
				rc = msm_isp_buf_done(buf_mgr,
					info->handle, info->buf_idx,
					buf_info->tv, buf_info->frame_id, 0);
			}
		}
	} else {
		if (MSM_ISP_BUFFER_SRC_HAL != BUF_SRC(bufq->stream_id)) {
			buf_info = msm_isp_get_buf_ptr(buf_mgr,
				info->handle, info->buf_idx);
			if (!buf_info) {
				pr_err("%s: buf not found\n", __func__);
				return rc;
			}

			buf_info->buf_debug.put_state[
				buf_info->buf_debug.put_state_last] =
				MSM_ISP_BUFFER_STATE_PUT_PREPARED;
			buf_info->buf_debug.put_state_last ^= 1;
			rc = msm_isp_put_buf(buf_mgr,
					info->handle, info->buf_idx);
			if (rc < 0) {
@@ -1027,8 +1161,15 @@ static int msm_isp_request_bufq(struct msm_isp_buf_mgr *buf_mgr,
	INIT_LIST_HEAD(&bufq->share_head);
	for (i = 0; i < buf_request->num_buf; i++) {
		bufq->bufs[i].state = MSM_ISP_BUFFER_STATE_INITIALIZED;
		bufq->bufs[i].buf_debug.put_state[0] =
			MSM_ISP_BUFFER_STATE_PUT_PREPARED;
		bufq->bufs[i].buf_debug.put_state[1] =
			MSM_ISP_BUFFER_STATE_PUT_PREPARED;
		bufq->bufs[i].buf_debug.put_state_last = 0;
		bufq->bufs[i].bufq_handle = bufq->bufq_handle;
		bufq->bufs[i].buf_idx = i;
		INIT_LIST_HEAD(&bufq->bufs[i].list);
		INIT_LIST_HEAD(&bufq->bufs[i].share_list);
	}

	return 0;
@@ -1431,7 +1572,6 @@ static struct msm_isp_buf_ops isp_buf_ops = {
	.put_buf = msm_isp_put_buf,
	.flush_buf = msm_isp_flush_buf,
	.buf_done = msm_isp_buf_done,
	.buf_divert = msm_isp_buf_divert,
	.buf_mgr_init = msm_isp_init_isp_buf_mgr,
	.buf_mgr_deinit = msm_isp_deinit_isp_buf_mgr,
	.buf_mgr_debug = msm_isp_buf_mgr_debug,
+17 −3
Original line number Diff line number Diff line
@@ -46,6 +46,15 @@ enum msm_isp_buffer_state {
	MSM_ISP_BUFFER_STATE_DISPATCHED,     /* Sent to HAL*/
};

enum msm_isp_buffer_put_state {
	MSM_ISP_BUFFER_STATE_PUT_PREPARED,  /* on init */
	MSM_ISP_BUFFER_STATE_PUT_BUF,       /* on rotation */
	MSM_ISP_BUFFER_STATE_FLUSH,         /* on recovery */
	MSM_ISP_BUFFER_STATE_DROP_REG,      /* on drop frame for reg_update */
	MSM_ISP_BUFFER_STATE_DROP_SKIP,      /* on drop frame for sw skip */
	MSM_ISP_BUFFER_STATE_RETURN_EMPTY,  /* for return empty */
};

enum msm_isp_buffer_flush_t {
	MSM_ISP_BUFFER_FLUSH_DIVERTED,
	MSM_ISP_BUFFER_FLUSH_ALL,
@@ -67,6 +76,11 @@ struct buffer_cmd {
	struct msm_isp_buffer_mapped_info *mapped_info;
};

struct msm_isp_buffer_debug_t {
	enum msm_isp_buffer_put_state put_state[2];
	uint8_t put_state_last;
};

struct msm_isp_buffer {
	/*Common Data structure*/
	int num_planes;
@@ -80,6 +94,8 @@ struct msm_isp_buffer {
	struct list_head list;
	enum msm_isp_buffer_state state;

	struct msm_isp_buffer_debug_t buf_debug;

	/*Vb2 buffer data*/
	struct vb2_buffer *vb2_buf;

@@ -148,9 +164,6 @@ struct msm_isp_buf_ops {
	int (*buf_done)(struct msm_isp_buf_mgr *buf_mgr,
		uint32_t bufq_handle, uint32_t buf_index,
		struct timeval *tv, uint32_t frame_id, uint32_t output_format);
	int (*buf_divert)(struct msm_isp_buf_mgr *buf_mgr,
		uint32_t bufq_handle, uint32_t buf_index,
		struct timeval *tv, uint32_t frame_id);
	void (*register_ctx)(struct msm_isp_buf_mgr *buf_mgr,
		struct device **iommu_ctx1, struct device **iommu_ctx2,
		int num_iommu_ctx1, int num_iommu_ctx2);
@@ -163,6 +176,7 @@ struct msm_isp_buf_ops {
		uint32_t bufq_handle);
	int (*update_put_buf_cnt)(struct msm_isp_buf_mgr *buf_mgr,
		uint32_t bufq_handle, uint32_t buf_index,
		struct timeval *tv,
		uint32_t frame_id);
};

+84 −34
Original line number Diff line number Diff line
@@ -1547,7 +1547,11 @@ static int msm_isp_cfg_ping_pong_address(struct vfe_device *vfe_dev,
	rc = vfe_dev->buf_mgr->ops->get_buf(vfe_dev->buf_mgr,
		vfe_dev->pdev->id, bufq_handle, &buf, &buf_cnt);

	if (rc < 0) {
	if (rc == -EFAULT) {
		msm_isp_halt_send_error(vfe_dev, ISP_EVENT_BUF_FATAL_ERROR);
		return rc;
	}
	if (rc < 0 || buf == NULL) {
		ISP_DBG("%s vfe %d get_buf fail bufq %x\n", __func__,
			vfe_dev->pdev->id, bufq_handle);
		vfe_dev->error_info.
@@ -1660,8 +1664,6 @@ static int msm_isp_cfg_ping_pong_address(struct vfe_device *vfe_dev,

	return 0;
buf_error:
	vfe_dev->buf_mgr->ops->put_buf(vfe_dev->buf_mgr,
		buf->bufq_handle, buf->buf_idx);
	return rc;
}

@@ -1732,15 +1734,8 @@ static void msm_isp_process_done_buf(struct vfe_device *vfe_dev,
		return;
	}

	if (stream_info->buf_divert && rc == 0 &&
			buf_src != MSM_ISP_BUFFER_SRC_SCRATCH) {
		rc = vfe_dev->buf_mgr->ops->buf_divert(vfe_dev->buf_mgr,
			buf->bufq_handle, buf->buf_idx,
			time_stamp, frame_id);
	} else {
	rc = vfe_dev->buf_mgr->ops->update_put_buf_cnt(vfe_dev->buf_mgr,
			buf->bufq_handle, buf->buf_idx, frame_id);
	}
			buf->bufq_handle, buf->buf_idx, time_stamp, frame_id);

	/* Buf divert return value represent whether the buf
	 * can be diverted. A positive return value means
@@ -1759,8 +1754,15 @@ static void msm_isp_process_done_buf(struct vfe_device *vfe_dev,
				vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id;
			error_event.u.error_info.err_type =
				ISP_ERROR_FRAME_ID_MISMATCH;
			rc = vfe_dev->buf_mgr->ops->put_buf(vfe_dev->buf_mgr,
				buf->bufq_handle, buf->buf_idx);
			rc = vfe_dev->buf_mgr->ops->buf_done(vfe_dev->buf_mgr,
				buf->bufq_handle, buf->buf_idx, time_stamp,
				frame_id,
				stream_info->runtime_output_format);
			if (rc == -EFAULT) {
				msm_isp_halt_send_error(vfe_dev,
						ISP_EVENT_BUF_FATAL_ERROR);
				return;
			}
			msm_isp_send_event(vfe_dev, ISP_EVENT_ERROR,
				&error_event);
			pr_err("%s: Error! frame id mismatch!! 1st buf frame %d,curr frame %d\n",
@@ -1772,9 +1774,21 @@ static void msm_isp_process_done_buf(struct vfe_device *vfe_dev,
			/* Put but if dual vfe usecase and
			 * both vfe have done using buf
			 */
			rc = vfe_dev->buf_mgr->ops->put_buf(
			buf->buf_debug.put_state[
				buf->buf_debug.put_state_last] =
				MSM_ISP_BUFFER_STATE_DROP_SKIP;
			buf->buf_debug.put_state_last ^= 1;
			rc = vfe_dev->buf_mgr->ops->buf_done(
				vfe_dev->buf_mgr,
				buf->bufq_handle, buf->buf_idx);
				buf->bufq_handle, buf->buf_idx,
				time_stamp, frame_id,
				stream_info->runtime_output_format);

			if (rc == -EFAULT) {
				msm_isp_halt_send_error(vfe_dev,
					ISP_EVENT_BUF_FATAL_ERROR);
				return;
			}
		if (!rc) {
				ISP_DBG("%s:%d vfe_id %d Buffer dropped %d\n",
					__func__, __LINE__, vfe_dev->pdev->id,
@@ -1818,9 +1832,18 @@ static void msm_isp_process_done_buf(struct vfe_device *vfe_dev,
				buf->bufq_handle);
			msm_isp_send_event(vfe_dev, ISP_EVENT_BUF_DONE,
				&buf_event);
			vfe_dev->buf_mgr->ops->buf_done(vfe_dev->buf_mgr,
			buf->buf_debug.put_state[
				buf->buf_debug.put_state_last] =
				MSM_ISP_BUFFER_STATE_PUT_BUF;
			buf->buf_debug.put_state_last ^= 1;
			rc = vfe_dev->buf_mgr->ops->buf_done(vfe_dev->buf_mgr,
				buf->bufq_handle, buf->buf_idx, time_stamp,
				frame_id, stream_info->runtime_output_format);
			if (rc == -EFAULT) {
				msm_isp_halt_send_error(vfe_dev,
					ISP_EVENT_BUF_FATAL_ERROR);
				return;
			}
		}
	} else {
		pr_err_ratelimited("%s: Warning! Unexpected return value rc = %d\n",
@@ -1875,12 +1898,21 @@ int msm_isp_drop_frame(struct vfe_device *vfe_dev,

	if (done_buf) {
		rc = vfe_dev->buf_mgr->ops->update_put_buf_cnt(vfe_dev->buf_mgr,
			done_buf->bufq_handle, done_buf->buf_idx, frame_id);
			done_buf->bufq_handle, done_buf->buf_idx, 0, frame_id);
		if (rc == 0) {
			vfe_dev->buf_mgr->ops->buf_done(vfe_dev->buf_mgr,
			done_buf->buf_debug.put_state[
				done_buf->buf_debug.put_state_last] =
				MSM_ISP_BUFFER_STATE_DROP_REG;
			done_buf->buf_debug.put_state_last ^= 1;
			rc = vfe_dev->buf_mgr->ops->buf_done(vfe_dev->buf_mgr,
				done_buf->bufq_handle, done_buf->buf_idx,
				&ts->buf_time, frame_id,
				stream_info->runtime_output_format);
			if (rc == -EFAULT) {
				msm_isp_halt_send_error(vfe_dev,
					ISP_EVENT_BUF_FATAL_ERROR);
				return rc;
			}
		}

		bufq = vfe_dev->buf_mgr->ops->get_bufq(vfe_dev->buf_mgr,
@@ -2140,7 +2172,6 @@ int msm_isp_axi_reset(struct vfe_device *vfe_dev,
	int rc = 0, i, j;
	struct msm_vfe_axi_stream *stream_info;
	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
	struct msm_isp_bufq *bufq = NULL;
	uint32_t bufq_handle = 0, bufq_id = 0;

	if (!reset_cmd) {
@@ -2171,17 +2202,14 @@ int msm_isp_axi_reset(struct vfe_device *vfe_dev,
			if (!bufq_handle)
				continue;

			bufq = vfe_dev->buf_mgr->ops->get_bufq(vfe_dev->buf_mgr,
				bufq_handle);
			if (!bufq) {
				pr_err("%s: bufq null %p by handle %x\n",
					__func__, bufq, bufq_handle);
				continue;
			}

			vfe_dev->buf_mgr->ops->flush_buf(
			rc = vfe_dev->buf_mgr->ops->flush_buf(
				vfe_dev->buf_mgr, bufq_handle,
				MSM_ISP_BUFFER_FLUSH_ALL);
			if (rc == -EFAULT) {
				msm_isp_halt_send_error(vfe_dev,
					ISP_EVENT_BUF_FATAL_ERROR);
				return rc;
			}
			memset(&stream_info->buf, 0, sizeof(stream_info->buf));

			axi_data->src_info[SRC_TO_INTF(stream_info->
@@ -2671,9 +2699,14 @@ static int msm_isp_stop_axi_stream(struct vfe_device *vfe_dev,
			if (!bufq_handle)
				continue;

			vfe_dev->buf_mgr->ops->flush_buf(
			rc = vfe_dev->buf_mgr->ops->flush_buf(
				vfe_dev->buf_mgr, bufq_handle,
				MSM_ISP_BUFFER_FLUSH_ALL);
			if (rc == -EFAULT) {
				msm_isp_halt_send_error(vfe_dev,
					ISP_EVENT_BUF_FATAL_ERROR);
				return rc;
			}
		}
		memset(&stream_info->buf, 0, sizeof(stream_info->buf));
		vfe_dev->reg_update_requested &=
@@ -2777,6 +2810,10 @@ static int msm_isp_return_empty_buffer(struct vfe_device *vfe_dev,

	rc = vfe_dev->buf_mgr->ops->get_buf(vfe_dev->buf_mgr,
		vfe_dev->pdev->id, bufq_handle, &buf, &buf_cnt);
	if (rc == -EFAULT) {
		msm_isp_halt_send_error(vfe_dev, ISP_EVENT_BUF_FATAL_ERROR);
		return rc;
	}
	if (rc < 0) {
		vfe_dev->error_info.
			stream_framedrop_count[bufq_handle & 0xFF]++;
@@ -2785,12 +2822,20 @@ static int msm_isp_return_empty_buffer(struct vfe_device *vfe_dev,

	msm_isp_get_timestamp(&timestamp);
	rc = vfe_dev->buf_mgr->ops->update_put_buf_cnt(vfe_dev->buf_mgr,
		buf->bufq_handle, buf->buf_idx, frame_id);
		buf->bufq_handle, buf->buf_idx, 0, frame_id);
	if (rc == 0) {
		vfe_dev->buf_mgr->ops->buf_done(vfe_dev->buf_mgr,
		buf->buf_debug.put_state[buf->buf_debug.put_state_last] =
			MSM_ISP_BUFFER_STATE_DROP_REG;
		buf->buf_debug.put_state_last ^= 1;
		rc = vfe_dev->buf_mgr->ops->buf_done(vfe_dev->buf_mgr,
			buf->bufq_handle, buf->buf_idx,
			&timestamp.buf_time, frame_id,
			stream_info->runtime_output_format);
		if (rc == -EFAULT) {
			msm_isp_halt_send_error(vfe_dev,
				ISP_EVENT_BUF_FATAL_ERROR);
			return rc;
		}
	}

	error_event.frame_id = frame_id;
@@ -3069,9 +3114,14 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg)
			break;
		case DISABLE_STREAM_BUF_DIVERT:
			stream_info->buf_divert = 0;
			vfe_dev->buf_mgr->ops->flush_buf(vfe_dev->buf_mgr,
			rc = vfe_dev->buf_mgr->ops->flush_buf(vfe_dev->buf_mgr,
				stream_info->bufq_handle[VFE_BUF_QUEUE_DEFAULT],
				MSM_ISP_BUFFER_FLUSH_DIVERTED);
			if (rc == -EFAULT) {
				msm_isp_halt_send_error(vfe_dev,
					ISP_EVENT_BUF_FATAL_ERROR);
				return rc;
			}
			break;
		case UPDATE_STREAM_FRAMEDROP_PATTERN: {
			uint32_t framedrop_period =
+30 −34

File changed.

Preview size limit exceeded, changes collapsed.

+3 −1
Original line number Diff line number Diff line
@@ -610,7 +610,8 @@ enum msm_isp_event_idx {
	ISP_HW_FATAL_ERROR      = 11,
	ISP_PING_PONG_MISMATCH = 12,
	ISP_REG_UPDATE_MISSING = 13,
	ISP_EVENT_MAX         = 14
	ISP_BUF_FATAL_ERROR = 14,
	ISP_EVENT_MAX         = 15
};

#define ISP_EVENT_OFFSET          8
@@ -638,6 +639,7 @@ enum msm_isp_event_idx {
#define ISP_EVENT_HW_FATAL_ERROR  (ISP_EVENT_BASE + ISP_HW_FATAL_ERROR)
#define ISP_EVENT_PING_PONG_MISMATCH (ISP_EVENT_BASE + ISP_PING_PONG_MISMATCH)
#define ISP_EVENT_REG_UPDATE_MISSING (ISP_EVENT_BASE + ISP_REG_UPDATE_MISSING)
#define ISP_EVENT_BUF_FATAL_ERROR (ISP_EVENT_BASE + ISP_BUF_FATAL_ERROR)
#define ISP_EVENT_STREAM_UPDATE_DONE   (ISP_STREAM_EVENT_BASE)

/* The msm_v4l2_event_data structure should match the