[PATCH] media: coda: avoid starvation on well-compressed data

From: Benjamin Bara - SKIDATA
Date: Fri Aug 21 2020 - 08:06:14 EST


The prefetcher requires two 256 byte periods beyond the current one.
However, currently it is only checked if there are at least 512 bytes
beyond the current meta available.
This only works under the assumption that every buffer has a size of
at least 256 bytes.

To ensure that the requirement is fulfilled with buffers < 256 bytes,
the queue head and the queue tail must not be below this threshold.
Otherwise, additional buffers are enqueued to ensure a full window.

Signed-off-by: Benjamin Bara <benjamin.bara@xxxxxxxxxxx>
---
drivers/media/platform/coda/coda-bit.c | 8 ++++++--
drivers/media/platform/coda/coda.h | 1 +
2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c
index b021604eceaa..8158f3b34b36 100644
--- a/drivers/media/platform/coda/coda-bit.c
+++ b/drivers/media/platform/coda/coda-bit.c
@@ -323,7 +323,7 @@ static bool coda_bitstream_try_queue(struct coda_ctx *ctx,
void coda_fill_bitstream(struct coda_ctx *ctx, struct list_head *buffer_list)
{
struct vb2_v4l2_buffer *src_buf;
- struct coda_buffer_meta *meta;
+ struct coda_buffer_meta *meta, *last_meta;
u32 start;

if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG)
@@ -343,6 +343,8 @@ void coda_fill_bitstream(struct coda_ctx *ctx, struct list_head *buffer_list)
ctx->num_metas >= ctx->num_internal_frames) {
meta = list_first_entry(&ctx->buffer_meta_list,
struct coda_buffer_meta, list);
+ last_meta = list_last_entry(&ctx->buffer_meta_list,
+ struct coda_buffer_meta, list);

/*
* If we managed to fill in at least a full reorder
@@ -352,7 +354,8 @@ void coda_fill_bitstream(struct coda_ctx *ctx, struct list_head *buffer_list)
* the first buffer to fetch, we can safely stop queuing
* in order to limit the decoder drain latency.
*/
- if (coda_bitstream_can_fetch_past(ctx, meta->end))
+ if (!meta->below_threshold && !last_meta->below_threshold &&
+ coda_bitstream_can_fetch_past(ctx, meta->end))
break;
}

@@ -403,6 +406,7 @@ void coda_fill_bitstream(struct coda_ctx *ctx, struct list_head *buffer_list)
meta->start = start;
meta->end = ctx->bitstream_fifo.kfifo.in;
meta->last = src_buf->flags & V4L2_BUF_FLAG_LAST;
+ meta->below_threshold = (meta->end - meta->start) < 256;
if (meta->last)
coda_dbg(1, ctx, "marking last meta");
spin_lock(&ctx->buffer_meta_lock);
diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h
index b81f3aca9209..6f77553e81b8 100644
--- a/drivers/media/platform/coda/coda.h
+++ b/drivers/media/platform/coda/coda.h
@@ -160,6 +160,7 @@ struct coda_buffer_meta {
unsigned int start;
unsigned int end;
bool last;
+ bool below_threshold;
};

/* Per-queue, driver-specific private data */
--
2.25.1