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

Commit 9ecd8cfc authored by Jing Zhou's avatar Jing Zhou
Browse files

msm: camera: isp: Remove buffer queue shared list



Remove the shared list of buffer queue that is used in case of
dual vfe. Whenever a buffer is dequeued from the buffer queue
program it on both vfe and ensure that buffer is dequeued only
once by compositing the buf done irq.
Also, program scratch buffer for stats stream

Change-Id: I96cd0a97b24bf6bc0223cbee8d1fc6bf2ecc7c49
Signed-off-by: default avatarHarsh Shah <harshs@codeaurora.org>
Signed-off-by: default avatarShubhraprakash Das <sadas@codeaurora.org>
Signed-off-by: default avatarJing Zhou <jzhou70@codeaurora.org>
parent 9e1495f3
Loading
Loading
Loading
Loading
+95 −243
Original line number Diff line number Diff line
@@ -75,31 +75,6 @@ static int msm_buf_check_head_sanity(struct msm_isp_bufq *bufq)
		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;
}

@@ -187,9 +162,7 @@ static int msm_isp_free_bufq_handle(struct msm_isp_buf_mgr *buf_mgr,
	bufq->stream_id = 0;
	bufq->num_bufs = 0;
	bufq->buf_type = 0;
	memset(&bufq->head, 0, sizeof(bufq->head));
	memset(&bufq->share_head, 0, sizeof(bufq->share_head));
	bufq->buf_client_count = 0;
	INIT_LIST_HEAD(&bufq->head);

	return 0;
}
@@ -487,27 +460,12 @@ 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)
	uint32_t bufq_handle, struct msm_isp_buffer **buf_info)
{
	int rc = -1;
	unsigned long flags;
	unsigned int list_count = 0;
	struct msm_isp_buffer *temp_buf_info = NULL;
	struct msm_isp_bufq *bufq = NULL;
	struct vb2_buffer *vb2_buf = NULL;
@@ -532,52 +490,6 @@ 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) {
			if ((temp_buf_info->get_buf_mask & (1 << id)) == 0) {
				temp_buf_info->get_buf_mask |= (1 << 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_init(
					&temp_buf_info->share_list);
				}

				if (temp_buf_info->buf_reuse_flag) {
					kfree(temp_buf_info);
				} else {
					*buf_info = temp_buf_info;
					rc = 0;
				}
				spin_unlock_irqrestore(
					&bufq->bufq_lock, flags);
				return rc;
			} else if ((temp_buf_info->get_buf_mask & (1 << id)) &&
				temp_buf_info->buf_reuse_flag) {
				spin_unlock_irqrestore(
					&bufq->bufq_lock, flags);
				return rc;
			}
			list_count++;
			if (list_count > MAX_LIST_COUNT) {
				pr_err_ratelimited("%s: %d share_list corruption, list corrupt! count = %d\n",
					__func__, __LINE__,  list_count);
				spin_unlock_irqrestore(
					&bufq->bufq_lock, flags);
				return -EINVAL;
			}
		}
	}

	switch (BUF_SRC(bufq->stream_id)) {
	case MSM_ISP_BUFFER_SRC_NATIVE:
@@ -588,11 +500,10 @@ static int msm_isp_get_buf(struct msm_isp_buf_mgr *buf_mgr, uint32_t id,
				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",
					WARN(1, "%s buf_handle 0x%x buf_idx %d\n",
						__func__,
						bufq->bufq_handle,
						temp_buf_info->buf_idx,
						temp_buf_info->buf_reuse_flag);
						temp_buf_info->buf_idx);
					return -EFAULT;
				}
				*buf_info = temp_buf_info;
@@ -641,68 +552,9 @@ static int msm_isp_get_buf(struct msm_isp_buf_mgr *buf_mgr, uint32_t id,
	}

	if (!(*buf_info)) {
		if (bufq->buf_type == ISP_SHARE_BUF) {
			temp_buf_info = kzalloc(
				sizeof(struct msm_isp_buffer), GFP_ATOMIC);
			if (temp_buf_info) {
				temp_buf_info->buf_reuse_flag = 1;
				temp_buf_info->get_buf_mask |= (1 << 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;
				}
			}
			(*buf_info)->get_buf_mask = (1 << id);
			(*buf_info)->buf_get_count = 1;
			(*buf_info)->buf_put_count = 0;
			(*buf_info)->put_buf_mask = 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;
	}
	spin_unlock_irqrestore(&bufq->bufq_lock, flags);
@@ -730,6 +582,7 @@ static int msm_isp_put_buf_unsafe(struct msm_isp_buf_mgr *buf_mgr,

	switch (buf_info->state) {
	case MSM_ISP_BUFFER_STATE_PREPARED:
	case MSM_ISP_BUFFER_STATE_DEQUEUED:
		if (BUF_SRC(bufq->stream_id)) {
			if (!list_empty(&buf_info->list)) {
				WARN(1, "%s: buf %x/%x double add\n",
@@ -738,11 +591,10 @@ static int msm_isp_put_buf_unsafe(struct msm_isp_buf_mgr *buf_mgr,
			}
			list_add_tail(&buf_info->list, &bufq->head);
			if (msm_buf_check_head_sanity(bufq) < 0) {
				WARN(1, "%s buf_handle 0x%x buf_idx %d buf_reuse_flag %d\n",
				WARN(1, "%s buf_handle 0x%x buf_idx %d\n",
					__func__,
					bufq->bufq_handle,
					buf_info->buf_idx,
					buf_info->buf_reuse_flag);
					buf_info->buf_idx);
				return -EFAULT;
			}
		} else {
@@ -757,7 +609,6 @@ static int msm_isp_put_buf_unsafe(struct msm_isp_buf_mgr *buf_mgr,
		rc = 0;
		break;
	case MSM_ISP_BUFFER_STATE_QUEUED:
	case MSM_ISP_BUFFER_STATE_DEQUEUED:
	case MSM_ISP_BUFFER_STATE_DIVERTED:
	default:
		WARN(1, "%s: bufq 0x%x, buf idx 0x%x, incorrect state = %d",
@@ -790,11 +641,6 @@ static int msm_isp_put_buf(struct msm_isp_buf_mgr *buf_mgr,

	spin_lock_irqsave(&bufq->bufq_lock, flags);

	buf_info->buf_get_count = 0;
	buf_info->buf_put_count = 0;
	buf_info->get_buf_mask = 0;
	buf_info->put_buf_mask = 0;

	rc = msm_isp_put_buf_unsafe(buf_mgr, bufq_handle, buf_index);

	spin_unlock_irqrestore(&bufq->bufq_lock, flags);
@@ -804,13 +650,13 @@ static int msm_isp_put_buf(struct msm_isp_buf_mgr *buf_mgr,

static int msm_isp_update_put_buf_cnt_unsafe(
	struct msm_isp_buf_mgr *buf_mgr,
	uint32_t id, uint32_t bufq_handle, uint32_t buf_index,
	struct timeval *tv, uint32_t frame_id, unsigned long *flags)
	uint32_t id, uint32_t bufq_handle, int32_t buf_index,
	struct timeval *tv, uint32_t frame_id, uint32_t pingpong_bit)
{
	int rc = -1;
	struct msm_isp_bufq *bufq = NULL;
	struct msm_isp_buffer *buf_info = NULL;
	enum msm_isp_buffer_state state;
	uint8_t *put_buf_mask = NULL;

	bufq = msm_isp_get_bufq(buf_mgr, bufq_handle);
	if (!bufq) {
@@ -818,38 +664,46 @@ static int msm_isp_update_put_buf_cnt_unsafe(
		return rc;
	}

	put_buf_mask = &bufq->put_buf_mask[pingpong_bit];

	if (buf_index >= 0) {
		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;
			return -EFAULT;
		}
		if (buf_info->state != MSM_ISP_BUFFER_STATE_DEQUEUED) {
			pr_err(
			"%s: Invalid state, bufq_handle %x stream id %x, state %d\n",
			__func__, bufq_handle,
			bufq->stream_id, buf_info->state);
			return -EFAULT;
		}
		BUG_ON(buf_info->pingpong_bit != pingpong_bit);
	}

	if (bufq->buf_type != ISP_SHARE_BUF ||
		buf_info->put_buf_mask == 0) {
		(*put_buf_mask == 0)) {
		if (buf_info)
			buf_info->frame_id = frame_id;
	}

	state = buf_info->state;
	if (state == MSM_ISP_BUFFER_STATE_DEQUEUED) {
	if (bufq->buf_type == ISP_SHARE_BUF &&
			((buf_info->put_buf_mask & (1 << id)) == 0)) {
			buf_info->put_buf_mask |= (1 << id);
			buf_info->buf_put_count++;
			if (buf_info->buf_put_count != ISP_SHARE_BUF_CLIENT) {
				rc = buf_info->buf_put_count;
				return rc;
			}
		((*put_buf_mask & (1 << id)) == 0)) {
		*put_buf_mask |= (1 << id);
		if (*put_buf_mask != ISP_SHARE_BUF_MASK) {
			rc = *put_buf_mask;
			return 1;
		}
	} 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();
		spin_lock_irqsave(&bufq->bufq_lock, *flags);
		return rc;
		*put_buf_mask = 0;
		rc = 0;
	} else if (bufq->buf_type == ISP_SHARE_BUF &&
		(*put_buf_mask & (1 << id)) != 0) {
		return -ENOTEMPTY;
	}

	if (MSM_ISP_BUFFER_SRC_NATIVE == BUF_SRC(bufq->stream_id)) {
	if (buf_info &&
		MSM_ISP_BUFFER_SRC_NATIVE == BUF_SRC(bufq->stream_id)) {
			buf_info->state = MSM_ISP_BUFFER_STATE_DIVERTED;
			buf_info->tv = tv;
	}
@@ -857,8 +711,8 @@ static int msm_isp_update_put_buf_cnt_unsafe(
}

static int msm_isp_update_put_buf_cnt(struct msm_isp_buf_mgr *buf_mgr,
	uint32_t id, uint32_t bufq_handle, uint32_t buf_index,
	struct timeval *tv, uint32_t frame_id)
	uint32_t id, uint32_t bufq_handle, int32_t buf_index,
	struct timeval *tv, uint32_t frame_id, uint32_t pingpong_bit)
{
	int rc = -1;
	struct msm_isp_bufq *bufq = NULL;
@@ -872,7 +726,12 @@ static int msm_isp_update_put_buf_cnt(struct msm_isp_buf_mgr *buf_mgr,

	spin_lock_irqsave(&bufq->bufq_lock, flags);
	rc = msm_isp_update_put_buf_cnt_unsafe(buf_mgr, id, bufq_handle,
		buf_index, tv, frame_id, &flags);
		buf_index, tv, frame_id, pingpong_bit);
	if (-ENOTEMPTY == rc) {
		pr_err("%s: Error! Uncleared put_buf_mask for pingpong(%d) from vfe %d bufq 0x%x buf_idx %d\n",
			__func__, pingpong_bit, id, bufq_handle, buf_index);
		rc = -EFAULT;
	}
	spin_unlock_irqrestore(&bufq->bufq_lock, flags);
	return rc;
}
@@ -881,7 +740,7 @@ static int msm_isp_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 rc = -1;
	int rc = 0;
	unsigned long flags;
	struct msm_isp_bufq *bufq = NULL;
	struct msm_isp_buffer *buf_info = NULL;
@@ -890,13 +749,13 @@ static int msm_isp_buf_done(struct msm_isp_buf_mgr *buf_mgr,
	bufq = msm_isp_get_bufq(buf_mgr, bufq_handle);
	if (!bufq) {
		pr_err("Invalid bufq\n");
		return rc;
		return -EINVAL;
	}

	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;
		return -EINVAL;
	}

	spin_lock_irqsave(&bufq->bufq_lock, flags);
@@ -936,7 +795,7 @@ static int msm_isp_flush_buf(struct msm_isp_buf_mgr *buf_mgr, uint32_t id,
	uint32_t bufq_handle, enum msm_isp_buffer_flush_t flush_type,
	struct timeval *tv, uint32_t frame_id)
{
	int rc = -1, i;
	int rc = 0, i;
	struct msm_isp_bufq *bufq = NULL;
	struct msm_isp_buffer *buf_info = NULL;
	unsigned long flags;
@@ -944,7 +803,7 @@ static int msm_isp_flush_buf(struct msm_isp_buf_mgr *buf_mgr, uint32_t id,
	bufq = msm_isp_get_bufq(buf_mgr, bufq_handle);
	if (!bufq) {
		pr_err("Invalid bufq\n");
		return rc;
		return -EINVAL;
	}

	spin_lock_irqsave(&bufq->bufq_lock, flags);
@@ -965,40 +824,35 @@ static int msm_isp_flush_buf(struct msm_isp_buf_mgr *buf_mgr, uint32_t id,
					__func__);
			} else if (buf_info->state ==
				MSM_ISP_BUFFER_STATE_DEQUEUED) {
				rc = msm_isp_update_put_buf_cnt_unsafe(buf_mgr,
					id, bufq_handle, buf_info->buf_idx, tv,
					frame_id,  buf_info->pingpong_bit);
				if (-ENOTEMPTY == rc) {
					rc = 0;
					continue;
				}

				if (rc == 0) {
					buf_info->buf_debug.put_state[
					buf_info->buf_debug.put_state_last]
						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;
					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,
						spin_unlock_irqrestore(
							&bufq->bufq_lock,
							flags);
						return rc;
					}
				}
			}
		}

	if (bufq->buf_type == ISP_SHARE_BUF) {
		while (!list_empty(&bufq->share_head)) {
			buf_info = list_entry((&bufq->share_head)->next,
				typeof(*buf_info), share_list);
			list_del_init(&(buf_info->share_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,
					buf_info->buf_idx,
					buf_info->buf_reuse_flag);
				return -EFAULT;
			}
			if (buf_info->buf_reuse_flag)
				kfree(buf_info);
		 }
	}

	spin_unlock_irqrestore(&bufq->bufq_lock, flags);
	return 0;
}
@@ -1006,7 +860,7 @@ static int msm_isp_flush_buf(struct msm_isp_buf_mgr *buf_mgr, uint32_t id,
static int msm_isp_buf_enqueue(struct msm_isp_buf_mgr *buf_mgr,
	struct msm_isp_qbuf_info *info)
{
	int rc = -1, buf_state;
	int rc = 0, buf_state;
	struct msm_isp_bufq *bufq = NULL;
	struct msm_isp_buffer *buf_info = NULL;

@@ -1029,7 +883,7 @@ static int msm_isp_buf_enqueue(struct msm_isp_buf_mgr *buf_mgr,
						info->handle, info->buf_idx);
		if (!buf_info) {
			pr_err("%s: buf not found\n", __func__);
			return rc;
			return -EINVAL;
		}
		if (info->dirty_buf) {
			buf_info->buf_debug.put_state[
@@ -1059,7 +913,7 @@ static int msm_isp_buf_enqueue(struct msm_isp_buf_mgr *buf_mgr,
				info->handle, info->buf_idx);
			if (!buf_info) {
				pr_err("%s: buf not found\n", __func__);
				return rc;
				return -EINVAL;
			}

			buf_info->buf_debug.put_state[
@@ -1075,7 +929,7 @@ static int msm_isp_buf_enqueue(struct msm_isp_buf_mgr *buf_mgr,
			}
		}
	}
	return rc;
	return 0;
}

static int msm_isp_buf_dequeue(struct msm_isp_buf_mgr *buf_mgr,
@@ -1136,20 +990,20 @@ static int msm_isp_get_buf_src(struct msm_isp_buf_mgr *buf_mgr,
static int msm_isp_request_bufq(struct msm_isp_buf_mgr *buf_mgr,
	struct msm_isp_buf_request *buf_request)
{
	int rc = -1, i;
	int i;
	struct msm_isp_bufq *bufq = NULL;
	CDBG("%s: E\n", __func__);

	if (!buf_request->num_buf || buf_request->num_buf > VB2_MAX_FRAME) {
		pr_err("Invalid buffer request\n");
		return rc;
		return -EINVAL;
	}

	buf_request->handle = msm_isp_get_buf_handle(buf_mgr,
		buf_request->session_id, buf_request->stream_id);
	if (!buf_request->handle) {
		pr_err("Invalid buffer handle\n");
		return rc;
		return -EINVAL;
	}

	bufq = msm_isp_get_bufq(buf_mgr, buf_request->handle);
@@ -1157,7 +1011,7 @@ static int msm_isp_request_bufq(struct msm_isp_buf_mgr *buf_mgr,
		pr_err("%s: Invalid bufq stream_id %x\n",
			__func__, buf_request->stream_id);

		return rc;
		return -EINVAL;
	}

	bufq->bufs = kzalloc(sizeof(struct msm_isp_buffer) *
@@ -1165,7 +1019,7 @@ static int msm_isp_request_bufq(struct msm_isp_buf_mgr *buf_mgr,
	if (!bufq->bufs) {
		pr_err("No free memory for buf info\n");
		msm_isp_free_bufq_handle(buf_mgr, buf_request->handle);
		return rc;
		return -ENOMEM;
	}

	bufq->bufq_handle = buf_request->handle;
@@ -1173,10 +1027,10 @@ static int msm_isp_request_bufq(struct msm_isp_buf_mgr *buf_mgr,
	bufq->stream_id = buf_request->stream_id;
	bufq->num_bufs = buf_request->num_buf;
	bufq->buf_type = buf_request->buf_type;
	if (bufq->buf_type == ISP_SHARE_BUF)
		bufq->buf_client_count = ISP_SHARE_BUF_CLIENT;
	for (i = 0; i < ISP_NUM_BUF_MASK; i++)
		bufq->put_buf_mask[i] = 0;
	INIT_LIST_HEAD(&bufq->head);
	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] =
@@ -1187,7 +1041,6 @@ static int msm_isp_request_bufq(struct msm_isp_buf_mgr *buf_mgr,
		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;
@@ -1198,11 +1051,10 @@ static int msm_isp_release_bufq(struct msm_isp_buf_mgr *buf_mgr,
{
	struct msm_isp_bufq *bufq = NULL;
	unsigned long flags;
	int rc = -1;
	bufq = msm_isp_get_bufq(buf_mgr, bufq_handle);
	if (!bufq) {
		pr_err("Invalid bufq release\n");
		return rc;
		return -EINVAL;
	}

	msm_isp_buf_unprepare_all(buf_mgr, bufq_handle);
+12 −17
Original line number Diff line number Diff line
@@ -23,7 +23,12 @@
		(id & ISP_NATIVE_BUF_BIT) ? MSM_ISP_BUFFER_SRC_NATIVE : \
				MSM_ISP_BUFFER_SRC_HAL)

#define ISP_SHARE_BUF_CLIENT 2
/*
 * This mask can be set dynamically if there are more than 2 VFE
 *.and 2 of those are used
 */
#define ISP_SHARE_BUF_MASK 0x3
#define ISP_NUM_BUF_MASK 2
#define BUF_MGR_NUM_BUF_Q 28
#define MAX_IOMMU_CTX 2

@@ -89,6 +94,8 @@ struct msm_isp_buffer {
	uint32_t bufq_handle;
	uint32_t frame_id;
	struct timeval *tv;
	/* Indicates whether buffer is used as ping ot pong buffer */
	uint32_t pingpong_bit;

	/*Native buffer*/
	struct list_head list;
@@ -98,14 +105,6 @@ struct msm_isp_buffer {

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

	/*Share buffer cache state*/
	struct list_head share_list;
	uint8_t get_buf_mask;
	uint8_t put_buf_mask;
	uint8_t buf_get_count;
	uint8_t buf_put_count;
	uint8_t buf_reuse_flag;
};

struct msm_isp_bufq {
@@ -116,12 +115,9 @@ struct msm_isp_bufq {
	enum msm_isp_buf_type buf_type;
	struct msm_isp_buffer *bufs;
	spinlock_t bufq_lock;

	uint8_t put_buf_mask[ISP_NUM_BUF_MASK];
	/*Native buffer queue*/
	struct list_head head;
	/*Share buffer cache queue*/
	struct list_head share_head;
	uint8_t buf_client_count;
};

struct msm_isp_buf_ops {
@@ -144,8 +140,7 @@ struct msm_isp_buf_ops {
		uint32_t bufq_handle, uint32_t *buf_src);

	int (*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);
		uint32_t bufq_handle, struct msm_isp_buffer **buf_info);

	int (*get_buf_by_index)(struct msm_isp_buf_mgr *buf_mgr,
		uint32_t bufq_handle, uint32_t buf_index,
@@ -177,8 +172,8 @@ struct msm_isp_buf_ops {
	struct msm_isp_bufq * (*get_bufq)(struct msm_isp_buf_mgr *buf_mgr,
		uint32_t bufq_handle);
	int (*update_put_buf_cnt)(struct msm_isp_buf_mgr *buf_mgr,
		uint32_t id, uint32_t bufq_handle, uint32_t buf_index,
		struct timeval *tv, uint32_t frame_id);
	uint32_t id, uint32_t bufq_handle, int32_t buf_index,
	struct timeval *tv, uint32_t frame_id, uint32_t pingpong_bit);
};

struct msm_isp_buf_mgr {
+484 −408

File changed.

Preview size limit exceeded, changes collapsed.

+162 −96
Original line number Diff line number Diff line
@@ -17,16 +17,40 @@
#include "msm_isp_axi_util.h"
#include "msm_isp_stats_util.h"

static inline void msm_isp_stats_cfg_wm_scratch(struct vfe_device *vfe_dev,
				struct msm_vfe_stats_stream *stream_info,
				uint32_t pingpong_status)
{
	vfe_dev->hw_info->vfe_ops.stats_ops.update_ping_pong_addr(
		vfe_dev->vfe_base, stream_info,
		pingpong_status, vfe_dev->buf_mgr->scratch_buf_addr);
}

static inline void msm_isp_stats_cfg_stream_scratch(struct vfe_device *vfe_dev,
				struct msm_vfe_stats_stream *stream_info,
				uint32_t pingpong_status)
{
	uint32_t stats_idx = STATS_IDX(stream_info->stream_handle);
	uint32_t pingpong_bit;
	uint32_t stats_pingpong_offset =
		vfe_dev->hw_info->stats_hw_info->stats_ping_pong_offset[
		stats_idx];

	pingpong_bit = (~(pingpong_status >> stats_pingpong_offset) & 0x1);

	msm_isp_stats_cfg_wm_scratch(vfe_dev, stream_info,
		pingpong_status);
	stream_info->buf[pingpong_bit] = NULL;
}

static int msm_isp_stats_cfg_ping_pong_address(struct vfe_device *vfe_dev,
	struct msm_vfe_stats_stream *stream_info, uint32_t pingpong_status,
	struct msm_isp_buffer **done_buf)
	struct msm_vfe_stats_stream *stream_info, uint32_t pingpong_status)
{
	int rc = -1, vfe_id = 0;
	struct msm_isp_buffer *buf;
	uint32_t pingpong_bit = 0;
	uint32_t buf_cnt = 0;
	uint32_t bufq_handle = stream_info->bufq_handle;
	uint32_t stats_pingpong_offset;
	uint32_t bufq_handle = stream_info->bufq_handle;
	uint32_t stats_idx = STATS_IDX(stream_info->stream_handle);
	struct dual_vfe_resource *dual_vfe_res = NULL;
	struct msm_vfe_stats_stream *dual_vfe_stream_info = NULL;
@@ -42,23 +66,23 @@ static int msm_isp_stats_cfg_ping_pong_address(struct vfe_device *vfe_dev,
		stats_idx];

	pingpong_bit = (~(pingpong_status >> stats_pingpong_offset) & 0x1);

	rc = vfe_dev->buf_mgr->ops->get_buf(vfe_dev->buf_mgr,
			vfe_dev->pdev->id, bufq_handle, &buf, &buf_cnt);
			vfe_dev->pdev->id, bufq_handle, &buf);
	if (rc == -EFAULT) {
		msm_isp_halt_send_error(vfe_dev, ISP_EVENT_BUF_FATAL_ERROR);
		return rc;
	}
	if (rc < 0) {
	if (rc < 0 || NULL == buf)
		vfe_dev->error_info.stats_framedrop_count[stats_idx]++;
		return rc;
	}

	if (buf->num_planes != 1) {
	if (buf && buf->num_planes != 1) {
		pr_err("%s: Invalid buffer\n", __func__);
		msm_isp_halt_send_error(vfe_dev, ISP_EVENT_BUF_FATAL_ERROR);
		rc = -EINVAL;
		goto buf_error;
	}
	if (vfe_dev->is_split && buf_cnt == MAX_VFE) {
	if (vfe_dev->is_split) {
		dual_vfe_res = vfe_dev->common_data->dual_vfe_res;
		if (!dual_vfe_res->vfe_base[ISP_VFE0] ||
			!dual_vfe_res->stats_data[ISP_VFE0] ||
@@ -74,26 +98,41 @@ static int msm_isp_stats_cfg_ping_pong_address(struct vfe_device *vfe_dev,
				dual_vfe_stream_info = &dual_vfe_res->
					stats_data[vfe_id]->
					stream_info[stats_idx];
				if (buf)
					vfe_dev->hw_info->vfe_ops.stats_ops.
						update_ping_pong_addr(
						dual_vfe_res->vfe_base[vfe_id],
					dual_vfe_stream_info, pingpong_status,
						dual_vfe_stream_info,
						pingpong_status,
						buf->mapped_info[0].paddr +
					dual_vfe_stream_info->buffer_offset);
						dual_vfe_stream_info->
						buffer_offset);
				else
					msm_isp_stats_cfg_stream_scratch(
						vfe_dev,
						dual_vfe_stream_info,
						pingpong_status);

				dual_vfe_stream_info->buf[pingpong_bit]
					= buf;
			}
		}
	} else if (!vfe_dev->is_split) {
		vfe_dev->hw_info->vfe_ops.stats_ops.update_ping_pong_addr(
		if (buf)
			vfe_dev->hw_info->vfe_ops.stats_ops.
				update_ping_pong_addr(
				vfe_dev->vfe_base, stream_info,
				pingpong_status, buf->mapped_info[0].paddr +
				stream_info->buffer_offset);
	}


	if (stream_info->buf[pingpong_bit] && done_buf)
		*done_buf = stream_info->buf[pingpong_bit];
		else
			msm_isp_stats_cfg_stream_scratch(vfe_dev,
					stream_info, pingpong_status);

		stream_info->buf[pingpong_bit] = buf;
	}

	if (buf)
		buf->pingpong_bit = pingpong_bit;
	return 0;
buf_error:
	vfe_dev->buf_mgr->ops->put_buf(vfe_dev->buf_mgr,
@@ -102,20 +141,24 @@ buf_error:
}

static int32_t msm_isp_stats_buf_divert(struct vfe_device *vfe_dev,
	struct msm_isp_buffer *done_buf, struct msm_isp_timestamp *ts,
	struct msm_isp_timestamp *ts,
	struct msm_isp_event_data *buf_event,
	struct msm_vfe_stats_stream *stream_info,
	uint32_t *comp_stats_type_mask)
	uint32_t *comp_stats_type_mask, uint32_t pingpong_status)
{
	int32_t rc = 0, frame_id = 0, drop_buffer = 0;
	struct msm_isp_stats_event *stats_event = NULL;
	struct msm_isp_sw_framskip *sw_skip = NULL;
	int32_t buf_index = -1;
	uint32_t pingpong_bit;
	struct msm_isp_buffer *done_buf;
	uint32_t stats_pingpong_offset;
	uint32_t stats_idx;

	if (!vfe_dev || !done_buf || !ts || !buf_event || !stream_info ||
		!comp_stats_type_mask) {
		pr_err("%s:%d failed: invalid params %p %p %p %p %p %p\n",
			__func__, __LINE__, vfe_dev, done_buf, ts, buf_event,
			stream_info, comp_stats_type_mask);
	if (!vfe_dev || !ts || !buf_event || !stream_info) {
		pr_err("%s:%d failed: invalid params %p %p %p %p\n",
			__func__, __LINE__, vfe_dev, ts, buf_event,
			stream_info);
		return -EINVAL;
	}
	frame_id = vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id;
@@ -138,39 +181,60 @@ static int32_t msm_isp_stats_buf_divert(struct vfe_device *vfe_dev,
				(struct msm_isp_sw_framskip));
		}
	}
	stats_idx = STATS_IDX(stream_info->stream_handle);

	stats_pingpong_offset =
			vfe_dev->hw_info->stats_hw_info->stats_ping_pong_offset[
			stats_idx];
	pingpong_bit = (~(pingpong_status >> stats_pingpong_offset) & 0x1);

	done_buf = stream_info->buf[pingpong_bit];

	if (done_buf)
		buf_index = done_buf->buf_idx;

	rc = vfe_dev->buf_mgr->ops->update_put_buf_cnt(
		vfe_dev->buf_mgr, vfe_dev->pdev->id, done_buf->bufq_handle,
		done_buf->buf_idx, &ts->buf_time,
		frame_id);
	if (rc != 0) {
		vfe_dev->buf_mgr, vfe_dev->pdev->id, stream_info->bufq_handle,
		buf_index, &ts->buf_time,
		frame_id, pingpong_bit);

	if (rc < 0) {
		if (rc == -EFAULT)
			msm_isp_halt_send_error(vfe_dev,
					ISP_EVENT_BUF_FATAL_ERROR);
		pr_err("stats_buf_divert: update put buf cnt fail\n");
		return rc;
	}

	if (rc > 0) {
		ISP_DBG("%s: vfe_id %d buf_id %d bufq %x put_cnt 1\n", __func__,
			vfe_dev->pdev->id, done_buf->buf_idx,
			done_buf->bufq_handle);
		*comp_stats_type_mask |=
			1 << stream_info->stats_type;
		stats_event->stats_buf_idxs
			[stream_info->stats_type] =
			done_buf->buf_idx;
			vfe_dev->pdev->id, buf_index,
			stream_info->bufq_handle);
		return rc;
	}

	if (drop_buffer) {
	/* Program next buffer */
	rc = msm_isp_stats_cfg_ping_pong_address(vfe_dev, stream_info,
						pingpong_status);
	if (rc)
		return rc;

	if (drop_buffer && done_buf) {
		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, 0);
		if (rc == -EFAULT) {
		if (rc == -EFAULT)
			msm_isp_halt_send_error(vfe_dev,
					ISP_EVENT_BUF_FATAL_ERROR);
		return rc;
	}
		return rc;
	}

	if (done_buf) {
		stats_event->stats_buf_idxs
			[stream_info->stats_type] =
			done_buf->buf_idx;
	if (!stream_info->composite_flag) {
		if (NULL == comp_stats_type_mask) {
			stats_event->stats_mask =
				1 << stream_info->stats_type;
			ISP_DBG("%s: stats frameid: 0x%x %d bufq %x\n",
@@ -184,6 +248,7 @@ static int32_t msm_isp_stats_buf_divert(struct vfe_device *vfe_dev,
			*comp_stats_type_mask |=
				1 << stream_info->stats_type;
		}
	}

	return rc;
}
@@ -195,10 +260,10 @@ static int32_t msm_isp_stats_configure(struct vfe_device *vfe_dev,
	int i, rc = 0;
	struct msm_isp_event_data buf_event;
	struct msm_isp_stats_event *stats_event = &buf_event.u.stats;
	struct msm_isp_buffer *done_buf;
	struct msm_vfe_stats_stream *stream_info = NULL;
	uint32_t pingpong_status;
	uint32_t comp_stats_type_mask = 0;
	int result = 0;

	memset(&buf_event, 0, sizeof(struct msm_isp_event_data));
	buf_event.timestamp = ts->buf_time;
@@ -210,26 +275,24 @@ static int32_t msm_isp_stats_configure(struct vfe_device *vfe_dev,
		if (!(stats_irq_mask & (1 << i)))
			continue;
		stream_info = &vfe_dev->stats_data.stream_info[i];

		if (stream_info->state == STATS_INACTIVE) {
			pr_debug("%s: Warning! Stream already inactive. Drop irq handling\n",
				__func__);
			continue;
		}

		done_buf = NULL;
		msm_isp_stats_cfg_ping_pong_address(vfe_dev,
			stream_info, pingpong_status, &done_buf);
		if (done_buf) {
			rc = msm_isp_stats_buf_divert(vfe_dev, done_buf, ts,
				&buf_event, stream_info, &comp_stats_type_mask);
		rc = msm_isp_stats_buf_divert(vfe_dev, ts,
				&buf_event, stream_info,
				is_composite ? &comp_stats_type_mask : NULL,
				pingpong_status);
		if (rc < 0) {
			pr_err("%s:%d failed: stats buf divert rc %d\n",
				__func__, __LINE__, rc);
			if (0 == result)
				result = rc;
		}
	}
	}
	if (is_composite && !rc && comp_stats_type_mask) {
	if (is_composite && comp_stats_type_mask) {
		ISP_DBG("%s:vfe_id %d comp_stats frameid %x,comp_mask %x\n",
			__func__, vfe_dev->pdev->id, buf_event.frame_id,
			comp_stats_type_mask);
@@ -238,7 +301,7 @@ static int32_t msm_isp_stats_configure(struct vfe_device *vfe_dev,
			ISP_EVENT_COMP_STATS_NOTIFY, &buf_event);
		comp_stats_type_mask = 0;
	}
	return rc;
	return result;
}

void msm_isp_process_stats_irq(struct vfe_device *vfe_dev,
@@ -272,10 +335,6 @@ void msm_isp_process_stats_irq(struct vfe_device *vfe_dev,
	if (stats_irq_mask) {
		rc = msm_isp_stats_configure(vfe_dev, stats_irq_mask, ts,
			comp_flag);
		if (rc < 0) {
			pr_err("%s:%d failed individual stats rc %d\n",
				__func__, __LINE__, rc);
		}
	}

	/* Process composite irq */
@@ -289,10 +348,6 @@ void msm_isp_process_stats_irq(struct vfe_device *vfe_dev,

			rc = msm_isp_stats_configure(vfe_dev, atomic_stats_mask,
				ts, !comp_flag);
			if (rc < 0) {
				pr_err("%s:%d failed comp stats %d rc %d\n",
					__func__, __LINE__, j, rc);
			}
		}
	}
}
@@ -397,6 +452,10 @@ int msm_isp_request_stats_stream(struct vfe_device *vfe_dev, void *arg)
		vfe_dev->hw_info->vfe_ops.stats_ops.cfg_wm_reg(vfe_dev,
			stream_info);

	msm_isp_stats_cfg_stream_scratch(vfe_dev, stream_info,
					VFE_PING_FLAG);
	msm_isp_stats_cfg_stream_scratch(vfe_dev, stream_info,
					VFE_PONG_FLAG);
	return rc;
}

@@ -450,18 +509,21 @@ static int msm_isp_init_stats_ping_pong_reg(
		return -EINVAL;
	}

	if ((vfe_dev->is_split && vfe_dev->pdev->id == 1) ||
		!vfe_dev->is_split) {
		rc = msm_isp_stats_cfg_ping_pong_address(vfe_dev,
		stream_info, VFE_PING_FLAG, NULL);
			stream_info, VFE_PING_FLAG);
		if (rc < 0) {
			pr_err("%s: No free buffer for ping\n", __func__);
			return rc;
		}
		rc = msm_isp_stats_cfg_ping_pong_address(vfe_dev,
		stream_info, VFE_PONG_FLAG, NULL);
			stream_info, VFE_PONG_FLAG);
		if (rc < 0) {
			pr_err("%s: No free buffer for pong\n", __func__);
			return rc;
		}
	}
	return rc;
}

@@ -616,7 +678,6 @@ static int msm_isp_start_stats_stream(struct vfe_device *vfe_dev,
	uint32_t num_stats_comp_mask = 0;
	struct msm_vfe_stats_stream *stream_info;
	struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data;

	num_stats_comp_mask =
		vfe_dev->hw_info->stats_hw_info->num_stats_comp_mask;
	rc = vfe_dev->hw_info->vfe_ops.stats_ops.check_streams(
@@ -735,6 +796,11 @@ static int msm_isp_stop_stats_stream(struct vfe_device *vfe_dev,
			comp_stats_mask[stream_info->composite_flag-1] |=
				1 << idx;

		msm_isp_stats_cfg_stream_scratch(vfe_dev, stream_info,
						VFE_PING_FLAG);
		msm_isp_stats_cfg_stream_scratch(vfe_dev, stream_info,
						VFE_PONG_FLAG);

		ISP_DBG("%s: stats_mask %x %x active streams %d\n",
			__func__, comp_stats_mask[0],
			comp_stats_mask[1],
+10 −1
Original line number Diff line number Diff line
@@ -350,6 +350,15 @@ static inline u32 msm_isp_evt_mask_to_isp_event(u32 evt_mask)
	case ISP_EVENT_MASK_INDEX_MASK_FE_READ_DONE:
		evt_id = ISP_EVENT_FE_READ_DONE;
		break;
	case ISP_EVENT_MASK_INDEX_PING_PONG_MISMATCH:
		evt_id = ISP_EVENT_PING_PONG_MISMATCH;
		break;
	case ISP_EVENT_MASK_INDEX_REG_UPDATE_MISSING:
		evt_id = ISP_EVENT_REG_UPDATE_MISSING;
		break;
	case ISP_EVENT_MASK_INDEX_BUF_FATAL_ERROR:
		evt_id = ISP_EVENT_BUF_FATAL_ERROR;
		break;
	default:
		evt_id = ISP_EVENT_SUBS_MASK_NONE;
		break;
@@ -424,7 +433,7 @@ static inline int msm_isp_process_event_subscription(struct v4l2_fh *fh,
	}

	for (evt_mask_index = ISP_EVENT_MASK_INDEX_STATS_NOTIFY;
		evt_mask_index <= ISP_EVENT_MASK_INDEX_MASK_FE_READ_DONE;
		evt_mask_index <= ISP_EVENT_MASK_INDEX_BUF_FATAL_ERROR;
		evt_mask_index++) {
		if (evt_mask & (1<<evt_mask_index)) {
			evt_id = msm_isp_evt_mask_to_isp_event(evt_mask_index);
Loading