mirror of https://gitee.com/openkylin/linux.git
[media] coda: rework meta counting and add separate lock
Keep count of number of buffer meta structures in the list and use a separate spinlock for operations on this counted list instead of reusing the bitstream mutex in some places and none at all in others. Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
This commit is contained in:
parent
2cf251c0c3
commit
47f3fa63ee
|
@ -226,6 +226,7 @@ void coda_fill_bitstream(struct coda_ctx *ctx, bool streaming)
|
||||||
{
|
{
|
||||||
struct vb2_buffer *src_buf;
|
struct vb2_buffer *src_buf;
|
||||||
struct coda_buffer_meta *meta;
|
struct coda_buffer_meta *meta;
|
||||||
|
unsigned long flags;
|
||||||
u32 start;
|
u32 start;
|
||||||
|
|
||||||
if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG)
|
if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG)
|
||||||
|
@ -274,8 +275,13 @@ void coda_fill_bitstream(struct coda_ctx *ctx, bool streaming)
|
||||||
meta->start = start;
|
meta->start = start;
|
||||||
meta->end = ctx->bitstream_fifo.kfifo.in &
|
meta->end = ctx->bitstream_fifo.kfifo.in &
|
||||||
ctx->bitstream_fifo.kfifo.mask;
|
ctx->bitstream_fifo.kfifo.mask;
|
||||||
|
spin_lock_irqsave(&ctx->buffer_meta_lock,
|
||||||
|
flags);
|
||||||
list_add_tail(&meta->list,
|
list_add_tail(&meta->list,
|
||||||
&ctx->buffer_meta_list);
|
&ctx->buffer_meta_list);
|
||||||
|
ctx->num_metas++;
|
||||||
|
spin_unlock_irqrestore(&ctx->buffer_meta_lock,
|
||||||
|
flags);
|
||||||
|
|
||||||
trace_coda_bit_queue(ctx, src_buf, meta);
|
trace_coda_bit_queue(ctx, src_buf, meta);
|
||||||
}
|
}
|
||||||
|
@ -1665,6 +1671,7 @@ static int coda_prepare_decode(struct coda_ctx *ctx)
|
||||||
struct coda_dev *dev = ctx->dev;
|
struct coda_dev *dev = ctx->dev;
|
||||||
struct coda_q_data *q_data_dst;
|
struct coda_q_data *q_data_dst;
|
||||||
struct coda_buffer_meta *meta;
|
struct coda_buffer_meta *meta;
|
||||||
|
unsigned long flags;
|
||||||
u32 reg_addr, reg_stride;
|
u32 reg_addr, reg_stride;
|
||||||
|
|
||||||
dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
|
dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
|
||||||
|
@ -1743,6 +1750,7 @@ static int coda_prepare_decode(struct coda_ctx *ctx)
|
||||||
coda_write(dev, ctx->iram_info.axi_sram_use,
|
coda_write(dev, ctx->iram_info.axi_sram_use,
|
||||||
CODA7_REG_BIT_AXI_SRAM_USE);
|
CODA7_REG_BIT_AXI_SRAM_USE);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ctx->buffer_meta_lock, flags);
|
||||||
meta = list_first_entry_or_null(&ctx->buffer_meta_list,
|
meta = list_first_entry_or_null(&ctx->buffer_meta_list,
|
||||||
struct coda_buffer_meta, list);
|
struct coda_buffer_meta, list);
|
||||||
|
|
||||||
|
@ -1762,6 +1770,7 @@ static int coda_prepare_decode(struct coda_ctx *ctx)
|
||||||
kfifo_in(&ctx->bitstream_fifo, buf, pad);
|
kfifo_in(&ctx->bitstream_fifo, buf, pad);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
spin_unlock_irqrestore(&ctx->buffer_meta_lock, flags);
|
||||||
|
|
||||||
coda_kfifo_sync_to_device_full(ctx);
|
coda_kfifo_sync_to_device_full(ctx);
|
||||||
|
|
||||||
|
@ -1783,6 +1792,7 @@ static void coda_finish_decode(struct coda_ctx *ctx)
|
||||||
struct vb2_buffer *dst_buf;
|
struct vb2_buffer *dst_buf;
|
||||||
struct coda_buffer_meta *meta;
|
struct coda_buffer_meta *meta;
|
||||||
unsigned long payload;
|
unsigned long payload;
|
||||||
|
unsigned long flags;
|
||||||
int width, height;
|
int width, height;
|
||||||
int decoded_idx;
|
int decoded_idx;
|
||||||
int display_idx;
|
int display_idx;
|
||||||
|
@ -1908,11 +1918,13 @@ static void coda_finish_decode(struct coda_ctx *ctx)
|
||||||
} else {
|
} else {
|
||||||
val = coda_read(dev, CODA_RET_DEC_PIC_FRAME_NUM) - 1;
|
val = coda_read(dev, CODA_RET_DEC_PIC_FRAME_NUM) - 1;
|
||||||
val -= ctx->sequence_offset;
|
val -= ctx->sequence_offset;
|
||||||
mutex_lock(&ctx->bitstream_mutex);
|
spin_lock_irqsave(&ctx->buffer_meta_lock, flags);
|
||||||
if (!list_empty(&ctx->buffer_meta_list)) {
|
if (!list_empty(&ctx->buffer_meta_list)) {
|
||||||
meta = list_first_entry(&ctx->buffer_meta_list,
|
meta = list_first_entry(&ctx->buffer_meta_list,
|
||||||
struct coda_buffer_meta, list);
|
struct coda_buffer_meta, list);
|
||||||
list_del(&meta->list);
|
list_del(&meta->list);
|
||||||
|
ctx->num_metas--;
|
||||||
|
spin_unlock_irqrestore(&ctx->buffer_meta_lock, flags);
|
||||||
/*
|
/*
|
||||||
* Clamp counters to 16 bits for comparison, as the HW
|
* Clamp counters to 16 bits for comparison, as the HW
|
||||||
* counter rolls over at this point for h.264. This
|
* counter rolls over at this point for h.264. This
|
||||||
|
@ -1929,13 +1941,13 @@ static void coda_finish_decode(struct coda_ctx *ctx)
|
||||||
ctx->frame_metas[decoded_idx] = *meta;
|
ctx->frame_metas[decoded_idx] = *meta;
|
||||||
kfree(meta);
|
kfree(meta);
|
||||||
} else {
|
} else {
|
||||||
|
spin_unlock_irqrestore(&ctx->buffer_meta_lock, flags);
|
||||||
v4l2_err(&dev->v4l2_dev, "empty timestamp list!\n");
|
v4l2_err(&dev->v4l2_dev, "empty timestamp list!\n");
|
||||||
memset(&ctx->frame_metas[decoded_idx], 0,
|
memset(&ctx->frame_metas[decoded_idx], 0,
|
||||||
sizeof(struct coda_buffer_meta));
|
sizeof(struct coda_buffer_meta));
|
||||||
ctx->frame_metas[decoded_idx].sequence = val;
|
ctx->frame_metas[decoded_idx].sequence = val;
|
||||||
ctx->sequence_offset++;
|
ctx->sequence_offset++;
|
||||||
}
|
}
|
||||||
mutex_unlock(&ctx->bitstream_mutex);
|
|
||||||
|
|
||||||
trace_coda_dec_pic_done(ctx, &ctx->frame_metas[decoded_idx]);
|
trace_coda_dec_pic_done(ctx, &ctx->frame_metas[decoded_idx]);
|
||||||
|
|
||||||
|
|
|
@ -908,9 +908,9 @@ static int coda_job_ready(void *m2m_priv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit) {
|
if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit) {
|
||||||
struct list_head *meta;
|
bool stream_end = ctx->bit_stream_param &
|
||||||
bool stream_end;
|
CODA_BIT_STREAM_END_FLAG;
|
||||||
int num_metas;
|
int num_metas = ctx->num_metas;
|
||||||
|
|
||||||
if (ctx->hold && !src_bufs) {
|
if (ctx->hold && !src_bufs) {
|
||||||
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
|
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
|
||||||
|
@ -919,13 +919,6 @@ static int coda_job_ready(void *m2m_priv)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream_end = ctx->bit_stream_param &
|
|
||||||
CODA_BIT_STREAM_END_FLAG;
|
|
||||||
|
|
||||||
num_metas = 0;
|
|
||||||
list_for_each(meta, &ctx->buffer_meta_list)
|
|
||||||
num_metas++;
|
|
||||||
|
|
||||||
if (!stream_end && (num_metas + src_bufs) < 2) {
|
if (!stream_end && (num_metas + src_bufs) < 2) {
|
||||||
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
|
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
|
||||||
"%d: not ready: need 2 buffers available (%d, %d)\n",
|
"%d: not ready: need 2 buffers available (%d, %d)\n",
|
||||||
|
@ -951,6 +944,7 @@ static int coda_job_ready(void *m2m_priv)
|
||||||
|
|
||||||
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
|
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
|
||||||
"job ready\n");
|
"job ready\n");
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1267,6 +1261,7 @@ static void coda_stop_streaming(struct vb2_queue *q)
|
||||||
struct coda_ctx *ctx = vb2_get_drv_priv(q);
|
struct coda_ctx *ctx = vb2_get_drv_priv(q);
|
||||||
struct coda_dev *dev = ctx->dev;
|
struct coda_dev *dev = ctx->dev;
|
||||||
struct vb2_buffer *buf;
|
struct vb2_buffer *buf;
|
||||||
|
unsigned long flags;
|
||||||
bool stop;
|
bool stop;
|
||||||
|
|
||||||
stop = ctx->streamon_out && ctx->streamon_cap;
|
stop = ctx->streamon_out && ctx->streamon_cap;
|
||||||
|
@ -1301,14 +1296,15 @@ static void coda_stop_streaming(struct vb2_queue *q)
|
||||||
queue_work(dev->workqueue, &ctx->seq_end_work);
|
queue_work(dev->workqueue, &ctx->seq_end_work);
|
||||||
flush_work(&ctx->seq_end_work);
|
flush_work(&ctx->seq_end_work);
|
||||||
}
|
}
|
||||||
mutex_lock(&ctx->bitstream_mutex);
|
spin_lock_irqsave(&ctx->buffer_meta_lock, flags);
|
||||||
while (!list_empty(&ctx->buffer_meta_list)) {
|
while (!list_empty(&ctx->buffer_meta_list)) {
|
||||||
meta = list_first_entry(&ctx->buffer_meta_list,
|
meta = list_first_entry(&ctx->buffer_meta_list,
|
||||||
struct coda_buffer_meta, list);
|
struct coda_buffer_meta, list);
|
||||||
list_del(&meta->list);
|
list_del(&meta->list);
|
||||||
kfree(meta);
|
kfree(meta);
|
||||||
}
|
}
|
||||||
mutex_unlock(&ctx->bitstream_mutex);
|
ctx->num_metas = 0;
|
||||||
|
spin_unlock_irqrestore(&ctx->buffer_meta_lock, flags);
|
||||||
kfifo_init(&ctx->bitstream_fifo,
|
kfifo_init(&ctx->bitstream_fifo,
|
||||||
ctx->bitstream.vaddr, ctx->bitstream.size);
|
ctx->bitstream.vaddr, ctx->bitstream.size);
|
||||||
ctx->runcounter = 0;
|
ctx->runcounter = 0;
|
||||||
|
@ -1661,6 +1657,7 @@ static int coda_open(struct file *file)
|
||||||
mutex_init(&ctx->bitstream_mutex);
|
mutex_init(&ctx->bitstream_mutex);
|
||||||
mutex_init(&ctx->buffer_mutex);
|
mutex_init(&ctx->buffer_mutex);
|
||||||
INIT_LIST_HEAD(&ctx->buffer_meta_list);
|
INIT_LIST_HEAD(&ctx->buffer_meta_list);
|
||||||
|
spin_lock_init(&ctx->buffer_meta_lock);
|
||||||
|
|
||||||
coda_lock(ctx);
|
coda_lock(ctx);
|
||||||
list_add(&ctx->list, &dev->instances);
|
list_add(&ctx->list, &dev->instances);
|
||||||
|
|
|
@ -227,6 +227,8 @@ struct coda_ctx {
|
||||||
struct coda_buffer_meta frame_metas[CODA_MAX_FRAMEBUFFERS];
|
struct coda_buffer_meta frame_metas[CODA_MAX_FRAMEBUFFERS];
|
||||||
u32 frame_errors[CODA_MAX_FRAMEBUFFERS];
|
u32 frame_errors[CODA_MAX_FRAMEBUFFERS];
|
||||||
struct list_head buffer_meta_list;
|
struct list_head buffer_meta_list;
|
||||||
|
spinlock_t buffer_meta_lock;
|
||||||
|
int num_metas;
|
||||||
struct coda_aux_buf workbuf;
|
struct coda_aux_buf workbuf;
|
||||||
int num_internal_frames;
|
int num_internal_frames;
|
||||||
int idx;
|
int idx;
|
||||||
|
|
Loading…
Reference in New Issue