Media drivers that use the videobuf2 framework have to give back to vb2
all the buffers that received from vb2 using its .buf_queue callback.
But the exynos-gsc driver isn't doing a proper cleanup so vb2 complains
that the number of buffers enqueued and received are not balanced:
WARNING: CPU: 2 PID: 660 at drivers/media/v4l2-core/videobuf2-core.c:1654 __vb2_queue_cancel+0xec/0x150 [videobuf2_core]
Modules linked in: mwifiex_sdio mwifiex uvcvideo exynos_gsc videobuf2_vmalloc s5p_mfc s5p_jpeg
CPU: 2 PID: 660 Comm: lt-gst-validate Not tainted 4.8.0
Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
[<
c010e24c>] (unwind_backtrace) from [<
c010af30>] (show_stack+0x10/0x14)
[<
c010af30>] (show_stack) from [<
c03291a4>] (dump_stack+0x88/0x9c)
[<
c03291a4>] (dump_stack) from [<
c011a858>] (__warn+0xe8/0x100)
[<
c011a858>] (__warn) from [<
c011a920>] (warn_slowpath_null+0x20/0x28)
[<
c011a920>] (warn_slowpath_null) from [<
bf0b6ed0>] (__vb2_queue_cancel+0xec/0x150 [videobuf2_core])
[<
bf0b6ed0>] (__vb2_queue_cancel [videobuf2_core]) from [<
bf0b7464>] (vb2_core_streamoff+0x34/0x9c [videobuf2_core])
[<
bf0b7464>] (vb2_core_streamoff [videobuf2_core]) from [<
bf11b9e8>] (v4l2_m2m_streamoff+0x2c/0xe4 [v4l2_mem2mem])
[<
bf11b9e8>] (v4l2_m2m_streamoff [v4l2_mem2mem]) from [<
bf01b84c>] (__video_do_ioctl+0x298/0x30c [videodev])
[<
bf01b84c>] (__video_do_ioctl [videodev]) from [<
bf01b234>] (video_usercopy+0x174/0x4e8 [videodev])
[<
bf01b234>] (video_usercopy [videodev]) from [<
bf0165c8>] (v4l2_ioctl+0xc4/0xd8 [videodev])
[<
bf0165c8>] (v4l2_ioctl [videodev]) from [<
c01f291c>] (do_vfs_ioctl+0x9c/0x8f4)
[<
c01f291c>] (do_vfs_ioctl) from [<
c01f31a8>] (SyS_ioctl+0x34/0x5c)
[<
c01f31a8>] (SyS_ioctl) from [<
c01078c0>] (ret_fast_syscall+0x0/0x3c)
Fix this by passing back to vb2 all the received buffers that were not
processed.
Signed-off-by: Javier Martinez Canillas <javier@osg.samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
return ret > 0 ? 0 : ret;
}
+static void __gsc_m2m_cleanup_queue(struct gsc_ctx *ctx)
+{
+ struct vb2_v4l2_buffer *src_vb, *dst_vb;
+
+ while (v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) > 0) {
+ src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+ v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_ERROR);
+ }
+
+ while (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) > 0) {
+ dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+ v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_ERROR);
+ }
+}
+
static void gsc_m2m_stop_streaming(struct vb2_queue *q)
{
struct gsc_ctx *ctx = q->drv_priv;
__gsc_m2m_job_abort(ctx);
+ __gsc_m2m_cleanup_queue(ctx);
+
pm_runtime_put(&ctx->gsc_dev->pdev->dev);
}