From a07ad088b167db11d9ed11f964d3ada002663266 Mon Sep 17 00:00:00 2001 From: jintao xu Date: Tue, 7 May 2019 11:09:04 +0800 Subject: [PATCH] ionvideo: fix latency and crash [1/1] PD#SWPL-8069 Problem: 1.about 2ms latency due to sleep 2.crash while poll ionvideo Solution: 1.use semaphore instead of sleep 2.fix poll function 3.add trace info for ionvideo Verify: U212 Change-Id: Idde64151541d826ba6a6cd1abcc901e80f0e4b45 Signed-off-by: jintao xu --- drivers/amlogic/debug/meson_atrace.c | 1 + .../media/video_processor/ionvideo/ionvideo.c | 55 +++++++++++++++++----- .../media/video_processor/ionvideo/ionvideo.h | 1 + include/trace/events/meson_atrace.h | 3 +- 4 files changed, 48 insertions(+), 12 deletions(-) diff --git a/drivers/amlogic/debug/meson_atrace.c b/drivers/amlogic/debug/meson_atrace.c index 0127977..2e67dc6 100644 --- a/drivers/amlogic/debug/meson_atrace.c +++ b/drivers/amlogic/debug/meson_atrace.c @@ -32,6 +32,7 @@ struct { TAG_INFO(CODEC_MM), TAG_INFO(VDEC), TAG_INFO(TSYNC), + TAG_INFO(IONVIDEO), { NULL, 0 } }; diff --git a/drivers/amlogic/media/video_processor/ionvideo/ionvideo.c b/drivers/amlogic/media/video_processor/ionvideo/ionvideo.c index c89143c..a06190f 100644 --- a/drivers/amlogic/media/video_processor/ionvideo/ionvideo.c +++ b/drivers/amlogic/media/video_processor/ionvideo/ionvideo.c @@ -25,7 +25,8 @@ #include #include #include - +#define KERNEL_ATRACE_TAG KERNEL_ATRACE_TAG_IONVIDEO +#include #define IONVIDEO_MODULE_NAME "ionvideo" #define IONVIDEO_VERSION "1.0" @@ -389,8 +390,6 @@ static void ionvideo_thread_tick(struct ionvideo_dev *dev) vf = vf_peek(dev->vf_receiver_name); if (!vf) { dev->vf_wait_cnt++; - /* msleep(5); */ - usleep_range(1000, 2000); return; } dev->ppmgr2_dev.dst_width = dev->width; @@ -407,7 +406,7 @@ static void ionvideo_thread_tick(struct ionvideo_dev *dev) } if (dev->freerun_mode == 0 && ionvideo_size_changed(dev, w, h)) { /* msleep(10); */ - usleep_range(4000, 5000); + /*usleep_range(4000, 5000);*/ return; } mutex_lock(&dev->mutex_input); @@ -415,7 +414,6 @@ static void ionvideo_thread_tick(struct ionvideo_dev *dev) if (buf == NULL) { dprintk(dev, 3, "No active queue to serve\n"); mutex_unlock(&dev->mutex_input); - schedule_timeout_interruptible(msecs_to_jiffies(20)); return; } mutex_unlock(&dev->mutex_input); @@ -431,6 +429,8 @@ static void ionvideo_thread_tick(struct ionvideo_dev *dev) v4l2q_push(&dev->output_queue, buf); dma_q->vb_ready++; mutex_unlock(&dev->mutex_output); + ATRACE_COUNTER(dev->v4l2_dev.name, dma_q->vb_ready); + wake_up_interruptible(&dma_q->wq_poll); dprintk(dev, 4, "[%p/%d] done\n", buf, buf->index); } @@ -441,22 +441,33 @@ static void ionvideo_sleep(struct ionvideo_dev *dev) { struct ionvideo_dmaqueue *dma_q = &dev->vidq; /* int timeout; */ - DECLARE_WAITQUEUE(wait, current); + /*DECLARE_WAITQUEUE(wait, current);*/ dprintk(dev, 4, "%s dma_q=0x%08lx\n", __func__, (unsigned long)dma_q); - add_wait_queue(&dma_q->wq, &wait); + /*add_wait_queue(&dma_q->wq, &wait);*/ if (kthread_should_stop()) goto stop_task; /* Calculate time to wake up */ /* timeout = msecs_to_jiffies(frames_to_ms(1)); */ + if (vf_peek(dev->vf_receiver_name) == NULL + || v4l2q_peek(&dev->input_queue) == NULL) { + wait_event_interruptible_timeout( + dma_q->wq, + (vf_peek(dev->vf_receiver_name) != NULL) + && (v4l2q_peek(&dev->input_queue) != NULL), + msecs_to_jiffies(5)); + } + ATRACE_BEGIN("ionvideo_thread_tick"); ionvideo_thread_tick(dev); + ATRACE_END(); /* schedule_timeout_interruptible(timeout); */ -stop_task: remove_wait_queue(&dma_q->wq, &wait); +stop_task: + /*remove_wait_queue(&dma_q->wq, &wait);*/ try_to_freeze(); } @@ -476,7 +487,6 @@ static int ionvideo_thread(void *data) break; } dev->thread_stopped = 1; - wake_up_interruptible(&dev->wq); dprintk(dev, 2, "thread: exit\n"); return 0; } @@ -695,6 +705,21 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, return 0; } +static unsigned int vidioc_poll(struct file *file, + struct poll_table_struct *wait) +{ + struct ionvideo_dev *dev = video_drvdata(file); + struct ionvideo_dmaqueue *dma_q = &dev->vidq; + + if (dma_q->vb_ready > 0) + return POLL_IN | POLLRDNORM; + poll_wait(file, &dma_q->wq_poll, wait); + if (dma_q->vb_ready > 0) + return POLL_IN | POLLRDNORM; + else + return 0; +} + static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) { struct ionvideo_dev *dev = video_drvdata(file); @@ -868,6 +893,7 @@ static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) if (out_put != NULL) { dma_q->vb_ready--; *p = *out_put; + ATRACE_COUNTER(dev->v4l2_dev.name, dma_q->vb_ready); } else { mutex_unlock(&dev->mutex_output); return -EAGAIN; @@ -887,7 +913,7 @@ static const struct v4l2_file_operations ionvideo_v4l2_fops = { .open = vidioc_open, .release = vidioc_close, .read = vb2_fop_read, - .poll = vb2_fop_poll, + .poll = vidioc_poll, .unlocked_ioctl = video_ioctl2,/* V4L2 ioctl handler */ .mmap = vb2_fop_mmap, }; @@ -951,6 +977,7 @@ static int ionvideo_v4l2_release(void) static int video_receiver_event_fun(int type, void *data, void *private_data) { struct ionvideo_dev *dev = (struct ionvideo_dev *)private_data; + struct ionvideo_dmaqueue *dma_q = &dev->vidq; int timeout = 0; if (type == VFRAME_EVENT_PROVIDER_UNREG) { dev->receiver_register = 0; @@ -992,8 +1019,13 @@ static int video_receiver_event_fun(int type, void *data, void *private_data) set_vframe_rate_end_hint(); } #endif + } else if (type == VFRAME_EVENT_PROVIDER_VFRAME_READY) { + wake_up_interruptible(&dma_q->wq); + return 0; + } else if (type == VFRAME_EVENT_PROVIDER_RESET) { + wake_up_interruptible(&dma_q->wq); + return 0; } - return 0; } @@ -1034,6 +1066,7 @@ static int __init ionvideo_create_instance(int inst) /* init video dma queues */ INIT_LIST_HEAD(&dev->vidq.active); init_waitqueue_head(&dev->vidq.wq); + init_waitqueue_head(&dev->vidq.wq_poll); dev->vidq.pdev = dev; vfd = &dev->vdev; diff --git a/drivers/amlogic/media/video_processor/ionvideo/ionvideo.h b/drivers/amlogic/media/video_processor/ionvideo/ionvideo.h index edbfffe..f754d21 100644 --- a/drivers/amlogic/media/video_processor/ionvideo/ionvideo.h +++ b/drivers/amlogic/media/video_processor/ionvideo/ionvideo.h @@ -195,6 +195,7 @@ struct ionvideo_dmaqueue { /* thread for generating video stream*/ struct task_struct *kthread; wait_queue_head_t wq; + wait_queue_head_t wq_poll; /* Counters to control fps rate */ int vb_ready; struct ionvideo_dev *pdev; diff --git a/include/trace/events/meson_atrace.h b/include/trace/events/meson_atrace.h index d6f2196..1baade7 100644 --- a/include/trace/events/meson_atrace.h +++ b/include/trace/events/meson_atrace.h @@ -42,6 +42,7 @@ enum { KERNEL_ATRACE_TAG_CODEC_MM, KERNEL_ATRACE_TAG_VDEC, KERNEL_ATRACE_TAG_TSYNC, + KERNEL_ATRACE_TAG_IONVIDEO, KERNEL_ATRACE_TAG_MAX = 64, KERNEL_ATRACE_TAG_ALL }; @@ -96,7 +97,7 @@ void meson_atrace(int tag, const char *name, unsigned int flags, #define ATRACE_BEGIN(name) \ meson_atrace(KERNEL_ATRACE_TAG, name, \ (1 << KERNEL_ATRACE_BEGIN), 0) -#define ATRACE_END(name) \ +#define ATRACE_END() \ meson_atrace(KERNEL_ATRACE_TAG, "", \ (1 << KERNEL_ATRACE_END), 1) #define ATRACE_ASYNC_BEGIN(name, cookie) \ -- 2.7.4