| From 627530c32a43283474e9dd3e954519410ffa033a Mon Sep 17 00:00:00 2001 |
| From: Frank Schaefer <fschaefer.oss@googlemail.com> |
| Date: Sat, 9 Aug 2014 06:37:20 -0300 |
| Subject: media: em28xx-v4l: give back all active video buffers to the vb2 core properly on streaming stop |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Frank Schaefer <fschaefer.oss@googlemail.com> |
| |
| commit 627530c32a43283474e9dd3e954519410ffa033a upstream. |
| |
| When a new video frame is started, the driver takes the next video buffer from |
| the list of active buffers and moves it to dev->usb_ctl.vid_buf / dev->usb_ctl.vbi_buf |
| for further processing. |
| |
| On streaming stop we currently only give back the pending buffers from the list |
| but not the ones which are currently processed. |
| |
| This causes the following warning from the vb2 core since kernel 3.15: |
| |
| ... |
| ------------[ cut here ]------------ |
| WARNING: CPU: 1 PID: 2284 at drivers/media/v4l2-core/videobuf2-core.c:2115 __vb2_queue_cancel+0xed/0x150 [videobuf2_core]() |
| [...] |
| Call Trace: |
| [<c0769c46>] dump_stack+0x48/0x69 |
| [<c0245b69>] warn_slowpath_common+0x79/0x90 |
| [<f925e4ad>] ? __vb2_queue_cancel+0xed/0x150 [videobuf2_core] |
| [<f925e4ad>] ? __vb2_queue_cancel+0xed/0x150 [videobuf2_core] |
| [<c0245bfd>] warn_slowpath_null+0x1d/0x20 |
| [<f925e4ad>] __vb2_queue_cancel+0xed/0x150 [videobuf2_core] |
| [<f925fa35>] vb2_internal_streamoff+0x35/0x90 [videobuf2_core] |
| [<f925fac5>] vb2_streamoff+0x35/0x60 [videobuf2_core] |
| [<f925fb27>] vb2_ioctl_streamoff+0x37/0x40 [videobuf2_core] |
| [<f8e45895>] v4l_streamoff+0x15/0x20 [videodev] |
| [<f8e4925d>] __video_do_ioctl+0x23d/0x2d0 [videodev] |
| [<f8e49020>] ? video_ioctl2+0x20/0x20 [videodev] |
| [<f8e48c63>] video_usercopy+0x203/0x5a0 [videodev] |
| [<f8e49020>] ? video_ioctl2+0x20/0x20 [videodev] |
| [<c039d0e7>] ? fsnotify+0x1e7/0x2b0 |
| [<f8e49012>] video_ioctl2+0x12/0x20 [videodev] |
| [<f8e49020>] ? video_ioctl2+0x20/0x20 [videodev] |
| [<f8e4461e>] v4l2_ioctl+0xee/0x130 [videodev] |
| [<f8e44530>] ? v4l2_open+0xf0/0xf0 [videodev] |
| [<c0378de2>] do_vfs_ioctl+0x2e2/0x4d0 |
| [<c0368eec>] ? vfs_write+0x13c/0x1c0 |
| [<c0369a8f>] ? vfs_writev+0x2f/0x50 |
| [<c0379028>] SyS_ioctl+0x58/0x80 |
| [<c076fff3>] sysenter_do_call+0x12/0x12 |
| ---[ end trace 5545f934409f13f4 ]--- |
| ... |
| |
| Many thanks to Hans Verkuil, whose recently added check in the vb2 core unveiled |
| this long standing issue and who has investigated it further. |
| |
| Signed-off-by: Frank Schรคfer <fschaefer.oss@googlemail.com> |
| Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/media/usb/em28xx/em28xx-video.c | 10 ++++++++-- |
| 1 file changed, 8 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/media/usb/em28xx/em28xx-video.c |
| +++ b/drivers/media/usb/em28xx/em28xx-video.c |
| @@ -994,13 +994,16 @@ static void em28xx_stop_streaming(struct |
| } |
| |
| spin_lock_irqsave(&dev->slock, flags); |
| + if (dev->usb_ctl.vid_buf != NULL) { |
| + vb2_buffer_done(&dev->usb_ctl.vid_buf->vb, VB2_BUF_STATE_ERROR); |
| + dev->usb_ctl.vid_buf = NULL; |
| + } |
| while (!list_empty(&vidq->active)) { |
| struct em28xx_buffer *buf; |
| buf = list_entry(vidq->active.next, struct em28xx_buffer, list); |
| list_del(&buf->list); |
| vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); |
| } |
| - dev->usb_ctl.vid_buf = NULL; |
| spin_unlock_irqrestore(&dev->slock, flags); |
| } |
| |
| @@ -1021,13 +1024,16 @@ void em28xx_stop_vbi_streaming(struct vb |
| } |
| |
| spin_lock_irqsave(&dev->slock, flags); |
| + if (dev->usb_ctl.vbi_buf != NULL) { |
| + vb2_buffer_done(&dev->usb_ctl.vbi_buf->vb, VB2_BUF_STATE_ERROR); |
| + dev->usb_ctl.vbi_buf = NULL; |
| + } |
| while (!list_empty(&vbiq->active)) { |
| struct em28xx_buffer *buf; |
| buf = list_entry(vbiq->active.next, struct em28xx_buffer, list); |
| list_del(&buf->list); |
| vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); |
| } |
| - dev->usb_ctl.vbi_buf = NULL; |
| spin_unlock_irqrestore(&dev->slock, flags); |
| } |
| |