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

Commit 2699f97e authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: camera: isp: Remove buffer queue shared list"

parents 949f0ca8 9ecd8cfc
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;
	}
	spin_lock_init(&bufq->bufq_lock);
	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