diff options
Diffstat (limited to 'target/linux/bcm27xx/patches-5.4/950-0500-media-v4l2-mem2mem-allow-request-job-buffer-processi.patch')
-rw-r--r-- | target/linux/bcm27xx/patches-5.4/950-0500-media-v4l2-mem2mem-allow-request-job-buffer-processi.patch | 274 |
1 files changed, 0 insertions, 274 deletions
diff --git a/target/linux/bcm27xx/patches-5.4/950-0500-media-v4l2-mem2mem-allow-request-job-buffer-processi.patch b/target/linux/bcm27xx/patches-5.4/950-0500-media-v4l2-mem2mem-allow-request-job-buffer-processi.patch deleted file mode 100644 index b43a4d534a..0000000000 --- a/target/linux/bcm27xx/patches-5.4/950-0500-media-v4l2-mem2mem-allow-request-job-buffer-processi.patch +++ /dev/null @@ -1,274 +0,0 @@ -From b8ae9d55d468a9f55524296247dba93531c29c99 Mon Sep 17 00:00:00 2001 -From: John Cox <jc@kynesim.co.uk> -Date: Thu, 5 Mar 2020 14:46:54 +0000 -Subject: [PATCH] media: v4l2-mem2mem: allow request job buffer - processing after job finish - -Allow the capture buffer to be detached from a v4l2 request job such -that another job can start before the capture buffer is returned. This -allows h/w codecs that can process multiple requests at the same time -to operate more efficiently. - -Signed-off-by: John Cox <jc@kynesim.co.uk> ---- - drivers/media/v4l2-core/v4l2-mem2mem.c | 105 +++++++++++++++++++++++-- - include/media/v4l2-mem2mem.h | 47 +++++++++++ - include/media/videobuf2-v4l2.h | 3 + - 3 files changed, 149 insertions(+), 6 deletions(-) - ---- a/drivers/media/v4l2-core/v4l2-mem2mem.c -+++ b/drivers/media/v4l2-core/v4l2-mem2mem.c -@@ -399,15 +399,18 @@ static void v4l2_m2m_cancel_job(struct v - { - struct v4l2_m2m_dev *m2m_dev; - unsigned long flags; -+ bool det_abort_req; - - m2m_dev = m2m_ctx->m2m_dev; - spin_lock_irqsave(&m2m_dev->job_spinlock, flags); - -+ det_abort_req = !list_empty(&m2m_ctx->det_list); - m2m_ctx->job_flags |= TRANS_ABORT; - if (m2m_ctx->job_flags & TRANS_RUNNING) { - spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); - if (m2m_dev->m2m_ops->job_abort) - m2m_dev->m2m_ops->job_abort(m2m_ctx->priv); -+ det_abort_req = false; - dprintk("m2m_ctx %p running, will wait to complete\n", m2m_ctx); - wait_event(m2m_ctx->finished, - !(m2m_ctx->job_flags & TRANS_RUNNING)); -@@ -421,6 +424,11 @@ static void v4l2_m2m_cancel_job(struct v - /* Do nothing, was not on queue/running */ - spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); - } -+ -+ /* Wait for detached buffers to come back too */ -+ if (det_abort_req && m2m_dev->m2m_ops->job_abort) -+ m2m_dev->m2m_ops->job_abort(m2m_ctx->priv); -+ wait_event(m2m_ctx->det_empty, list_empty(&m2m_ctx->det_list)); - } - - /* -@@ -458,6 +466,7 @@ static bool _v4l2_m2m_job_finish(struct - - list_del(&m2m_dev->curr_ctx->queue); - m2m_dev->curr_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING); -+ m2m_ctx->cap_detached = false; - wake_up(&m2m_dev->curr_ctx->finished); - m2m_dev->curr_ctx = NULL; - return true; -@@ -485,6 +494,80 @@ void v4l2_m2m_job_finish(struct v4l2_m2m - } - EXPORT_SYMBOL(v4l2_m2m_job_finish); - -+struct vb2_v4l2_buffer *_v4l2_m2m_cap_buf_detach(struct v4l2_m2m_ctx *m2m_ctx) -+{ -+ struct vb2_v4l2_buffer *buf; -+ -+ buf = v4l2_m2m_dst_buf_remove(m2m_ctx); -+ list_add_tail(&container_of(buf, struct v4l2_m2m_buffer, vb)->list, -+ &m2m_ctx->det_list); -+ m2m_ctx->cap_detached = true; -+ buf->is_held = true; -+ buf->det_state = VB2_BUF_STATE_ACTIVE; -+ -+ return buf; -+} -+ -+struct vb2_v4l2_buffer *v4l2_m2m_cap_buf_detach(struct v4l2_m2m_dev *m2m_dev, -+ struct v4l2_m2m_ctx *m2m_ctx) -+{ -+ unsigned long flags; -+ struct vb2_v4l2_buffer *src_buf, *dst_buf; -+ -+ spin_lock_irqsave(&m2m_dev->job_spinlock, flags); -+ -+ dst_buf = NULL; -+ src_buf = v4l2_m2m_next_src_buf(m2m_ctx); -+ -+ if (!(src_buf->flags & V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF) && -+ !m2m_ctx->cap_detached) -+ dst_buf = _v4l2_m2m_cap_buf_detach(m2m_ctx); -+ -+ spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); -+ return dst_buf; -+} -+EXPORT_SYMBOL(v4l2_m2m_cap_buf_detach); -+ -+static void _v4l2_m2m_cap_buf_return(struct v4l2_m2m_ctx *m2m_ctx, -+ struct vb2_v4l2_buffer *buf, -+ enum vb2_buffer_state state) -+{ -+ buf->det_state = state; -+ -+ /* -+ * Always signal done in the order we got stuff -+ * Stop if we find a buf that is still in use -+ */ -+ while (!list_empty(&m2m_ctx->det_list)) { -+ buf = &list_first_entry(&m2m_ctx->det_list, -+ struct v4l2_m2m_buffer, list)->vb; -+ state = buf->det_state; -+ if (state != VB2_BUF_STATE_DONE && -+ state != VB2_BUF_STATE_ERROR) -+ return; -+ list_del(&container_of(buf, struct v4l2_m2m_buffer, vb)->list); -+ buf->det_state = VB2_BUF_STATE_DEQUEUED; -+ v4l2_m2m_buf_done(buf, state); -+ } -+ wake_up(&m2m_ctx->det_empty); -+} -+ -+void v4l2_m2m_cap_buf_return(struct v4l2_m2m_dev *m2m_dev, -+ struct v4l2_m2m_ctx *m2m_ctx, -+ struct vb2_v4l2_buffer *buf, -+ enum vb2_buffer_state state) -+{ -+ unsigned long flags; -+ -+ if (!buf) -+ return; -+ -+ spin_lock_irqsave(&m2m_dev->job_spinlock, flags); -+ _v4l2_m2m_cap_buf_return(m2m_ctx, buf, state); -+ spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); -+} -+EXPORT_SYMBOL(v4l2_m2m_cap_buf_return); -+ - void v4l2_m2m_buf_done_and_job_finish(struct v4l2_m2m_dev *m2m_dev, - struct v4l2_m2m_ctx *m2m_ctx, - enum vb2_buffer_state state) -@@ -495,15 +578,23 @@ void v4l2_m2m_buf_done_and_job_finish(st - - spin_lock_irqsave(&m2m_dev->job_spinlock, flags); - src_buf = v4l2_m2m_src_buf_remove(m2m_ctx); -- dst_buf = v4l2_m2m_next_dst_buf(m2m_ctx); - -- if (WARN_ON(!src_buf || !dst_buf)) -+ if (WARN_ON(!src_buf)) - goto unlock; - v4l2_m2m_buf_done(src_buf, state); -- dst_buf->is_held = src_buf->flags & V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF; -- if (!dst_buf->is_held) { -- v4l2_m2m_dst_buf_remove(m2m_ctx); -- v4l2_m2m_buf_done(dst_buf, state); -+ -+ if (!m2m_ctx->cap_detached) { -+ dst_buf = v4l2_m2m_next_dst_buf(m2m_ctx); -+ if (WARN_ON(!dst_buf)) -+ goto unlock; -+ -+ dst_buf->is_held = src_buf->flags -+ & V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF; -+ -+ if (!dst_buf->is_held) { -+ dst_buf = _v4l2_m2m_cap_buf_detach(m2m_ctx); -+ _v4l2_m2m_cap_buf_return(m2m_ctx, dst_buf, state); -+ } - } - schedule_next = _v4l2_m2m_job_finish(m2m_dev, m2m_ctx); - unlock: -@@ -981,12 +1072,14 @@ struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(s - m2m_ctx->priv = drv_priv; - m2m_ctx->m2m_dev = m2m_dev; - init_waitqueue_head(&m2m_ctx->finished); -+ init_waitqueue_head(&m2m_ctx->det_empty); - - out_q_ctx = &m2m_ctx->out_q_ctx; - cap_q_ctx = &m2m_ctx->cap_q_ctx; - - INIT_LIST_HEAD(&out_q_ctx->rdy_queue); - INIT_LIST_HEAD(&cap_q_ctx->rdy_queue); -+ INIT_LIST_HEAD(&m2m_ctx->det_list); - spin_lock_init(&out_q_ctx->rdy_spinlock); - spin_lock_init(&cap_q_ctx->rdy_spinlock); - ---- a/include/media/v4l2-mem2mem.h -+++ b/include/media/v4l2-mem2mem.h -@@ -88,6 +88,9 @@ struct v4l2_m2m_queue_ctx { - * %TRANS_QUEUED, %TRANS_RUNNING and %TRANS_ABORT. - * @finished: Wait queue used to signalize when a job queue finished. - * @priv: Instance private data -+ * @cap_detached: Current job's capture buffer has been detached -+ * @det_list: List of detached (post-job but still in flight) capture buffers -+ * @det_empty: Wait queue signalled when det_list goes empty - * - * The memory to memory context is specific to a file handle, NOT to e.g. - * a device. -@@ -111,6 +114,11 @@ struct v4l2_m2m_ctx { - wait_queue_head_t finished; - - void *priv; -+ -+ /* Detached buffer handling */ -+ bool cap_detached; -+ struct list_head det_list; -+ wait_queue_head_t det_empty; - }; - - /** -@@ -216,6 +224,45 @@ v4l2_m2m_buf_done(struct vb2_v4l2_buffer - } - - /** -+ * v4l2_m2m_cap_buf_detach() - detach the capture buffer from the job and -+ * return it. -+ * -+ * @m2m_dev: opaque pointer to the internal data to handle M2M context -+ * @m2m_ctx: m2m context assigned to the instance given by struct &v4l2_m2m_ctx -+ * -+ * This function is designed to be used in conjunction with -+ * v4l2_m2m_buf_done_and_job_finish(). It allows the next job to start -+ * execution before the capture buffer is returned to the user which can be -+ * important if the underlying processing has multiple phases that are more -+ * efficiently executed in parallel. -+ * -+ * If used then it must be called before v4l2_m2m_buf_done_and_job_finish() -+ * as otherwise the buffer will have already gone. -+ * -+ * It is the callers reponsibilty to ensure that all detached buffers are -+ * returned. -+ */ -+struct vb2_v4l2_buffer *v4l2_m2m_cap_buf_detach(struct v4l2_m2m_dev *m2m_dev, -+ struct v4l2_m2m_ctx *m2m_ctx); -+ -+/** -+ * v4l2_m2m_cap_buf_return() - return a capture buffer, previously detached -+ * with v4l2_m2m_cap_buf_detach() to the user. -+ * -+ * @m2m_dev: opaque pointer to the internal data to handle M2M context -+ * @m2m_ctx: m2m context assigned to the instance given by struct &v4l2_m2m_ctx -+ * @buf: the buffer to return -+ * @state: vb2 buffer state passed to v4l2_m2m_buf_done(). -+ * -+ * Buffers returned by this function will be returned to the user in the order -+ * of the original jobs rather than the order in which this function is called. -+ */ -+void v4l2_m2m_cap_buf_return(struct v4l2_m2m_dev *m2m_dev, -+ struct v4l2_m2m_ctx *m2m_ctx, -+ struct vb2_v4l2_buffer *buf, -+ enum vb2_buffer_state state); -+ -+/** - * v4l2_m2m_reqbufs() - multi-queue-aware REQBUFS multiplexer - * - * @file: pointer to struct &file ---- a/include/media/videobuf2-v4l2.h -+++ b/include/media/videobuf2-v4l2.h -@@ -35,6 +35,8 @@ - * @request_fd: the request_fd associated with this buffer - * @is_held: if true, then this capture buffer was held - * @planes: plane information (userptr/fd, length, bytesused, data_offset). -+ * @det_state: if a detached request capture buffer then this contains its -+ * current state - * - * Should contain enough information to be able to cover all the fields - * of &struct v4l2_buffer at ``videodev2.h``. -@@ -49,6 +51,7 @@ struct vb2_v4l2_buffer { - __s32 request_fd; - bool is_held; - struct vb2_plane planes[VB2_MAX_PLANES]; -+ enum vb2_buffer_state det_state; - }; - - /* VB2 V4L2 flags as set in vb2_queue.subsystem_flags */ |