From 38f25a09d4bf36ba4ca183cf8d9425f61c969764 Mon Sep 17 00:00:00 2001 From: Jeonghee Kim Date: Thu, 8 Mar 2018 18:31:09 +0900 Subject: [PATCH] media: mfc: Fix the reference count pair. When decoding and display status, the release information of the referenced buffers without display should not be updated. It will be reused. When decoding only status, the release information of the referenced buffers(except for reused buffer) should be left to update when displayed. It is an already displayed buffer. Change-Id: I37df2bfd9d6cd3defde26edf1f2ac46ebb42ae8e Signed-off-by: Jeonghee Kim --- .../media/platform/exynos/mfc/s5p_mfc_irq.c | 8 +++- .../media/platform/exynos/mfc/s5p_mfc_nal_q.c | 5 +- .../media/platform/exynos/mfc/s5p_mfc_queue.c | 46 +++++++++++++++++-- .../media/platform/exynos/mfc/s5p_mfc_queue.h | 2 +- 4 files changed, 52 insertions(+), 9 deletions(-) diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_irq.c b/drivers/media/platform/exynos/mfc/s5p_mfc_irq.c index e6237215a735..4843b02b8908 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_irq.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_irq.c @@ -508,10 +508,14 @@ static void mfc_handle_reuse_buffer(struct s5p_mfc_ctx *ctx) if (!released_flag) return; - /* reuse not referenced buf anymore */ + /* Reuse not referenced buf anymore */ for (i = 0; i < MFC_MAX_DPBS; i++) if (released_flag & (1 << i)) - s5p_mfc_move_reuse_buffer(ctx, i); + if (s5p_mfc_move_reuse_buffer(ctx, i)) + released_flag &= ~(1 << i); + + /* Not reused buffer should be released when there is a display frame */ + dec->dynamic_used |= released_flag; } static void mfc_handle_frame_input(struct s5p_mfc_ctx *ctx, unsigned int err) diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.c b/drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.c index 0124bf551faf..821815e01ee6 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.c @@ -1058,8 +1058,11 @@ static void mfc_nal_q_handle_reuse_buffer(struct s5p_mfc_ctx *ctx, DecoderOutput for (i = 0; i < MFC_MAX_DPBS; i++) if (released_flag & (1 << i)) - s5p_mfc_move_reuse_buffer(ctx, i); + if (s5p_mfc_move_reuse_buffer(ctx, i)) + released_flag &= ~(1 << i); + /* Not reused buffer should be released when there is a display frame */ + dec->dynamic_used |= released_flag; } static void mfc_nal_q_handle_ref_frame(struct s5p_mfc_ctx *ctx, DecoderOutputStr *pOutStr) diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_queue.c b/drivers/media/platform/exynos/mfc/s5p_mfc_queue.c index 6acc904bda19..9e701ca60d76 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_queue.c +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_queue.c @@ -581,10 +581,33 @@ static void mfc_cleanup_batch_queue(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf_ spin_unlock_irqrestore(&ctx->buf_queue_lock, flags); } +struct s5p_mfc_buf *mfc_find_buf_index(spinlock_t *plock, struct s5p_mfc_buf_queue *queue, + int index) +{ + unsigned long flags; + struct s5p_mfc_buf *mfc_buf = NULL; + int buf_index; + + spin_lock_irqsave(plock, flags); + + mfc_debug(2, "Looking for index: %d\n", index); + list_for_each_entry(mfc_buf, &queue->head, list) { + buf_index = mfc_buf->vb.vb2_buf.index; + + if (index == buf_index) { + mfc_debug(2, "Found index: %d\n", buf_index); + spin_unlock_irqrestore(plock, flags); + return mfc_buf; + } + } + + spin_unlock_irqrestore(plock, flags); + return NULL; +} + /* - * Check released buffers are enqueued again. - * s5p_mfc_dec.assigned_fd - * s5p_mfc_dec.available_dpb + * Check released and enqueued buffers. (dst queue) + * Check and move reuse buffers. (ref -> dst queue) */ static void mfc_check_ref_frame(spinlock_t *plock, struct s5p_mfc_buf_queue *dst_queue, struct s5p_mfc_buf_queue *ref_queue, @@ -598,6 +621,7 @@ static void mfc_check_ref_frame(spinlock_t *plock, struct s5p_mfc_buf_queue *dst spin_lock_irqsave(plock, flags); + /* reuse buffers : error frame, decoding only frame (ref -> dst queue) */ list_for_each_entry_safe(ref_mb, tmp_mb, &ref_queue->head, list) { index = ref_mb->vb.vb2_buf.index; if (index == ref_index) { @@ -617,6 +641,7 @@ static void mfc_check_ref_frame(spinlock_t *plock, struct s5p_mfc_buf_queue *dst } } + /* released and enqueued buffers (dst queue) */ if (!found) { list_for_each_entry_safe(ref_mb, tmp_mb, &dst_queue->head, list) { index = ref_mb->vb.vb2_buf.index; @@ -653,10 +678,17 @@ void s5p_mfc_handle_released_info(struct s5p_mfc_ctx *ctx, for (t = 0; t < MFC_MAX_DPBS; t++) { if (released_flag & (1 << t)) { if (dec->err_reuse_flag & (1 << t)) { - mfc_debug(2, "Released, but reuse. FD[%d] = %03d\n", + /* reuse buffer with error : do not update released info */ + mfc_debug(2, "Released, but reuse(error frame). FD[%d] = %03d\n", t, dec->assigned_fd[t]); dec->err_reuse_flag &= ~(1 << t); + } else if ((t != index) && + mfc_find_buf_index(&ctx->buf_queue_lock, &ctx->ref_buf_queue, t)) { + /* decoding only frame: do not update released info */ + mfc_debug(2, "Released, but reuse(decoding only). FD[%d] = %03d\n", + t, dec->assigned_fd[t]); } else { + /* displayed and released frame */ mfc_debug(2, "Release FD[%d] = %03d\n", t, dec->assigned_fd[t]); refBuf->dpb[ncount].fd[0] = dec->assigned_fd[t]; @@ -673,7 +705,7 @@ void s5p_mfc_handle_released_info(struct s5p_mfc_ctx *ctx, refBuf->dpb[ncount].fd[0] = MFC_INFO_INIT_FD; } -void s5p_mfc_move_reuse_buffer(struct s5p_mfc_ctx *ctx, int release_index) +struct s5p_mfc_buf *s5p_mfc_move_reuse_buffer(struct s5p_mfc_ctx *ctx, int release_index) { struct s5p_mfc_dec *dec = ctx->dec_priv; struct s5p_mfc_buf_queue *dst_queue = &ctx->dst_buf_queue; @@ -700,10 +732,14 @@ void s5p_mfc_move_reuse_buffer(struct s5p_mfc_ctx *ctx, int release_index) clear_bit(index, &dec->available_dpb); mfc_debug(2, "buffer[%d] is moved to dst queue for reuse\n", index); + + spin_unlock_irqrestore(plock, flags); + return ref_mb; } } spin_unlock_irqrestore(plock, flags); + return NULL; } void s5p_mfc_cleanup_enc_src_queue(struct s5p_mfc_ctx *ctx) diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_queue.h b/drivers/media/platform/exynos/mfc/s5p_mfc_queue.h index 3432f806e429..ac7782e8bef1 100644 --- a/drivers/media/platform/exynos/mfc/s5p_mfc_queue.h +++ b/drivers/media/platform/exynos/mfc/s5p_mfc_queue.h @@ -145,7 +145,7 @@ void s5p_mfc_cleanup_queue(spinlock_t *plock, struct s5p_mfc_buf_queue *queue); void s5p_mfc_handle_released_info(struct s5p_mfc_ctx *ctx, unsigned int released_flag, int index); -void s5p_mfc_move_reuse_buffer(struct s5p_mfc_ctx *ctx, int release_index); +struct s5p_mfc_buf *s5p_mfc_move_reuse_buffer(struct s5p_mfc_ctx *ctx, int release_index); void s5p_mfc_cleanup_enc_src_queue(struct s5p_mfc_ctx *ctx); void s5p_mfc_cleanup_enc_dst_queue(struct s5p_mfc_ctx *ctx); -- 2.20.1