On 21/05/2020 19:11, Tomasz Figa wrote: > Hi Jerry, > > On Wed, Dec 04, 2019 at 08:47:29PM +0800, Jerry-ch Chen wrote: >> From: Pi-Hsun Shih <pihsun@xxxxxxxxxxxx> >> >> Add two functions that can be used to stop new jobs from being queued / >> continue running queued job. This can be used while a driver using m2m >> helper is going to suspend / wake up from resume, and can ensure that >> there's no job running in suspend process. >> >> BUG=b:143046833 >> TEST=build >> >> Signed-off-by: Pi-Hsun Shih <pihsun@xxxxxxxxxxxx> >> Signed-off-by: Jerry-ch Chen <jerry-ch.chen@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx> >> --- >> drivers/media/v4l2-core/v4l2-mem2mem.c | 40 ++++++++++++++++++++++++++ >> include/media/v4l2-mem2mem.h | 22 ++++++++++++++ >> 2 files changed, 62 insertions(+) >> >> diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c >> index 5bbdec55b7d7..76ba203e0035 100644 >> --- a/drivers/media/v4l2-core/v4l2-mem2mem.c >> +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c >> @@ -47,6 +47,10 @@ module_param(debug, bool, 0644); >> #define TRANS_ABORT (1 << 2) >> >> >> +/* The job queue is not running new jobs */ >> +#define QUEUE_PAUSED (1 << 0) >> + >> + >> /* Offset base for buffers on the destination queue - used to distinguish >> * between source and destination buffers when mmapping - they receive the same >> * offsets but for different queues */ >> @@ -88,6 +92,7 @@ static const char * const m2m_entity_name[] = { >> * @job_queue: instances queued to run >> * @job_spinlock: protects job_queue >> * @job_work: worker to run queued jobs. >> + * @job_queue_flags: flags of the queue status, %QUEUE_PAUSED. >> * @m2m_ops: driver callbacks >> */ >> struct v4l2_m2m_dev { >> @@ -105,6 +110,7 @@ struct v4l2_m2m_dev { >> struct list_head job_queue; >> spinlock_t job_spinlock; >> struct work_struct job_work; >> + unsigned long job_queue_flags; >> >> const struct v4l2_m2m_ops *m2m_ops; >> }; >> @@ -267,6 +273,12 @@ static void v4l2_m2m_try_run(struct v4l2_m2m_dev *m2m_dev) >> return; >> } >> >> + if (m2m_dev->job_queue_flags & QUEUE_PAUSED) { >> + spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); >> + dprintk("Running new jobs is paused\n"); >> + return; >> + } >> + >> m2m_dev->curr_ctx = list_first_entry(&m2m_dev->job_queue, >> struct v4l2_m2m_ctx, queue); >> m2m_dev->curr_ctx->job_flags |= TRANS_RUNNING; >> @@ -447,6 +459,34 @@ void v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev, >> } >> EXPORT_SYMBOL(v4l2_m2m_job_finish); >> >> +void v4l2_m2m_suspend(struct v4l2_m2m_dev *m2m_dev) >> +{ >> + unsigned long flags; >> + struct v4l2_m2m_ctx *curr_ctx; >> + >> + spin_lock_irqsave(&m2m_dev->job_spinlock, flags); >> + m2m_dev->job_queue_flags |= QUEUE_PAUSED; >> + curr_ctx = m2m_dev->curr_ctx; >> + spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); >> + >> + if (curr_ctx) >> + wait_event(curr_ctx->finished, >> + !(curr_ctx->job_flags & TRANS_RUNNING)); >> +} >> +EXPORT_SYMBOL(v4l2_m2m_suspend); >> + >> +void v4l2_m2m_resume(struct v4l2_m2m_dev *m2m_dev) >> +{ >> + unsigned long flags; >> + >> + spin_lock_irqsave(&m2m_dev->job_spinlock, flags); >> + m2m_dev->job_queue_flags &= ~QUEUE_PAUSED; >> + spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags); >> + >> + v4l2_m2m_try_run(m2m_dev); >> +} >> +EXPORT_SYMBOL(v4l2_m2m_resume); >> + >> int v4l2_m2m_reqbufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx, >> struct v4l2_requestbuffers *reqbufs) >> { >> diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h >> index 5467264771ec..119a195da390 100644 >> --- a/include/media/v4l2-mem2mem.h >> +++ b/include/media/v4l2-mem2mem.h >> @@ -183,6 +183,28 @@ v4l2_m2m_buf_done(struct vb2_v4l2_buffer *buf, enum vb2_buffer_state state) >> vb2_buffer_done(&buf->vb2_buf, state); >> } >> >> +/** >> + * v4l2_m2m_suspend() - stop new jobs from being run and wait for current job >> + * to finish >> + * >> + * @m2m_dev: opaque pointer to the internal data to handle M2M context >> + * >> + * Called by a driver in the suspend hook. Stop new jobs from being run, and >> + * wait for current running job to finish. >> + */ >> +void v4l2_m2m_suspend(struct v4l2_m2m_dev *m2m_dev); >> + >> +/** >> + * v4l2_m2m_resume() - resume job running and try to run a queued job >> + * >> + * @m2m_dev: opaque pointer to the internal data to handle M2M context >> + * >> + * Called by a driver in the resume hook. This reverts the operation of >> + * v4l2_m2m_suspend() and allows job to be run. Also try to run a queued job if >> + * there is any. >> + */ >> +void v4l2_m2m_resume(struct v4l2_m2m_dev *m2m_dev); >> + >> /** >> * v4l2_m2m_reqbufs() - multi-queue-aware REQBUFS multiplexer >> * >> -- >> 2.18.0 > > Reviewed-by: Tomasz Figa <tfiga@xxxxxxxxxxxx> > > [Corrected Hans's email address.] > Hans, does this look good to you? Yes, this looks good. Sorry for the late reply. I assume this will be part of a future patch series that calls these new functions? Regards, Hans