Re: [PATCH v3 1/1] mtk-vcodec: check the vp9 decoder buffer index from VPU.

2017-03-07 Thread Tiffany Lin
On Wed, 2017-03-08 at 11:40 +0800, Wu-Cheng Li wrote:
> From: Wu-Cheng Li 
> 
> VPU firmware has a bug and may return invalid buffer index for
> some vp9 videos. Check the buffer indexes before accessing the
> buffer.
> 

Acked-by: Tiffany Lin 

> Signed-off-by: Wu-Cheng Li 
> ---
>  drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c | 33 
> +-
>  drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h |  2 ++
>  .../media/platform/mtk-vcodec/vdec/vdec_vp9_if.c   | 26 +
>  drivers/media/platform/mtk-vcodec/vdec_drv_if.h|  2 ++
>  4 files changed, 56 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c 
> b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
> index 502877a4b1df..a60b538686ea 100644
> --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
> +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
> @@ -420,6 +420,11 @@ static void mtk_vdec_worker(struct work_struct *work)
>   dst_buf->index,
>   ret, res_chg);
>   src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
> + if (ret == -EIO) {
> + mutex_lock(>lock);
> + src_buf_info->error = true;
> + mutex_unlock(>lock);
> + }
>   v4l2_m2m_buf_done(_buf_info->vb, VB2_BUF_STATE_ERROR);
>   } else if (res_chg == false) {
>   /*
> @@ -1170,8 +1175,16 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer 
> *vb)
>*/
>  
>   src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
> - v4l2_m2m_buf_done(to_vb2_v4l2_buffer(src_buf),
> - VB2_BUF_STATE_DONE);
> + if (ret == -EIO) {
> + mtk_v4l2_err("[%d] Unrecoverable error in 
> vdec_if_decode.",
> + ctx->id);
> + ctx->state = MTK_STATE_ABORT;
> + v4l2_m2m_buf_done(to_vb2_v4l2_buffer(src_buf),
> + VB2_BUF_STATE_ERROR);
> + } else {
> + v4l2_m2m_buf_done(to_vb2_v4l2_buffer(src_buf),
> + VB2_BUF_STATE_DONE);
> + }
>   mtk_v4l2_debug(ret ? 0 : 1,
>  "[%d] vdec_if_decode() src_buf=%d, size=%zu, 
> fail=%d, res_chg=%d",
>  ctx->id, src_buf->index,
> @@ -1216,16 +1229,22 @@ static void vb2ops_vdec_buf_finish(struct vb2_buffer 
> *vb)
>   struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
>   struct vb2_v4l2_buffer *vb2_v4l2;
>   struct mtk_video_dec_buf *buf;
> -
> - if (vb->vb2_queue->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
> - return;
> + bool buf_error;
>  
>   vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf);
>   buf = container_of(vb2_v4l2, struct mtk_video_dec_buf, vb);
>   mutex_lock(>lock);
> - buf->queued_in_v4l2 = false;
> - buf->queued_in_vb2 = false;
> + if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
> + buf->queued_in_v4l2 = false;
> + buf->queued_in_vb2 = false;
> + }
> + buf_error = buf->error;
>   mutex_unlock(>lock);
> +
> + if (buf_error) {
> + mtk_v4l2_err("Unrecoverable error on buffer.");
> + ctx->state = MTK_STATE_ABORT;
> + }
>  }
>  
>  static int vb2ops_vdec_buf_init(struct vb2_buffer *vb)
> diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h 
> b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h
> index 362f5a85762e..dc4fc1df63c5 100644
> --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h
> +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h
> @@ -50,6 +50,7 @@ struct vdec_fb {
>   * @queued_in_v4l2:  Capture buffer is in v4l2 driver, but not in vb2
>   *   queue yet
>   * @lastframe:   Intput buffer is last buffer - EOS
> + * @error:   An unrecoverable error occurs on this buffer.
>   * @frame_buffer:Decode status, and buffer information of Capture buffer
>   *
>   * Note : These status information help us track and debug buffer state
> @@ -63,6 +64,7 @@ struct mtk_video_dec_buf {
>   boolqueued_in_vb2;
>   boolqueued_in_v4l2;
>   boollastframe;
> + boolerror;
>   struct vdec_fb  frame_buffer;
>  };
>  
> diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c 
> b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
> index e91a3b425b0c..5539b1853f16 100644
> --- a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
> +++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
> @@ -718,6 +718,26 @@ static void get_free_fb(struct vdec_vp9_inst *inst, 
> struct vdec_fb **out_fb)
>   *out_fb = fb;
>  }
>  
> +static int 

[PATCH v3 1/1] mtk-vcodec: check the vp9 decoder buffer index from VPU.

2017-03-07 Thread Wu-Cheng Li
From: Wu-Cheng Li 

VPU firmware has a bug and may return invalid buffer index for
some vp9 videos. Check the buffer indexes before accessing the
buffer.

Signed-off-by: Wu-Cheng Li 
---
 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c | 33 +-
 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h |  2 ++
 .../media/platform/mtk-vcodec/vdec/vdec_vp9_if.c   | 26 +
 drivers/media/platform/mtk-vcodec/vdec_drv_if.h|  2 ++
 4 files changed, 56 insertions(+), 7 deletions(-)

diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
index 502877a4b1df..a60b538686ea 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
@@ -420,6 +420,11 @@ static void mtk_vdec_worker(struct work_struct *work)
dst_buf->index,
ret, res_chg);
src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+   if (ret == -EIO) {
+   mutex_lock(>lock);
+   src_buf_info->error = true;
+   mutex_unlock(>lock);
+   }
v4l2_m2m_buf_done(_buf_info->vb, VB2_BUF_STATE_ERROR);
} else if (res_chg == false) {
/*
@@ -1170,8 +1175,16 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb)
 */
 
src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
-   v4l2_m2m_buf_done(to_vb2_v4l2_buffer(src_buf),
-   VB2_BUF_STATE_DONE);
+   if (ret == -EIO) {
+   mtk_v4l2_err("[%d] Unrecoverable error in 
vdec_if_decode.",
+   ctx->id);
+   ctx->state = MTK_STATE_ABORT;
+   v4l2_m2m_buf_done(to_vb2_v4l2_buffer(src_buf),
+   VB2_BUF_STATE_ERROR);
+   } else {
+   v4l2_m2m_buf_done(to_vb2_v4l2_buffer(src_buf),
+   VB2_BUF_STATE_DONE);
+   }
mtk_v4l2_debug(ret ? 0 : 1,
   "[%d] vdec_if_decode() src_buf=%d, size=%zu, 
fail=%d, res_chg=%d",
   ctx->id, src_buf->index,
@@ -1216,16 +1229,22 @@ static void vb2ops_vdec_buf_finish(struct vb2_buffer 
*vb)
struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
struct vb2_v4l2_buffer *vb2_v4l2;
struct mtk_video_dec_buf *buf;
-
-   if (vb->vb2_queue->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
-   return;
+   bool buf_error;
 
vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf);
buf = container_of(vb2_v4l2, struct mtk_video_dec_buf, vb);
mutex_lock(>lock);
-   buf->queued_in_v4l2 = false;
-   buf->queued_in_vb2 = false;
+   if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+   buf->queued_in_v4l2 = false;
+   buf->queued_in_vb2 = false;
+   }
+   buf_error = buf->error;
mutex_unlock(>lock);
+
+   if (buf_error) {
+   mtk_v4l2_err("Unrecoverable error on buffer.");
+   ctx->state = MTK_STATE_ABORT;
+   }
 }
 
 static int vb2ops_vdec_buf_init(struct vb2_buffer *vb)
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h
index 362f5a85762e..dc4fc1df63c5 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h
@@ -50,6 +50,7 @@ struct vdec_fb {
  * @queued_in_v4l2:Capture buffer is in v4l2 driver, but not in vb2
  * queue yet
  * @lastframe: Intput buffer is last buffer - EOS
+ * @error: An unrecoverable error occurs on this buffer.
  * @frame_buffer:  Decode status, and buffer information of Capture buffer
  *
  * Note : These status information help us track and debug buffer state
@@ -63,6 +64,7 @@ struct mtk_video_dec_buf {
boolqueued_in_vb2;
boolqueued_in_v4l2;
boollastframe;
+   boolerror;
struct vdec_fb  frame_buffer;
 };
 
diff --git a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c 
b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
index e91a3b425b0c..5539b1853f16 100644
--- a/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
+++ b/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
@@ -718,6 +718,26 @@ static void get_free_fb(struct vdec_vp9_inst *inst, struct 
vdec_fb **out_fb)
*out_fb = fb;
 }
 
+static int validate_vsi_array_indexes(struct vdec_vp9_inst *inst,
+   struct vdec_vp9_vsi *vsi) {
+   if (vsi->sf_frm_idx >= VP9_MAX_FRM_BUF_NUM - 1) {
+   mtk_vcodec_err(inst, "Invalid vsi->sf_frm_idx=%u.",
+