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>
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);
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);
}
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;
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);
}
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();
}
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);
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;
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();
}
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;
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;
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;
}
/* 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);
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);
- }
}
}
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();
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)
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);
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);
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),
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),
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;
}
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)
{