From: Sunyoung Kang Date: Tue, 26 Feb 2019 00:22:24 +0000 (+0900) Subject: [RAMEN9610-19721][COMMON] media: mfc: DRV5.0: apply spin_lock to ctx_ready X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=1b382eb0116d269ee0909b9be85d3d47100a8556;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git [RAMEN9610-19721][COMMON] media: mfc: DRV5.0: apply spin_lock to ctx_ready 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 --- diff --git a/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.c b/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.c index ee038b17240f..f7d368ce4dab 100644 --- a/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.c +++ b/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.c @@ -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); } diff --git a/drivers/media/platform/exynos/mfc/mfc_dec_vb2.c b/drivers/media/platform/exynos/mfc/mfc_dec_vb2.c index 6d2c4ecf4497..f7bb8f30be62 100644 --- a/drivers/media/platform/exynos/mfc/mfc_dec_vb2.c +++ b/drivers/media/platform/exynos/mfc/mfc_dec_vb2.c @@ -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(); } diff --git a/drivers/media/platform/exynos/mfc/mfc_enc_v4l2.c b/drivers/media/platform/exynos/mfc/mfc_enc_v4l2.c index ba2f144e8e6f..da0a5a29e48f 100644 --- a/drivers/media/platform/exynos/mfc/mfc_enc_v4l2.c +++ b/drivers/media/platform/exynos/mfc/mfc_enc_v4l2.c @@ -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); diff --git a/drivers/media/platform/exynos/mfc/mfc_enc_vb2.c b/drivers/media/platform/exynos/mfc/mfc_enc_vb2.c index 3643c73f5ef6..4d200bd03654 100644 --- a/drivers/media/platform/exynos/mfc/mfc_enc_vb2.c +++ b/drivers/media/platform/exynos/mfc/mfc_enc_vb2.c @@ -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(); diff --git a/drivers/media/platform/exynos/mfc/mfc_hwlock.c b/drivers/media/platform/exynos/mfc/mfc_hwlock.c index e888ea7b50b5..22623c4e87df 100644 --- a/drivers/media/platform/exynos/mfc/mfc_hwlock.c +++ b/drivers/media/platform/exynos/mfc/mfc_hwlock.c @@ -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; } diff --git a/drivers/media/platform/exynos/mfc/mfc_isr.c b/drivers/media/platform/exynos/mfc/mfc_isr.c index 4a78fa15f153..e97810971fa3 100644 --- a/drivers/media/platform/exynos/mfc/mfc_isr.c +++ b/drivers/media/platform/exynos/mfc/mfc_isr.c @@ -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); diff --git a/drivers/media/platform/exynos/mfc/mfc_nal_q.c b/drivers/media/platform/exynos/mfc/mfc_nal_q.c index 12ce6b66d18f..90de0f02bb9b 100644 --- a/drivers/media/platform/exynos/mfc/mfc_nal_q.c +++ b/drivers/media/platform/exynos/mfc/mfc_nal_q.c @@ -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); - } } } diff --git a/drivers/media/platform/exynos/mfc/mfc_otf.c b/drivers/media/platform/exynos/mfc/mfc_otf.c index 584fb580d164..a611b9b35f70 100644 --- a/drivers/media/platform/exynos/mfc/mfc_otf.c +++ b/drivers/media/platform/exynos/mfc/mfc_otf.c @@ -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); diff --git a/drivers/media/platform/exynos/mfc/mfc_otf.h b/drivers/media/platform/exynos/mfc/mfc_otf.h index e9769ea13df3..1d7f1da7fd33 100644 --- a/drivers/media/platform/exynos/mfc/mfc_otf.h +++ b/drivers/media/platform/exynos/mfc/mfc_otf.h @@ -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); diff --git a/drivers/media/platform/exynos/mfc/mfc_sync.c b/drivers/media/platform/exynos/mfc/mfc_sync.c index 4cf455c4bf5a..548030449926 100644 --- a/drivers/media/platform/exynos/mfc/mfc_sync.c +++ b/drivers/media/platform/exynos/mfc/mfc_sync.c @@ -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; } diff --git a/drivers/media/platform/exynos/mfc/mfc_sync.h b/drivers/media/platform/exynos/mfc/mfc_sync.h index e7a00c85a6cb..30a23e131485 100644 --- a/drivers/media/platform/exynos/mfc/mfc_sync.h +++ b/drivers/media/platform/exynos/mfc/mfc_sync.h @@ -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) {