[RAMEN9610-19721][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)
committerKim Gunho <gunho.kim@samsung.com>
Mon, 9 Sep 2019 11:14:43 +0000 (20:14 +0900)
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 ee038b17240f272c9c36d5cb6c89698b94416ba5..f7d368ce4dab57668fbc952681c469516f0f1e34 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 ba2f144e8e6f246e89af5ba5043ef26d68c5d274..da0a5a29e48fb4ca53c8351c376ee5e970e0530d 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 3643c73f5ef6fb1ced7ddc3cebbea33a2768ffed..4d200bd036544c20a898a4561f8b1ffd2f135d59 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 4a78fa15f1535f1b7f445273c872002ce9175f43..e97810971fa377b1069729dac07ad0cd12e94ab2 100644 (file)
@@ -1570,14 +1570,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 12ce6b66d18fdefec52322bb55d3111068d8f78b..90de0f02bb9bbeebe084c624c37c2b49a6f762c2 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 584fb580d164bf761483a31a7e37e1ef69f6cebd..a611b9b35f7026e5f5328289a269f96342324135 100644 (file)
@@ -355,10 +355,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();
 
@@ -373,21 +375,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)
@@ -734,8 +791,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 e9769ea13df3535481b4c00551b660ad95406b91..1d7f1da7fd336099b235e4303f9566b9bf3a6caa 100644 (file)
@@ -25,7 +25,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 e7a00c85a6cb06dc15308aea5febefa3058b1f93..30a23e1314855288d54faa987909e967d3a67628 100644 (file)
@@ -46,7 +46,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)
 {