[RAMEN9610-17224][COMMON] media: mfc: DRV5.0: apply spin_lock to ctx_ready
authorSunyoung Kang <sy0816.kang@samsung.com>
Tue, 26 Feb 2019 00:22:24 +0000 (09:22 +0900)
committerlingsen1 <lingsen1@lenovo.com>
Tue, 25 Jun 2019 02:16:34 +0000 (10:16 +0800)
The ctx_ready() and set_bit() should be synchronized.
So this applies the spin_lock to ctx_ready() by using
new function mfc_ctx_ready_set_bit().

Change-Id: I366b64ccfaa18fe929c1a174531aa52c5a97b094
Signed-off-by: Sunyoung Kang <sy0816.kang@samsung.com>
drivers/media/platform/exynos/mfc/mfc_dec_v4l2.c
drivers/media/platform/exynos/mfc/mfc_dec_vb2.c
drivers/media/platform/exynos/mfc/mfc_enc_v4l2.c
drivers/media/platform/exynos/mfc/mfc_enc_vb2.c
drivers/media/platform/exynos/mfc/mfc_hwlock.c
drivers/media/platform/exynos/mfc/mfc_isr.c
drivers/media/platform/exynos/mfc/mfc_nal_q.c
drivers/media/platform/exynos/mfc/mfc_otf.c
drivers/media/platform/exynos/mfc/mfc_otf.h
drivers/media/platform/exynos/mfc/mfc_sync.c
drivers/media/platform/exynos/mfc/mfc_sync.h

index 3e7a596099b607000ae5bcc9fa371dc07936236d..b9526af4d370873a1c20489e62bd8b046378790a 100644 (file)
@@ -559,8 +559,7 @@ static int mfc_dec_s_fmt_vid_out_mplane(struct file *file, void *priv,
 
        mfc_debug(2, "Got instance number: %d\n", ctx->inst_no);
 
-       if (mfc_ctx_ready(ctx))
-               mfc_set_bit(ctx->num, &dev->work_bits);
+       mfc_ctx_ready_set_bit(ctx, &dev->work_bits);
        if (mfc_is_work_to_do(dev))
                queue_work(dev->butler_wq, &dev->butler_work);
 
@@ -654,9 +653,7 @@ static int mfc_dec_reqbufs(struct file *file, void *priv,
 
                ctx->capture_state = QUEUE_BUFS_REQUESTED;
 
-               if (mfc_ctx_ready(ctx))
-                       mfc_set_bit(ctx->num, &dev->work_bits);
-
+               mfc_ctx_ready_set_bit(ctx, &dev->work_bits);
                mfc_try_run(dev);
        }
 
index 6d2c4ecf44970b8e61958fddbb4fcb32347f38ca..f7bb8f30be62fbd269da67a7f48e72a3e66403ff 100644 (file)
@@ -262,9 +262,7 @@ static int mfc_dec_start_streaming(struct vb2_queue *q, unsigned int count)
        struct mfc_dev *dev = ctx->dev;
 
        /* If context is ready then dev = work->data;schedule it to run */
-       if (mfc_ctx_ready(ctx))
-               mfc_set_bit(ctx->num, &dev->work_bits);
-
+       mfc_ctx_ready_set_bit(ctx, &dev->work_bits);
        mfc_try_run(dev);
 
        return 0;
@@ -427,8 +425,7 @@ static void mfc_dec_stop_streaming(struct vb2_queue *q)
        mfc_clear_bit(ctx->num, &dev->work_bits);
        mfc_release_hwlock_ctx(ctx);
 
-       if (mfc_ctx_ready(ctx))
-               mfc_set_bit(ctx->num, &dev->work_bits);
+       mfc_ctx_ready_set_bit(ctx, &dev->work_bits);
        if (mfc_is_work_to_do(dev))
                queue_work(dev->butler_wq, &dev->butler_work);
 }
@@ -480,10 +477,8 @@ static void mfc_dec_buf_queue(struct vb2_buffer *vb)
                mfc_err_ctx("Unsupported buffer type (%d)\n", vq->type);
        }
 
-       if (mfc_ctx_ready(ctx)) {
-               mfc_set_bit(ctx->num, &dev->work_bits);
+       if (mfc_ctx_ready_set_bit(ctx, &dev->work_bits))
                mfc_try_run(dev);
-       }
 
        mfc_debug_leave();
 }
index 868ae88cb3a0a51a61c2288248a2098bd94f9bfb..cf359c5c4a04768f6c3629ddaab38660e5ea62e7 100644 (file)
@@ -478,10 +478,9 @@ static int mfc_enc_s_fmt_vid_cap_mplane(struct file *file, void *priv,
 
        mfc_debug(2, "Got instance number: %d\n", ctx->inst_no);
 
-       if (mfc_ctx_ready(ctx))
-               mfc_set_bit(ctx->num, &dev->work_bits);
-       if (ctx->otf_handle && mfc_otf_ctx_ready(ctx))
-               mfc_set_bit(ctx->num, &dev->work_bits);
+       mfc_ctx_ready_set_bit(ctx, &dev->work_bits);
+       if (ctx->otf_handle)
+               mfc_otf_ctx_ready_set_bit(ctx, &dev->work_bits);
        if (mfc_is_work_to_do(dev))
                queue_work(dev->butler_wq, &dev->butler_work);
 
index c542c05b49d0ff180e4da7b82dcd56c370f513f2..95e250d0090e3e058a4f0a7c95044ca2ed2fa21b 100644 (file)
@@ -322,9 +322,7 @@ static int mfc_enc_start_streaming(struct vb2_queue *q, unsigned int count)
        struct mfc_dev *dev = ctx->dev;
 
        /* If context is ready then dev = work->data;schedule it to run */
-       if (mfc_ctx_ready(ctx))
-               mfc_set_bit(ctx->num, &dev->work_bits);
-
+       mfc_ctx_ready_set_bit(ctx, &dev->work_bits);
        mfc_try_run(dev);
 
        return 0;
@@ -443,9 +441,7 @@ static void mfc_enc_buf_queue(struct vb2_buffer *vb)
                mfc_err_ctx("unsupported buffer type (%d)\n", vq->type);
        }
 
-       if (mfc_ctx_ready(ctx))
-               mfc_set_bit(ctx->num, &dev->work_bits);
-
+       mfc_ctx_ready_set_bit(ctx, &dev->work_bits);
        mfc_try_run(dev);
 
        mfc_debug_leave();
index e888ea7b50b5c3af1d0b89085270cb480ddf0ba0..22623c4e87df10b330dbf59f67651fd2cb4fcacf 100644 (file)
@@ -501,8 +501,10 @@ static int __mfc_nal_q_just_run(struct mfc_ctx *ctx, int need_cache_flush)
                        }
 
                        mfc_clear_bit(ctx->num, &dev->work_bits);
-                       if ((mfc_ctx_ready(ctx) && !ctx->clear_work_bit) ||
-                                       nal_q_handle->nal_q_exception)
+
+                       if (!ctx->clear_work_bit)
+                               mfc_ctx_ready_set_bit(ctx, &dev->work_bits);
+                       if (nal_q_handle->nal_q_exception)
                                mfc_set_bit(ctx->num, &dev->work_bits);
                        ctx->clear_work_bit = 0;
 
@@ -539,8 +541,9 @@ static int __mfc_nal_q_just_run(struct mfc_ctx *ctx, int need_cache_flush)
 
                        mfc_clear_bit(ctx->num, &dev->work_bits);
 
-                       if ((mfc_ctx_ready(ctx) && !ctx->clear_work_bit) ||
-                                       nal_q_handle->nal_q_exception)
+                       if (!ctx->clear_work_bit)
+                               mfc_ctx_ready_set_bit(ctx, &dev->work_bits);
+                       if (nal_q_handle->nal_q_exception)
                                mfc_set_bit(ctx->num, &dev->work_bits);
                        ctx->clear_work_bit = 0;
 
@@ -727,7 +730,9 @@ int mfc_just_run(struct mfc_dev *dev, int new_ctx_index)
        if (ret) {
                /* Check again the ctx condition and clear work bits
                 * if ctx is not available. */
-               if (mfc_ctx_ready(ctx) == 0 || ctx->clear_work_bit) {
+               if (mfc_ctx_ready_clear_bit(ctx, &dev->work_bits) == 0)
+                       ctx->clear_work_bit = 0;
+               if (ctx->clear_work_bit) {
                        mfc_clear_bit(ctx->num, &dev->work_bits);
                        ctx->clear_work_bit = 0;
                }
index 44fc3fcf1c863a6a5cf441492a6d4b5218863e71..edff778a234a394c4285974125c87875c6c50a4b 100644 (file)
@@ -1559,14 +1559,12 @@ irqreturn_t mfc_irq(int irq, void *priv)
        /* clean-up interrupt */
        mfc_clear_int();
 
-       if ((ctx->state != MFCINST_RES_CHANGE_INIT) && (mfc_ctx_ready(ctx) == 0))
-               mfc_clear_bit(ctx->num, &dev->work_bits);
+       if (ctx->state != MFCINST_RES_CHANGE_INIT)
+               mfc_ctx_ready_clear_bit(ctx, &dev->work_bits);
 
        if (ctx->otf_handle) {
-               if (mfc_otf_ctx_ready(ctx))
-                       mfc_set_bit(ctx->num, &dev->work_bits);
-               else
-                       mfc_clear_bit(ctx->num, &dev->work_bits);
+               if (mfc_otf_ctx_ready_set_bit(ctx, &dev->work_bits) == 0)
+                       mfc_otf_ctx_ready_clear_bit(ctx, &dev->work_bits);
        }
 
        mfc_hwlock_handler_irq(dev, ctx, reason, err);
index 779e8ec102d56ba1d11023e16aba1200fb8f81c2..337ac24730e0cd672c9cfa4f38045f0c64f4e32e 100644 (file)
@@ -500,11 +500,9 @@ void mfc_nal_q_cleanup_queue(struct mfc_dev *dev)
                ctx = dev->ctx[i];
                if (ctx) {
                        mfc_cleanup_nal_queue(ctx);
-                       if (mfc_ctx_ready(ctx)) {
-                               mfc_set_bit(ctx->num, &dev->work_bits);
+                       if (mfc_ctx_ready_set_bit(ctx, &dev->work_bits))
                                mfc_debug(2, "[NALQ] set work_bits after cleanup,"
                                                " ctx: %d\n", ctx->num);
-                       }
                }
        }
 
index 5b6f9137af021bcdc69eaebe63af1f2ff4b683ef..37bb29115aa004f76ea46138b8656b525c446a3d 100644 (file)
@@ -352,10 +352,12 @@ void mfc_otf_deinit(struct mfc_ctx *ctx)
        mfc_debug_leave();
 }
 
-int mfc_otf_ctx_ready(struct mfc_ctx *ctx)
+int mfc_otf_ctx_ready_set_bit(struct mfc_ctx *ctx, struct mfc_bits *data)
 {
        struct mfc_dev *dev = ctx->dev;
        struct _otf_handle *handle;
+       unsigned long flags;
+       int is_ready = 0;
 
        mfc_debug_enter();
 
@@ -370,21 +372,76 @@ int mfc_otf_ctx_ready(struct mfc_ctx *ctx)
        if (dev->shutdown)
                return 0;
 
+       /* The ready condition check and set work_bit should be synchronized */
+       spin_lock_irqsave(&data->lock, flags);
+
        /* Context is to parse header */
        if (ctx->state == MFCINST_GOT_INST)
-               return 1;
+               is_ready = 1;
 
        /* Context is to set buffers */
-       if (ctx->state == MFCINST_HEAD_PARSED)
-               return 1;
+       else if (ctx->state == MFCINST_HEAD_PARSED)
+               is_ready = 1;
 
-       if (ctx->state == MFCINST_RUNNING && handle->otf_work_bit)
-               return 1;
-       mfc_debug(2, "[OTF] ctx is not ready\n");
+       else if (ctx->state == MFCINST_RUNNING && handle->otf_work_bit)
+               is_ready = 1;
+
+       if (is_ready == 1)
+               __set_bit(ctx->num, &data->bits);
+       else
+               mfc_debug(2, "[OTF] ctx is not ready\n");
+
+       spin_unlock_irqrestore(&data->lock, flags);
 
        mfc_debug_leave();
 
-       return 0;
+       return is_ready;
+}
+
+int mfc_otf_ctx_ready_clear_bit(struct mfc_ctx *ctx, struct mfc_bits *data)
+{
+       struct mfc_dev *dev = ctx->dev;
+       struct _otf_handle *handle;
+       unsigned long flags;
+       int is_ready = 0;
+
+       mfc_debug_enter();
+
+       if (!ctx->otf_handle)
+               return 0;
+
+       handle = ctx->otf_handle;
+
+       mfc_debug(1, "[OTF] [c:%d] state = %d, otf_work_bit = %d\n",
+                       ctx->num, ctx->state, handle->otf_work_bit);
+       /* If shutdown is called, do not try any cmd */
+       if (dev->shutdown)
+               return 0;
+
+       /* The ready condition check and set work_bit should be synchronized */
+       spin_lock_irqsave(&data->lock, flags);
+
+       /* Context is to parse header */
+       if (ctx->state == MFCINST_GOT_INST)
+               is_ready = 1;
+
+       /* Context is to set buffers */
+       else if (ctx->state == MFCINST_HEAD_PARSED)
+               is_ready = 1;
+
+       else if (ctx->state == MFCINST_RUNNING && handle->otf_work_bit)
+               is_ready = 1;
+
+       if (is_ready == 0)
+               __clear_bit(ctx->num, &data->bits);
+       else
+               mfc_debug(2, "[OTF] ctx is ready\n");
+
+       spin_unlock_irqrestore(&data->lock, flags);
+
+       mfc_debug_leave();
+
+       return is_ready;
 }
 
 static int __check_disable_header_gen(struct mfc_dev *dev)
@@ -731,8 +788,7 @@ int mfc_hwfc_encode(int buf_index, int job_id, struct encoding_param *param)
        handle->otf_job_id = job_id;
        handle->otf_time_stamp = param->time_stamp;
 
-       if (mfc_otf_ctx_ready(ctx))
-               mfc_set_bit(ctx->num, &dev->work_bits);
+       mfc_otf_ctx_ready_set_bit(ctx, &dev->work_bits);
        if (mfc_is_work_to_do(dev))
                queue_work(dev->butler_wq, &dev->butler_work);
 
index 854cd6115a7082e7ad8e958b8983af9c7bc52bf0..1f915c05c7d1d24952dd1379d0401b59eb08fae8 100644 (file)
@@ -21,7 +21,8 @@ int mfc_otf_create(struct mfc_ctx *ctx);
 void mfc_otf_destroy(struct mfc_ctx *ctx);
 int mfc_otf_init(struct mfc_ctx *ctx);
 void mfc_otf_deinit(struct mfc_ctx *ctx);
-int mfc_otf_ctx_ready(struct mfc_ctx *ctx);
+int mfc_otf_ctx_ready_set_bit(struct mfc_ctx *ctx, struct mfc_bits *data);
+int mfc_otf_ctx_ready_clear_bit(struct mfc_ctx *ctx, struct mfc_bits *data);
 int mfc_otf_run_enc_init(struct mfc_ctx *ctx);
 int mfc_otf_run_enc_frame(struct mfc_ctx *ctx);
 int mfc_otf_handle_seq(struct mfc_ctx *ctx);
index 4cf455c4bf5accbdf715116036fa36ab73153523..548030449926ca0a282c30192c65bfe1f632e1e3 100644 (file)
@@ -189,13 +189,14 @@ int mfc_get_new_ctx(struct mfc_dev *dev)
        return new_ctx_index;
 }
 
-/* Check whether a context should be run on hardware */
-static int __mfc_dec_ctx_ready(struct mfc_ctx *ctx)
+int __mfc_dec_ctx_ready_set_bit(struct mfc_ctx *ctx, struct mfc_bits *data, bool set)
 {
        struct mfc_dev *dev = ctx->dev;
        int src_buf_queue_greater_than_0 = 0;
        int dst_buf_queue_greater_than_0 = 0;
        int ref_buf_queue_same_dpb_count_plus_5 = 0;
+       unsigned long flags;
+       int is_ready = 0;
 
        mfc_debug(1, "[c:%d] src = %d, dst = %d, src_nal = %d, dst_nal = %d, ref = %d, state = %d, capstat = %d\n",
                  ctx->num, mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_queue),
@@ -217,49 +218,67 @@ static int __mfc_dec_ctx_ready(struct mfc_ctx *ctx)
        if (dev->shutdown)
                return 0;
 
+       /* The ready condition check and set work_bit should be synchronized */
+       spin_lock_irqsave(&data->lock, flags);
+
        /* Context is to parse header */
        if (ctx->state == MFCINST_GOT_INST &&
                src_buf_queue_greater_than_0)
-               return 1;
+               is_ready = 1;
 
        /* Context is to decode a frame */
-       if (ctx->state == MFCINST_RUNNING &&
+       else if (ctx->state == MFCINST_RUNNING &&
                ctx->wait_state == WAIT_NONE && src_buf_queue_greater_than_0 &&
                (dst_buf_queue_greater_than_0 || ref_buf_queue_same_dpb_count_plus_5))
-               return 1;
+               is_ready = 1;
 
        /* Context is to return last frame */
-       if (ctx->state == MFCINST_FINISHING &&
+       else if (ctx->state == MFCINST_FINISHING &&
                (dst_buf_queue_greater_than_0 || ref_buf_queue_same_dpb_count_plus_5))
-               return 1;
+               is_ready = 1;
 
        /* Context is to set buffers */
-       if (ctx->state == MFCINST_HEAD_PARSED &&
+       else if (ctx->state == MFCINST_HEAD_PARSED &&
                (dst_buf_queue_greater_than_0 && ctx->wait_state == WAIT_NONE))
-               return 1;
+               is_ready = 1;
 
        /* Resolution change */
-       if ((ctx->state == MFCINST_RES_CHANGE_INIT || ctx->state == MFCINST_RES_CHANGE_FLUSH) &&
+       else if ((ctx->state == MFCINST_RES_CHANGE_INIT || ctx->state == MFCINST_RES_CHANGE_FLUSH) &&
                dst_buf_queue_greater_than_0)
-               return 1;
+               is_ready = 1;
 
-       if (ctx->state == MFCINST_RES_CHANGE_END &&
+       else if (ctx->state == MFCINST_RES_CHANGE_END &&
                src_buf_queue_greater_than_0)
-               return 1;
+               is_ready = 1;
+
+       if ((is_ready == 1) && (set == true)) {
+               /* if the ctx is ready and request set_bit, set the work_bit */
+               __set_bit(ctx->num, &data->bits);
+       } else if ((is_ready == 0) && (set == false)) {
+               /* if the ctx is not ready and request clear_bit, clear the work_bit */
+               __clear_bit(ctx->num, &data->bits);
+       } else {
+               if (set == true) {
+                       /* If the ctx is not ready, this is not included to S/W driver margin */
+                       mfc_perf_cancel_drv_margin(dev);
+                       mfc_debug(2, "ctx is not ready\n");
+               }
+       }
 
-       mfc_perf_cancel_drv_margin(dev);
-       mfc_debug(2, "ctx is not ready\n");
+       spin_unlock_irqrestore(&data->lock, flags);
 
-       return 0;
+       return is_ready;
 }
 
-static int __mfc_enc_ctx_ready(struct mfc_ctx *ctx)
+static int __mfc_enc_ctx_ready_set_bit(struct mfc_ctx *ctx, struct mfc_bits *data, bool set)
 {
        struct mfc_enc *enc = ctx->enc_priv;
        struct mfc_dev *dev = ctx->dev;
        struct mfc_enc_params *p = &enc->params;
        int src_buf_queue_greater_than_0 = 0;
        int dst_buf_queue_greater_than_0 = 0;
+       unsigned long flags;
+       int is_ready = 0;
 
        mfc_debug(1, "[c:%d] src = %d, dst = %d, src_nal = %d, dst_nal = %d, ref = %d, state = %d\n",
                  ctx->num, mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_queue),
@@ -278,49 +297,75 @@ static int __mfc_enc_ctx_ready(struct mfc_ctx *ctx)
        if (dev->shutdown)
                return 0;
 
+       /* The ready condition check and set work_bit should be synchronized */
+       spin_lock_irqsave(&data->lock, flags);
+
        /* context is ready to make header */
        if (ctx->state == MFCINST_GOT_INST &&
                dst_buf_queue_greater_than_0) {
                if (p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_AT_THE_READY) {
                        if (src_buf_queue_greater_than_0)
-                               return 1;
+                               is_ready = 1;
                } else {
-                       return 1;
+                       is_ready = 1;
                }
        }
 
        /* context is ready to allocate DPB */
-       if (ctx->state == MFCINST_HEAD_PARSED &&
+       else if (ctx->state == MFCINST_HEAD_PARSED &&
                dst_buf_queue_greater_than_0)
-               return 1;
+               is_ready = 1;
 
        /* context is ready to encode a frame */
-       if (ctx->state == MFCINST_RUNNING &&
+       else if (ctx->state == MFCINST_RUNNING &&
                src_buf_queue_greater_than_0 && dst_buf_queue_greater_than_0)
-               return 1;
+               is_ready = 1;
 
        /* context is ready to encode a frame for NAL_ABORT command */
-       if (ctx->state == MFCINST_ABORT_INST &&
+       else if (ctx->state == MFCINST_ABORT_INST &&
                src_buf_queue_greater_than_0 && dst_buf_queue_greater_than_0)
-               return 1;
+               is_ready = 1;
 
        /* context is ready to encode remain frames */
-       if (ctx->state == MFCINST_FINISHING &&
+       else if (ctx->state == MFCINST_FINISHING &&
                src_buf_queue_greater_than_0 && dst_buf_queue_greater_than_0)
-               return 1;
+               is_ready = 1;
+
+       if ((is_ready == 1) && (set == true)) {
+               /* if the ctx is ready and request set_bit, set the work_bit */
+               __set_bit(ctx->num, &data->bits);
+       } else if ((is_ready == 0) && (set == false)) {
+               /* if the ctx is not ready and request clear_bit, clear the work_bit */
+               __clear_bit(ctx->num, &data->bits);
+       } else {
+               if (set == true) {
+                       mfc_perf_cancel_drv_margin(dev);
+                       mfc_debug(2, "ctx is not ready\n");
+               }
+       }
+
+       spin_unlock_irqrestore(&data->lock, flags);
 
-       mfc_perf_cancel_drv_margin(dev);
-       mfc_debug(2, "ctx is not ready\n");
+       return is_ready;
+}
+
+
+int mfc_ctx_ready_set_bit(struct mfc_ctx *ctx, struct mfc_bits *data)
+{
+       if (ctx->type == MFCINST_DECODER)
+               return __mfc_dec_ctx_ready_set_bit(ctx, data, true);
+       else if (ctx->type == MFCINST_ENCODER)
+               return __mfc_enc_ctx_ready_set_bit(ctx, data, true);
 
        return 0;
 }
 
-int mfc_ctx_ready(struct mfc_ctx *ctx)
+int mfc_ctx_ready_clear_bit(struct mfc_ctx *ctx, struct mfc_bits *data)
 {
        if (ctx->type == MFCINST_DECODER)
-               return __mfc_dec_ctx_ready(ctx);
+               return __mfc_dec_ctx_ready_set_bit(ctx, data, false);
        else if (ctx->type == MFCINST_ENCODER)
-               return __mfc_enc_ctx_ready(ctx);
+               return __mfc_enc_ctx_ready_set_bit(ctx, data, false);
 
        return 0;
 }
index d18cc2eccac2cf4a1214c1d9a45f8915c99f4e5f..f4b74b60c75bad246dcb5e8ace3cadaba739207c 100644 (file)
@@ -44,7 +44,9 @@ void mfc_wake_up_ctx(struct mfc_ctx *ctx, unsigned int reason,
                unsigned int err);
 
 int mfc_get_new_ctx(struct mfc_dev *dev);
-int mfc_ctx_ready(struct mfc_ctx *ctx);
+
+int mfc_ctx_ready_set_bit(struct mfc_ctx *ctx, struct mfc_bits *data);
+int mfc_ctx_ready_clear_bit(struct mfc_ctx *ctx, struct mfc_bits *data);
 
 static inline void mfc_set_bit(int num, struct mfc_bits *data)
 {