Re: [PATCH v2 3/5] [media] exynos-mscl: Add m2m functionality for the M-Scaler driver

2013-09-11 Thread Sylwester Nawrocki
Hi Shaik,

On 09/10/2013 02:37 PM, Shaik Ameer Basha wrote:
> Hi Sylwester,
> 
> Almost all of the comments are already addressed.
> Will try to post the v3 by tomorrow.
> 
> I have one doubt?
> Do I need to rebase this driver on m2m-helpers-v2 or once the driver
> is merged we can take this up?

Sorry, I didn't even post an RFC for those helpers, I'll try to do it
today. Nevertheless this is something that isn't yet in mainline nor
in any stable branch, so don't worry about it. It can be handled easily
by a follow up patch, it would be mostly code deletion anyway.

--
Regards,
Sylwester
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 3/5] [media] exynos-mscl: Add m2m functionality for the M-Scaler driver

2013-09-10 Thread Shaik Ameer Basha
Hi Sylwester,

Almost all of the comments are already addressed.
Will try to post the v3 by tomorrow.

I have one doubt?
Do I need to rebase this driver on m2m-helpers-v2 or once the driver
is merged we can take this up?

Regards,
Shaik Ameer Basha


On Thu, Aug 29, 2013 at 6:51 PM, Sylwester Nawrocki
 wrote:
> On 08/19/2013 12:58 PM, Shaik Ameer Basha wrote:
>> This patch adds the memory to memory (m2m) interface functionality
>> for the M-Scaler driver.
>>
>> Signed-off-by: Shaik Ameer Basha 
>> ---
>>  drivers/media/platform/exynos-mscl/mscl-m2m.c |  763 
>> +
>>  1 file changed, 763 insertions(+)
>>  create mode 100644 drivers/media/platform/exynos-mscl/mscl-m2m.c
>>
>> diff --git a/drivers/media/platform/exynos-mscl/mscl-m2m.c 
>> b/drivers/media/platform/exynos-mscl/mscl-m2m.c
>> new file mode 100644
>> index 000..fecbb57
>> --- /dev/null
>> +++ b/drivers/media/platform/exynos-mscl/mscl-m2m.c
>> @@ -0,0 +1,763 @@
>> +/*
>> + * Copyright (c) 2013 - 2014 Samsung Electronics Co., Ltd.
>
> 2013 - 2014 ??
>
>> + *   http://www.samsung.com
>> + *
>> + * Samsung EXYNOS5 SoC series M-Scaler driver
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published
>> + * by the Free Software Foundation, either version 2 of the License,
>> + * or (at your option) any later version.
>> + */
>> +
>> +#include 
>> +#include 
>> +#include 
>> +
>> +#include 
>> +
>> +#include "mscl-core.h"
>> +
>> +static int mscl_m2m_ctx_stop_req(struct mscl_ctx *ctx)
>> +{
>> + struct mscl_ctx *curr_ctx;
>> + struct mscl_dev *mscl = ctx->mscl_dev;
>> + int ret;
>> +
>> + curr_ctx = v4l2_m2m_get_curr_priv(mscl->m2m.m2m_dev);
>> + if (!mscl_m2m_pending(mscl) || (curr_ctx != ctx))
>> + return 0;
>> +
>> + mscl_ctx_state_lock_set(MSCL_CTX_STOP_REQ, ctx);
>> + ret = wait_event_timeout(mscl->irq_queue,
>> + !mscl_ctx_state_is_set(MSCL_CTX_STOP_REQ, ctx),
>> + MSCL_SHUTDOWN_TIMEOUT);
>> +
>> + return ret == 0 ? -ETIMEDOUT : ret;
>> +}
>> +
>> +static int mscl_m2m_start_streaming(struct vb2_queue *q, unsigned int count)
>> +{
>> + struct mscl_ctx *ctx = q->drv_priv;
>> + int ret;
>> +
>> + ret = pm_runtime_get_sync(&ctx->mscl_dev->pdev->dev);
>> +
>> + return ret > 0 ? 0 : ret;
>> +}
>> +
>> +static int mscl_m2m_stop_streaming(struct vb2_queue *q)
>> +{
>> + struct mscl_ctx *ctx = q->drv_priv;
>> + int ret;
>> +
>> + ret = mscl_m2m_ctx_stop_req(ctx);
>> + if (ret == -ETIMEDOUT)
>> + mscl_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
>> +
>> + pm_runtime_put(&ctx->mscl_dev->pdev->dev);
>> +
>> + return 0;
>> +}
>> +
>> +void mscl_m2m_job_finish(struct mscl_ctx *ctx, int vb_state)
>> +{
>> + struct vb2_buffer *src_vb, *dst_vb;
>> +
>> + if (!ctx || !ctx->m2m_ctx)
>> + return;
>> +
>> + src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
>> + dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
>> +
>> + if (src_vb && dst_vb) {
>> + v4l2_m2m_buf_done(src_vb, vb_state);
>> + v4l2_m2m_buf_done(dst_vb, vb_state);
>> +
>> + v4l2_m2m_job_finish(ctx->mscl_dev->m2m.m2m_dev,
>> + ctx->m2m_ctx);
>> + }
>> +}
>> +
>> +
>
> Stray empty line.
>
>> +static void mscl_m2m_job_abort(void *priv)
>> +{
>> + struct mscl_ctx *ctx = priv;
>> + int ret;
>> +
>> + ret = mscl_m2m_ctx_stop_req(ctx);
>> + if (ret == -ETIMEDOUT)
>> + mscl_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
>> +}
>> +
>> +static int mscl_get_bufs(struct mscl_ctx *ctx)
>> +{
>> + struct mscl_frame *s_frame, *d_frame;
>> + struct vb2_buffer *src_vb, *dst_vb;
>> + int ret;
>> +
>> + s_frame = &ctx->s_frame;
>> + d_frame = &ctx->d_frame;
>> +
>> + src_vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
>> + ret = mscl_prepare_addr(ctx, src_vb, s_frame, &s_frame->addr);
>> + if (ret)
>
> How about using "if (ret < 0)" pattern consistently ?
>
>> + return ret;
>> +
>> + dst_vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
>> + ret = mscl_prepare_addr(ctx, dst_vb, d_frame, &d_frame->addr);
>> + if (ret)
>> + return ret;
>> +
>> + dst_vb->v4l2_buf.timestamp = src_vb->v4l2_buf.timestamp;
>> +
>> + return 0;
>> +}
>> +
>> +static void mscl_m2m_device_run(void *priv)
>> +{
>> + struct mscl_ctx *ctx = priv;
>> + struct mscl_dev *mscl;
>> + unsigned long flags;
>> + int ret;
>> + bool is_set = false;
>
> Unneeded initialization. And I can see a room for improvement WRT
> the variable's name.
>
>> +
>> + if (WARN(!ctx, "null hardware context\n"))
>> + return;
>> +
>> + mscl = ctx->mscl_dev;
>> + spin_lock_irqsave(&mscl->slock, flags);
>> +
>> + set_bit(ST_M2M_PEND, &mscl->state);
>> +
>> + /* Reconfigure h

Re: [PATCH v2 3/5] [media] exynos-mscl: Add m2m functionality for the M-Scaler driver

2013-08-29 Thread Sylwester Nawrocki
On 08/19/2013 12:58 PM, Shaik Ameer Basha wrote:
> This patch adds the memory to memory (m2m) interface functionality
> for the M-Scaler driver.
> 
> Signed-off-by: Shaik Ameer Basha 
> ---
>  drivers/media/platform/exynos-mscl/mscl-m2m.c |  763 
> +
>  1 file changed, 763 insertions(+)
>  create mode 100644 drivers/media/platform/exynos-mscl/mscl-m2m.c
> 
> diff --git a/drivers/media/platform/exynos-mscl/mscl-m2m.c 
> b/drivers/media/platform/exynos-mscl/mscl-m2m.c
> new file mode 100644
> index 000..fecbb57
> --- /dev/null
> +++ b/drivers/media/platform/exynos-mscl/mscl-m2m.c
> @@ -0,0 +1,763 @@
> +/*
> + * Copyright (c) 2013 - 2014 Samsung Electronics Co., Ltd.

2013 - 2014 ??

> + *   http://www.samsung.com
> + *
> + * Samsung EXYNOS5 SoC series M-Scaler driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published
> + * by the Free Software Foundation, either version 2 of the License,
> + * or (at your option) any later version.
> + */
> +
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +
> +#include "mscl-core.h"
> +
> +static int mscl_m2m_ctx_stop_req(struct mscl_ctx *ctx)
> +{
> + struct mscl_ctx *curr_ctx;
> + struct mscl_dev *mscl = ctx->mscl_dev;
> + int ret;
> +
> + curr_ctx = v4l2_m2m_get_curr_priv(mscl->m2m.m2m_dev);
> + if (!mscl_m2m_pending(mscl) || (curr_ctx != ctx))
> + return 0;
> +
> + mscl_ctx_state_lock_set(MSCL_CTX_STOP_REQ, ctx);
> + ret = wait_event_timeout(mscl->irq_queue,
> + !mscl_ctx_state_is_set(MSCL_CTX_STOP_REQ, ctx),
> + MSCL_SHUTDOWN_TIMEOUT);
> +
> + return ret == 0 ? -ETIMEDOUT : ret;
> +}
> +
> +static int mscl_m2m_start_streaming(struct vb2_queue *q, unsigned int count)
> +{
> + struct mscl_ctx *ctx = q->drv_priv;
> + int ret;
> +
> + ret = pm_runtime_get_sync(&ctx->mscl_dev->pdev->dev);
> +
> + return ret > 0 ? 0 : ret;
> +}
> +
> +static int mscl_m2m_stop_streaming(struct vb2_queue *q)
> +{
> + struct mscl_ctx *ctx = q->drv_priv;
> + int ret;
> +
> + ret = mscl_m2m_ctx_stop_req(ctx);
> + if (ret == -ETIMEDOUT)
> + mscl_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
> +
> + pm_runtime_put(&ctx->mscl_dev->pdev->dev);
> +
> + return 0;
> +}
> +
> +void mscl_m2m_job_finish(struct mscl_ctx *ctx, int vb_state)
> +{
> + struct vb2_buffer *src_vb, *dst_vb;
> +
> + if (!ctx || !ctx->m2m_ctx)
> + return;
> +
> + src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
> + dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
> +
> + if (src_vb && dst_vb) {
> + v4l2_m2m_buf_done(src_vb, vb_state);
> + v4l2_m2m_buf_done(dst_vb, vb_state);
> +
> + v4l2_m2m_job_finish(ctx->mscl_dev->m2m.m2m_dev,
> + ctx->m2m_ctx);
> + }
> +}
> +
> +

Stray empty line.

> +static void mscl_m2m_job_abort(void *priv)
> +{
> + struct mscl_ctx *ctx = priv;
> + int ret;
> +
> + ret = mscl_m2m_ctx_stop_req(ctx);
> + if (ret == -ETIMEDOUT)
> + mscl_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
> +}
> +
> +static int mscl_get_bufs(struct mscl_ctx *ctx)
> +{
> + struct mscl_frame *s_frame, *d_frame;
> + struct vb2_buffer *src_vb, *dst_vb;
> + int ret;
> +
> + s_frame = &ctx->s_frame;
> + d_frame = &ctx->d_frame;
> +
> + src_vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
> + ret = mscl_prepare_addr(ctx, src_vb, s_frame, &s_frame->addr);
> + if (ret)

How about using "if (ret < 0)" pattern consistently ?

> + return ret;
> +
> + dst_vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
> + ret = mscl_prepare_addr(ctx, dst_vb, d_frame, &d_frame->addr);
> + if (ret)
> + return ret;
> +
> + dst_vb->v4l2_buf.timestamp = src_vb->v4l2_buf.timestamp;
> +
> + return 0;
> +}
> +
> +static void mscl_m2m_device_run(void *priv)
> +{
> + struct mscl_ctx *ctx = priv;
> + struct mscl_dev *mscl;
> + unsigned long flags;
> + int ret;
> + bool is_set = false;

Unneeded initialization. And I can see a room for improvement WRT
the variable's name.

> +
> + if (WARN(!ctx, "null hardware context\n"))
> + return;
> +
> + mscl = ctx->mscl_dev;
> + spin_lock_irqsave(&mscl->slock, flags);
> +
> + set_bit(ST_M2M_PEND, &mscl->state);
> +
> + /* Reconfigure hardware if the context has changed. */
> + if (mscl->m2m.ctx != ctx) {
> + dev_dbg(&mscl->pdev->dev,
> + "mscl->m2m.ctx = 0x%p, current_ctx = 0x%p",
> + mscl->m2m.ctx, ctx);
> + ctx->state |= MSCL_PARAMS;
> + mscl->m2m.ctx = ctx;
> + }
> +
> + is_set = (ctx->state & MSCL_CTX_STOP_REQ) ? 1 : 0;

Just make it

is_set = ctx->state & MSCL_CTX_STOP_REQ;

> + ctx->state &= ~MSCL_CTX

Re: [PATCH v2 3/5] [media] exynos-mscl: Add m2m functionality for the M-Scaler driver

2013-08-19 Thread Hans Verkuil
On 08/19/2013 02:58 PM, Hans Verkuil wrote:
> On 08/19/2013 12:58 PM, Shaik Ameer Basha wrote:
>> This patch adds the memory to memory (m2m) interface functionality
>> for the M-Scaler driver.
> 
> Just one small comment below...
> 
>>
>> Signed-off-by: Shaik Ameer Basha 
>> ---
>>  drivers/media/platform/exynos-mscl/mscl-m2m.c |  763 
>> +
>>  1 file changed, 763 insertions(+)
>>  create mode 100644 drivers/media/platform/exynos-mscl/mscl-m2m.c
>>
>> diff --git a/drivers/media/platform/exynos-mscl/mscl-m2m.c 
>> b/drivers/media/platform/exynos-mscl/mscl-m2m.c
>> new file mode 100644
>> index 000..fecbb57
>> --- /dev/null
>> +++ b/drivers/media/platform/exynos-mscl/mscl-m2m.c
>> @@ -0,0 +1,763 @@
>> +/*
>> + * Copyright (c) 2013 - 2014 Samsung Electronics Co., Ltd.
>> + *  http://www.samsung.com
>> + *
>> + * Samsung EXYNOS5 SoC series M-Scaler driver
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published
>> + * by the Free Software Foundation, either version 2 of the License,
>> + * or (at your option) any later version.
>> + */
>> +
>> +#include 
>> +#include 
>> +#include 
>> +
>> +#include 
>> +
>> +#include "mscl-core.h"
>> +
>> +static int mscl_m2m_ctx_stop_req(struct mscl_ctx *ctx)
>> +{
>> +struct mscl_ctx *curr_ctx;
>> +struct mscl_dev *mscl = ctx->mscl_dev;
>> +int ret;
>> +
>> +curr_ctx = v4l2_m2m_get_curr_priv(mscl->m2m.m2m_dev);
>> +if (!mscl_m2m_pending(mscl) || (curr_ctx != ctx))
>> +return 0;
>> +
>> +mscl_ctx_state_lock_set(MSCL_CTX_STOP_REQ, ctx);
>> +ret = wait_event_timeout(mscl->irq_queue,
>> +!mscl_ctx_state_is_set(MSCL_CTX_STOP_REQ, ctx),
>> +MSCL_SHUTDOWN_TIMEOUT);
>> +
>> +return ret == 0 ? -ETIMEDOUT : ret;
>> +}
>> +
>> +static int mscl_m2m_start_streaming(struct vb2_queue *q, unsigned int count)
>> +{
>> +struct mscl_ctx *ctx = q->drv_priv;
>> +int ret;
>> +
>> +ret = pm_runtime_get_sync(&ctx->mscl_dev->pdev->dev);
>> +
>> +return ret > 0 ? 0 : ret;
>> +}
>> +
>> +static int mscl_m2m_stop_streaming(struct vb2_queue *q)
>> +{
>> +struct mscl_ctx *ctx = q->drv_priv;
>> +int ret;
>> +
>> +ret = mscl_m2m_ctx_stop_req(ctx);
>> +if (ret == -ETIMEDOUT)
>> +mscl_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
>> +
>> +pm_runtime_put(&ctx->mscl_dev->pdev->dev);
>> +
>> +return 0;
>> +}
>> +
>> +void mscl_m2m_job_finish(struct mscl_ctx *ctx, int vb_state)
>> +{
>> +struct vb2_buffer *src_vb, *dst_vb;
>> +
>> +if (!ctx || !ctx->m2m_ctx)
>> +return;
>> +
>> +src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
>> +dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
>> +
>> +if (src_vb && dst_vb) {
>> +v4l2_m2m_buf_done(src_vb, vb_state);
>> +v4l2_m2m_buf_done(dst_vb, vb_state);
>> +
>> +v4l2_m2m_job_finish(ctx->mscl_dev->m2m.m2m_dev,
>> +ctx->m2m_ctx);
>> +}
>> +}
>> +
>> +
>> +static void mscl_m2m_job_abort(void *priv)
>> +{
>> +struct mscl_ctx *ctx = priv;
>> +int ret;
>> +
>> +ret = mscl_m2m_ctx_stop_req(ctx);
>> +if (ret == -ETIMEDOUT)
>> +mscl_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
>> +}
>> +
>> +static int mscl_get_bufs(struct mscl_ctx *ctx)
>> +{
>> +struct mscl_frame *s_frame, *d_frame;
>> +struct vb2_buffer *src_vb, *dst_vb;
>> +int ret;
>> +
>> +s_frame = &ctx->s_frame;
>> +d_frame = &ctx->d_frame;
>> +
>> +src_vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
>> +ret = mscl_prepare_addr(ctx, src_vb, s_frame, &s_frame->addr);
>> +if (ret)
>> +return ret;
>> +
>> +dst_vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
>> +ret = mscl_prepare_addr(ctx, dst_vb, d_frame, &d_frame->addr);
>> +if (ret)
>> +return ret;
>> +
>> +dst_vb->v4l2_buf.timestamp = src_vb->v4l2_buf.timestamp;
>> +
>> +return 0;
>> +}
>> +
>> +static void mscl_m2m_device_run(void *priv)
>> +{
>> +struct mscl_ctx *ctx = priv;
>> +struct mscl_dev *mscl;
>> +unsigned long flags;
>> +int ret;
>> +bool is_set = false;
>> +
>> +if (WARN(!ctx, "null hardware context\n"))
>> +return;
>> +
>> +mscl = ctx->mscl_dev;
>> +spin_lock_irqsave(&mscl->slock, flags);
>> +
>> +set_bit(ST_M2M_PEND, &mscl->state);
>> +
>> +/* Reconfigure hardware if the context has changed. */
>> +if (mscl->m2m.ctx != ctx) {
>> +dev_dbg(&mscl->pdev->dev,
>> +"mscl->m2m.ctx = 0x%p, current_ctx = 0x%p",
>> +mscl->m2m.ctx, ctx);
>> +ctx->state |= MSCL_PARAMS;
>> +mscl->m2m.ctx = ctx;
>> +}
>> +
>> +is_set = (ctx->state & MSCL_CTX_STOP_REQ) ? 1 : 0;
>> +ctx->state &= ~MSCL_CTX_STOP_REQ;
>> +if (is_set) {
>> +wake_up(&mscl->irq_queue);
>

Re: [PATCH v2 3/5] [media] exynos-mscl: Add m2m functionality for the M-Scaler driver

2013-08-19 Thread Hans Verkuil
On 08/19/2013 12:58 PM, Shaik Ameer Basha wrote:
> This patch adds the memory to memory (m2m) interface functionality
> for the M-Scaler driver.

Just one small comment below...

> 
> Signed-off-by: Shaik Ameer Basha 
> ---
>  drivers/media/platform/exynos-mscl/mscl-m2m.c |  763 
> +
>  1 file changed, 763 insertions(+)
>  create mode 100644 drivers/media/platform/exynos-mscl/mscl-m2m.c
> 
> diff --git a/drivers/media/platform/exynos-mscl/mscl-m2m.c 
> b/drivers/media/platform/exynos-mscl/mscl-m2m.c
> new file mode 100644
> index 000..fecbb57
> --- /dev/null
> +++ b/drivers/media/platform/exynos-mscl/mscl-m2m.c
> @@ -0,0 +1,763 @@
> +/*
> + * Copyright (c) 2013 - 2014 Samsung Electronics Co., Ltd.
> + *   http://www.samsung.com
> + *
> + * Samsung EXYNOS5 SoC series M-Scaler driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published
> + * by the Free Software Foundation, either version 2 of the License,
> + * or (at your option) any later version.
> + */
> +
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +
> +#include "mscl-core.h"
> +
> +static int mscl_m2m_ctx_stop_req(struct mscl_ctx *ctx)
> +{
> + struct mscl_ctx *curr_ctx;
> + struct mscl_dev *mscl = ctx->mscl_dev;
> + int ret;
> +
> + curr_ctx = v4l2_m2m_get_curr_priv(mscl->m2m.m2m_dev);
> + if (!mscl_m2m_pending(mscl) || (curr_ctx != ctx))
> + return 0;
> +
> + mscl_ctx_state_lock_set(MSCL_CTX_STOP_REQ, ctx);
> + ret = wait_event_timeout(mscl->irq_queue,
> + !mscl_ctx_state_is_set(MSCL_CTX_STOP_REQ, ctx),
> + MSCL_SHUTDOWN_TIMEOUT);
> +
> + return ret == 0 ? -ETIMEDOUT : ret;
> +}
> +
> +static int mscl_m2m_start_streaming(struct vb2_queue *q, unsigned int count)
> +{
> + struct mscl_ctx *ctx = q->drv_priv;
> + int ret;
> +
> + ret = pm_runtime_get_sync(&ctx->mscl_dev->pdev->dev);
> +
> + return ret > 0 ? 0 : ret;
> +}
> +
> +static int mscl_m2m_stop_streaming(struct vb2_queue *q)
> +{
> + struct mscl_ctx *ctx = q->drv_priv;
> + int ret;
> +
> + ret = mscl_m2m_ctx_stop_req(ctx);
> + if (ret == -ETIMEDOUT)
> + mscl_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
> +
> + pm_runtime_put(&ctx->mscl_dev->pdev->dev);
> +
> + return 0;
> +}
> +
> +void mscl_m2m_job_finish(struct mscl_ctx *ctx, int vb_state)
> +{
> + struct vb2_buffer *src_vb, *dst_vb;
> +
> + if (!ctx || !ctx->m2m_ctx)
> + return;
> +
> + src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
> + dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
> +
> + if (src_vb && dst_vb) {
> + v4l2_m2m_buf_done(src_vb, vb_state);
> + v4l2_m2m_buf_done(dst_vb, vb_state);
> +
> + v4l2_m2m_job_finish(ctx->mscl_dev->m2m.m2m_dev,
> + ctx->m2m_ctx);
> + }
> +}
> +
> +
> +static void mscl_m2m_job_abort(void *priv)
> +{
> + struct mscl_ctx *ctx = priv;
> + int ret;
> +
> + ret = mscl_m2m_ctx_stop_req(ctx);
> + if (ret == -ETIMEDOUT)
> + mscl_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
> +}
> +
> +static int mscl_get_bufs(struct mscl_ctx *ctx)
> +{
> + struct mscl_frame *s_frame, *d_frame;
> + struct vb2_buffer *src_vb, *dst_vb;
> + int ret;
> +
> + s_frame = &ctx->s_frame;
> + d_frame = &ctx->d_frame;
> +
> + src_vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
> + ret = mscl_prepare_addr(ctx, src_vb, s_frame, &s_frame->addr);
> + if (ret)
> + return ret;
> +
> + dst_vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
> + ret = mscl_prepare_addr(ctx, dst_vb, d_frame, &d_frame->addr);
> + if (ret)
> + return ret;
> +
> + dst_vb->v4l2_buf.timestamp = src_vb->v4l2_buf.timestamp;
> +
> + return 0;
> +}
> +
> +static void mscl_m2m_device_run(void *priv)
> +{
> + struct mscl_ctx *ctx = priv;
> + struct mscl_dev *mscl;
> + unsigned long flags;
> + int ret;
> + bool is_set = false;
> +
> + if (WARN(!ctx, "null hardware context\n"))
> + return;
> +
> + mscl = ctx->mscl_dev;
> + spin_lock_irqsave(&mscl->slock, flags);
> +
> + set_bit(ST_M2M_PEND, &mscl->state);
> +
> + /* Reconfigure hardware if the context has changed. */
> + if (mscl->m2m.ctx != ctx) {
> + dev_dbg(&mscl->pdev->dev,
> + "mscl->m2m.ctx = 0x%p, current_ctx = 0x%p",
> + mscl->m2m.ctx, ctx);
> + ctx->state |= MSCL_PARAMS;
> + mscl->m2m.ctx = ctx;
> + }
> +
> + is_set = (ctx->state & MSCL_CTX_STOP_REQ) ? 1 : 0;
> + ctx->state &= ~MSCL_CTX_STOP_REQ;
> + if (is_set) {
> + wake_up(&mscl->irq_queue);
> + goto put_device;
> + }
> +
> + ret = mscl_get_bufs(ctx);
> + if (ret) {
> + dev_dbg(&mscl->pdev->