summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJing Zhou <jzhou70@codeaurora.org>2015-09-29 12:58:40 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 21:22:40 -0700
commitcc999c3a996122d3b2413b87b04cab45dd6fe80d (patch)
tree4d23410c0e86be44d94a214c1a7c15ca91596e58
parent0288b6f43bd6c2ef4b430fa89113bbfae8b79b24 (diff)
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: Harsh Shah <harshs@codeaurora.org> Signed-off-by: Jing Zhou <jzhou70@codeaurora.org>
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c378
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h20
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c118
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c64
-rw-r--r--include/media/msmb_isp.h4
5 files changed, 393 insertions, 191 deletions
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
index 4542d16a7524..11f499be8d46 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
@@ -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;
}
@@ -549,27 +645,66 @@ 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);
+ sizeof(struct msm_isp_buffer), GFP_ATOMIC);
if (temp_buf_info) {
temp_buf_info->buf_reuse_flag = 1;
temp_buf_info->buf_used[id] = 1;
temp_buf_info->buf_get_count = 1;
list_add_tail(&temp_buf_info->share_list,
- &bufq->share_head);
+ &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);
- 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)) {
+ 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);
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,7 +967,16 @@ 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));
+ 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);
}
@@ -828,50 +985,6 @@ static int msm_isp_flush_buf(struct msm_isp_buf_mgr *buf_mgr,
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;
- }
-
- 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->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;
-}
-
static int msm_isp_buf_enqueue(struct msm_isp_buf_mgr *buf_mgr,
struct msm_isp_qbuf_info *info)
{
@@ -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,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h
index 6041604dc4c0..1d4951b069bd 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h
@@ -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);
};
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index d1bd520fbc54..f3709b6a0d43 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -1561,7 +1561,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.
@@ -1674,8 +1678,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;
}
@@ -1746,15 +1748,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);
- }
+ rc = vfe_dev->buf_mgr->ops->update_put_buf_cnt(vfe_dev->buf_mgr,
+ 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
@@ -1773,8 +1768,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",
@@ -1786,10 +1788,22 @@ 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);
- if (!rc) {
+ 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,
frame_id);
@@ -1832,9 +1846,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",
@@ -1889,12 +1912,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,
@@ -2154,7 +2186,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) {
@@ -2185,17 +2216,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->
@@ -2725,9 +2753,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 &=
@@ -2831,6 +2864,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]++;
@@ -2839,12 +2876,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;
@@ -3123,9 +3168,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 =
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
index a3eb7f5752db..06e35fbeae2b 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
@@ -14,6 +14,7 @@
#include <media/v4l2-subdev.h>
#include <media/msmb_isp.h>
#include "msm_isp_util.h"
+#include "msm_isp_axi_util.h"
#include "msm_isp_stats_util.h"
static int msm_isp_stats_cfg_ping_pong_address(struct vfe_device *vfe_dev,
@@ -43,6 +44,10 @@ static int msm_isp_stats_cfg_ping_pong_address(struct vfe_device *vfe_dev,
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);
+ if (rc == -EFAULT) {
+ msm_isp_halt_send_error(vfe_dev, ISP_EVENT_BUF_FATAL_ERROR);
+ return rc;
+ }
if (rc < 0) {
vfe_dev->error_info.stats_framedrop_count[stats_idx]++;
return rc;
@@ -134,7 +139,7 @@ static int32_t msm_isp_stats_buf_divert(struct vfe_device *vfe_dev,
}
}
- rc = vfe_dev->buf_mgr->ops->buf_divert(
+ rc = vfe_dev->buf_mgr->ops->update_put_buf_cnt(
vfe_dev->buf_mgr, done_buf->bufq_handle,
done_buf->buf_idx, &ts->buf_time,
frame_id);
@@ -151,10 +156,15 @@ static int32_t msm_isp_stats_buf_divert(struct vfe_device *vfe_dev,
}
if (drop_buffer) {
- vfe_dev->buf_mgr->ops->put_buf(
+ rc = vfe_dev->buf_mgr->ops->buf_done(
vfe_dev->buf_mgr,
done_buf->bufq_handle,
- done_buf->buf_idx);
+ done_buf->buf_idx, &ts->buf_time, frame_id, 0);
+ if (rc == -EFAULT) {
+ msm_isp_halt_send_error(vfe_dev,
+ ISP_EVENT_BUF_FATAL_ERROR);
+ return rc;
+ }
return rc;
}
stats_event->stats_buf_idxs
@@ -455,20 +465,6 @@ static int msm_isp_init_stats_ping_pong_reg(
return rc;
}
-static void msm_isp_deinit_stats_ping_pong_reg(
- struct vfe_device *vfe_dev,
- struct msm_vfe_stats_stream *stream_info)
-{
- int i;
- struct msm_isp_buffer *buf;
- for (i = 0; i < 2; i++) {
- buf = stream_info->buf[i];
- if (buf)
- vfe_dev->buf_mgr->ops->put_buf(vfe_dev->buf_mgr,
- buf->bufq_handle, buf->buf_idx);
- }
-}
-
void msm_isp_update_stats_framedrop_reg(struct vfe_device *vfe_dev)
{
int i;
@@ -569,33 +565,26 @@ static int msm_isp_stats_update_cgc_override(struct vfe_device *vfe_dev,
int msm_isp_stats_reset(struct vfe_device *vfe_dev)
{
- int i = 0;
+ int i = 0, rc = 0;
struct msm_vfe_stats_stream *stream_info = NULL;
struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data;
- struct msm_isp_bufq *bufq = NULL;
for (i = 0; i < MSM_ISP_STATS_MAX; i++) {
stream_info = &stats_data->stream_info[i];
if (stream_info->state != STATS_ACTIVE)
continue;
- bufq = vfe_dev->buf_mgr->ops->get_bufq(vfe_dev->buf_mgr,
- stream_info->bufq_handle);
- if (!bufq) {
- pr_err("%s Error! bufq is NULL\n", __func__);
- continue;
+ rc = vfe_dev->buf_mgr->ops->flush_buf(vfe_dev->buf_mgr,
+ stream_info->bufq_handle,
+ MSM_ISP_BUFFER_FLUSH_ALL);
+ if (rc == -EFAULT) {
+ msm_isp_halt_send_error(vfe_dev,
+ ISP_EVENT_BUF_FATAL_ERROR);
+ return rc;
}
-
- if (bufq->buf_type != ISP_SHARE_BUF)
- msm_isp_deinit_stats_ping_pong_reg(vfe_dev,
- stream_info);
- else
- vfe_dev->buf_mgr->ops->flush_buf(vfe_dev->buf_mgr,
- stream_info->bufq_handle,
- MSM_ISP_BUFFER_FLUSH_ALL);
}
- return 0;
+ return rc;
}
int msm_isp_stats_restart(struct vfe_device *vfe_dev)
@@ -764,7 +753,14 @@ static int msm_isp_stop_stats_stream(struct vfe_device *vfe_dev,
}
stream_info = &stats_data->stream_info[idx];
- msm_isp_deinit_stats_ping_pong_reg(vfe_dev, stream_info);
+ rc = vfe_dev->buf_mgr->ops->flush_buf(vfe_dev->buf_mgr,
+ stream_info->bufq_handle,
+ MSM_ISP_BUFFER_FLUSH_ALL);
+ if (rc == -EFAULT) {
+ msm_isp_halt_send_error(vfe_dev,
+ ISP_EVENT_BUF_FATAL_ERROR);
+ return rc;
+ }
}
return rc;
}
diff --git a/include/media/msmb_isp.h b/include/media/msmb_isp.h
index 1bd0680b86cd..9d6cabd2c8b1 100644
--- a/include/media/msmb_isp.h
+++ b/include/media/msmb_isp.h
@@ -619,7 +619,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
@@ -647,6 +648,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