summaryrefslogtreecommitdiff
authorNanxin Qin <nanxin.qin@amlogic.com>2020-03-25 10:35:49 (GMT)
committer Nanxin Qin <nanxin.qin@amlogic.com>2020-03-30 08:53:08 (GMT)
commitcbce22a0c642534974fab6a20a081d6683baa3b9 (patch)
treefbacbe49d872b9efba45639205fbec18290514c7
parentad9d8329172b01ceeb135c4cabd804c99223a49b (diff)
downloadmedia_modules-cbce22a0c642534974fab6a20a081d6683baa3b9.zip
media_modules-cbce22a0c642534974fab6a20a081d6683baa3b9.tar.gz
media_modules-cbce22a0c642534974fab6a20a081d6683baa3b9.tar.bz2
v4l: fixed the issue of crash on multi-inst when the app exit. [1/1]
PD#SH-3015 Problem: Exit double decoder playback cause system reboot Solution: 1. have an issue with waiting decoding ending thas has fixed. 2. we must be ensure the job statue switched when invoke m2m pause. 3. to protect the list of capture thread. Verify: u212 Change-Id: I389b541d48b3460ef004a89df921f88cf6bee196 Signed-off-by: Nanxin Qin <nanxin.qin@amlogic.com>
Diffstat
-rw-r--r--drivers/amvdec_ports/aml_vcodec_dec.c36
-rw-r--r--drivers/amvdec_ports/aml_vcodec_dec_drv.c1
-rw-r--r--drivers/amvdec_ports/aml_vcodec_drv.h182
3 files changed, 117 insertions, 102 deletions
diff --git a/drivers/amvdec_ports/aml_vcodec_dec.c b/drivers/amvdec_ports/aml_vcodec_dec.c
index cd6acf8..c3af7cf 100644
--- a/drivers/amvdec_ports/aml_vcodec_dec.c
+++ b/drivers/amvdec_ports/aml_vcodec_dec.c
@@ -867,7 +867,9 @@ static void aml_vdec_worker(struct work_struct *work)
mutex_unlock(&ctx->state_lock);
ctx->q_data[AML_Q_DATA_SRC].resolution_changed = true;
- v4l2_m2m_job_pause(dev->m2m_dev_dec, ctx->m2m_ctx);
+ while (ctx->m2m_ctx->job_flags & TRANS_RUNNING) {
+ v4l2_m2m_job_pause(dev->m2m_dev_dec, ctx->m2m_ctx);
+ }
aml_vdec_flush_decoder(ctx);
@@ -920,17 +922,22 @@ void wait_vcodec_ending(struct aml_vcodec_ctx *ctx)
{
struct aml_vcodec_dev *dev = ctx->dev;
- /* pause inject output data to vdec. */
- v4l2_m2m_job_pause(dev->m2m_dev_dec, ctx->m2m_ctx);
+ /* disable queue output item to worker. */
+ ctx->output_thread_ready = false;
- /* flush worker. */
+ /* flush output buffer worker. */
flush_workqueue(dev->decode_workqueue);
- ctx->v4l_codec_dpb_ready = false;
-
- /* stop decoder. */
+ /* clean output cache and decoder status . */
if (ctx->state > AML_STATE_INIT)
aml_vdec_reset(ctx);
+
+ /* pause the job and clean trans status. */
+ while (ctx->m2m_ctx->job_flags & TRANS_RUNNING) {
+ v4l2_m2m_job_pause(ctx->dev->m2m_dev_dec, ctx->m2m_ctx);
+ }
+
+ ctx->v4l_codec_dpb_ready = false;
}
void try_to_capture(struct aml_vcodec_ctx *ctx)
@@ -987,6 +994,7 @@ void aml_thread_notify(struct aml_vcodec_ctx *ctx,
{
struct aml_vdec_thread *thread = NULL;
+ mutex_lock(&ctx->lock);
list_for_each_entry(thread, &ctx->vdec_thread_list, node) {
if (thread->task == NULL)
continue;
@@ -994,6 +1002,7 @@ void aml_thread_notify(struct aml_vcodec_ctx *ctx,
if (thread->type == type)
up(&thread->sem);
}
+ mutex_unlock(&ctx->lock);
}
EXPORT_SYMBOL_GPL(aml_thread_notify);
@@ -1039,7 +1048,10 @@ void aml_thread_stop(struct aml_vcodec_ctx *ctx)
while (!list_empty(&ctx->vdec_thread_list)) {
thread = list_entry(ctx->vdec_thread_list.next,
struct aml_vdec_thread, node);
+ mutex_lock(&ctx->lock);
list_del(&thread->node);
+ mutex_unlock(&ctx->lock);
+
thread->stop = true;
up(&thread->sem);
kthread_stop(thread->task);
@@ -1368,7 +1380,6 @@ static int vidioc_vdec_dqbuf(struct file *file, void *priv,
struct aml_video_dec_buf *aml_buf = NULL;
struct file *file = NULL;
- mutex_lock(&ctx->lock);
vq = v4l2_m2m_get_vq(ctx->m2m_ctx, buf->type);
vb2_v4l2 = to_vb2_v4l2_buffer(vq->bufs[buf->index]);
aml_buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb);
@@ -1387,7 +1398,6 @@ static int vidioc_vdec_dqbuf(struct file *file, void *priv,
(ulong) v4l_get_vf_handle(vb2_v4l2->private));
}
fput(file);
- mutex_unlock(&ctx->lock);
}
return ret;
@@ -2288,8 +2298,9 @@ static void vb2ops_vdec_stop_streaming(struct vb2_queue *q)
if (ctx->is_drm_mode && q->memory == VB2_MEMORY_DMABUF)
aml_recycle_dma_buffers(ctx);
} else {
- /* stop decoder. */
- wait_vcodec_ending(ctx);
+ /* clean output cache and decoder status . */
+ if (ctx->state > AML_STATE_INIT)
+ aml_vdec_reset(ctx);
for (i = 0; i < q->num_buffers; ++i) {
vb2_v4l2 = to_vb2_v4l2_buffer(q->bufs[i]);
@@ -2316,7 +2327,8 @@ static void m2mops_vdec_device_run(void *priv)
struct aml_vcodec_ctx *ctx = priv;
struct aml_vcodec_dev *dev = ctx->dev;
- queue_work(dev->decode_workqueue, &ctx->decode_work);
+ if (ctx->output_thread_ready)
+ queue_work(dev->decode_workqueue, &ctx->decode_work);
}
void vdec_device_vf_run(struct aml_vcodec_ctx *ctx)
diff --git a/drivers/amvdec_ports/aml_vcodec_dec_drv.c b/drivers/amvdec_ports/aml_vcodec_dec_drv.c
index b9febb6..a9363cd 100644
--- a/drivers/amvdec_ports/aml_vcodec_dec_drv.c
+++ b/drivers/amvdec_ports/aml_vcodec_dec_drv.c
@@ -108,6 +108,7 @@ static int fops_vcodec_open(struct file *file)
}
src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx,
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+ ctx->output_thread_ready = true;
ctx->empty_flush_buf->vb.vb2_buf.vb2_queue = src_vq;
ctx->empty_flush_buf->lastframe = true;
aml_vcodec_dec_set_default_params(ctx);
diff --git a/drivers/amvdec_ports/aml_vcodec_drv.h b/drivers/amvdec_ports/aml_vcodec_drv.h
index f66052f..3d20430 100644
--- a/drivers/amvdec_ports/aml_vcodec_drv.h
+++ b/drivers/amvdec_ports/aml_vcodec_drv.h
@@ -71,6 +71,14 @@
#define V4L_RESET_MODE_NORMAL (1 << 0) /* reset vdec_input and decoder. */
#define V4L_RESET_MODE_LIGHT (1 << 1) /* just only reset decoder. */
+/* m2m job queue's status */
+/* Instance is already queued on the job_queue */
+#define TRANS_QUEUED (1 << 0)
+/* Instance is currently running in hardware */
+#define TRANS_RUNNING (1 << 1)
+/* Instance is currently aborting */
+#define TRANS_ABORT (1 << 2)
+
/**
* enum aml_hw_reg_idx - AML hw register base index
*/
@@ -373,99 +381,93 @@ struct aml_vdec_thread {
/**
* struct aml_vcodec_ctx - Context (instance) private data.
*
- * @type: type of the instance - decoder or encoder
- * @dev: pointer to the aml_vcodec_dev of the device
- * @list: link to ctx_list of aml_vcodec_dev
- * @fh: struct v4l2_fh
- * @m2m_ctx: pointer to the v4l2_m2m_ctx of the context
- * @q_data: store information of input and output queue
- * of the context
- * @id: index of the context that this structure describes
- * @state: state of the context
- * @param_change: indicate encode parameter type
- * @enc_params: encoding parameters
- * @dec_if: hooked decoder driver interface
- * @enc_if: hoooked encoder driver interface
- * @drv_handle: driver handle for specific decode/encode instance
- *
- * @picinfo: store picture info after header parsing
+ * @id: index of the context that this structure describes.
+ * @type: type of the instance - decoder or encoder.
+ * @dev: pointer to the aml_vcodec_dev of the device.
+ * @m2m_ctx: pointer to the v4l2_m2m_ctx of the context.
+ * @ada_ctx: pointer to the aml_vdec_adapt of the context.
+ * @dec_if: hooked decoder driver interface.
+ * @drv_handle: driver handle for specific decode instance
+ * @fh: struct v4l2_fh.
+ * @ctrl_hdl: handler for v4l2 framework.
+ * @slock: protect v4l2 codec context.
+ * @empty_flush_buf: a fake size-0 capture buffer that indicates flush.
+ * @list: link to ctx_list of aml_vcodec_dev.
+ * @q_data: store information of input and output queue of the context.
+ * @queue: waitqueue that can be used to wait for this context to finish.
+ * @lock: protect the vdec thread.
+ * @state_lock: protect the codec status.
+ * @state: state of the context.
+ * @decode_work: decoder work be used to output buffer.
+ * @output_thread_ready: indicate the output thread ready.
+ * @cap_pool: capture buffers are remark in the pool.
+ * @vdec_thread_list: vdec thread be used to capture.
* @dpb_size: store dpb count after header parsing
- * @int_cond: variable used by the waitqueue
- * @int_type: type of the last interrupt
- * @queue: waitqueue that can be used to wait for this context to
- * finish
- * @irq_status: irq status
- *
- * @ctrl_hdl: handler for v4l2 framework
- * @decode_work: worker for the decoding
- * @encode_work: worker for the encoding
- * @last_decoded_picinfo: pic information get from latest decode
- * @empty_flush_buf: a fake size-0 capture buffer that indicates flush
- *
- * @colorspace: enum v4l2_colorspace; supplemental to pixelformat
- * @ycbcr_enc: enum v4l2_ycbcr_encoding, Y'CbCr encoding
- * @quantization: enum v4l2_quantization, colorspace quantization
- * @xfer_func: enum v4l2_xfer_func, colorspace transfer function
- * @lock: protect variables accessed by V4L2 threads and worker thread such as
- * aml_video_dec_buf.
+ * @param_change: indicate encode parameter type
+ * @param_sets_from_ucode: if true indicate ps from ucode.
+ * @v4l_codec_dpb_ready: queue buffer number greater than dpb.
+ * @comp: comp be used for sync picture information with decoder.
+ * @config: used to set or get parms for application.
+ * @picinfo: store picture info after header parsing.
+ * @last_decoded_picinfo: pic information get from latest decode.
+ * @colorspace: enum v4l2_colorspace; supplemental to pixelformat.
+ * @ycbcr_enc: enum v4l2_ycbcr_encoding, Y'CbCr encoding.
+ * @quantization: enum v4l2_quantization, colorspace quantization.
+ * @xfer_func: enum v4l2_xfer_func, colorspace transfer function.
+ * @cap_pix_fmt: the picture format used to switch nv21 or nv12.
+ * @has_receive_eos: if receive last frame of capture that be set.
+ * @is_drm_mode: decoding work on drm mode if that set.
+ * @is_stream_mode: vdec input used to stream mode, default frame mode.
+ * @is_stream_off: the value used to handle reset active.
+ * @receive_cmd_stop: if receive the cmd flush decoder.
+ * @reset_flag: reset mode includes lightly and normal mode.
+ * @decoded_frame_cnt: the capture buffer deque number to be count.
+ * @buf_used_count: means that decode allocate how many buffs from v4l.
*/
struct aml_vcodec_ctx {
- enum aml_instance_type type;
- struct aml_vcodec_dev *dev;
- struct list_head list;
-
- struct v4l2_fh fh;
- struct v4l2_m2m_ctx *m2m_ctx;
- struct aml_vdec_adapt *ada_ctx;
- struct aml_q_data q_data[2];
- int id;
- struct mutex state_lock;
- enum aml_instance_state state;
- enum aml_encode_param param_change;
- struct aml_enc_params enc_params;
-
- const struct vdec_common_if *dec_if;
- const struct venc_common_if *enc_if;
- unsigned long drv_handle;
-
- struct vdec_pic_info picinfo;
- int dpb_size;
-
- int int_cond;
- int int_type;
- wait_queue_head_t queue;
- unsigned int irq_status;
-
- struct v4l2_ctrl_handler ctrl_hdl;
- struct work_struct decode_work;
- struct work_struct encode_work;
- struct vdec_pic_info last_decoded_picinfo;
- struct aml_video_dec_buf *empty_flush_buf;
-
- enum v4l2_colorspace colorspace;
- enum v4l2_ycbcr_encoding ycbcr_enc;
- enum v4l2_quantization quantization;
- enum v4l2_xfer_func xfer_func;
-
- int decoded_frame_cnt;
- struct mutex lock;
- struct completion comp;
- bool has_receive_eos;
- struct list_head vdec_thread_list;
- bool is_drm_mode;
- bool is_stream_mode;
- int buf_used_count;
- bool receive_cmd_stop;
- bool param_sets_from_ucode;
- bool v4l_codec_dpb_ready;
- spinlock_t slock;
- struct v4l2_config_parm config;
- bool is_stream_off;
- int reset_flag;
- int stop_cmd;
- u32 display_count;
- struct v4l_buff_pool cap_pool;
- u32 cap_pix_fmt;
+ int id;
+ enum aml_instance_type type;
+ struct aml_vcodec_dev *dev;
+ struct v4l2_m2m_ctx *m2m_ctx;
+ struct aml_vdec_adapt *ada_ctx;
+ const struct vdec_common_if *dec_if;
+ ulong drv_handle;
+ struct v4l2_fh fh;
+ struct v4l2_ctrl_handler ctrl_hdl;
+ spinlock_t slock;
+ struct aml_video_dec_buf *empty_flush_buf;
+ struct list_head list;
+
+ struct aml_q_data q_data[2];
+ wait_queue_head_t queue;
+ struct mutex lock, state_lock;
+ enum aml_instance_state state;
+ struct work_struct decode_work;
+ bool output_thread_ready;
+ struct v4l_buff_pool cap_pool;
+ struct list_head vdec_thread_list;
+
+ int dpb_size;
+ bool param_sets_from_ucode;
+ bool v4l_codec_dpb_ready;
+ struct completion comp;
+ struct v4l2_config_parm config;
+ struct vdec_pic_info picinfo;
+ struct vdec_pic_info last_decoded_picinfo;
+ enum v4l2_colorspace colorspace;
+ enum v4l2_ycbcr_encoding ycbcr_enc;
+ enum v4l2_quantization quantization;
+ enum v4l2_xfer_func xfer_func;
+ u32 cap_pix_fmt;
+
+ bool has_receive_eos;
+ bool is_drm_mode;
+ bool is_stream_mode;
+ bool is_stream_off;
+ bool receive_cmd_stop;
+ int reset_flag;
+ int decoded_frame_cnt;
+ int buf_used_count;
};
/**