Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] vb2: fix 'UNBALANCED' warnings when calling vb2_thread_stop()

Stopping the vb2 thread (as used by several DVB devices) can result
in an 'UNBALANCED' warning such as this:

vb2: counters for queue ffff880407ee9828: UNBALANCED!
vb2: setup: 1 start_streaming: 1 stop_streaming: 1
vb2: wait_prepare: 249333 wait_finish: 249334

This is due to a race condition between stopping the thread and
calling vb2_internal_streamoff(). While I have not been able to deduce
the exact mechanism how this race condition can produce this warning,
I can see that the way the stream is stopped is likely to lead to a
race somewhere.

This patch simplifies how this is done by first ensuring that the
thread is completely stopped before cleaning up the vb2 queue. It
does that by setting threadio->stop to true, followed by a call to
vb2_queue_error() which will wake up the thread. The thread sees that
'stop' is true and it will exit.

The call to kthread_stop() waits until the thread has exited, and only
then is the queue cleaned up by calling __vb2_cleanup_fileio().

This is a much cleaner sequence and the warning has now disappeared.

Reported-by: Jurgen Kramer <gtmkramer@xs4all.nl>
Tested-by: Jurgen Kramer <gtmkramer@xs4all.nl>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Cc: <stable@vger.kernel.org> # for v3.18 and up
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>

authored by

Hans Verkuil and committed by
Mauro Carvalho Chehab
0e661006 c517d838

+3 -8
+3 -8
drivers/media/v4l2-core/videobuf2-core.c
··· 3230 3230 3231 3231 if (threadio == NULL) 3232 3232 return 0; 3233 - call_void_qop(q, wait_finish, q); 3234 3233 threadio->stop = true; 3235 - vb2_internal_streamoff(q, q->type); 3236 - call_void_qop(q, wait_prepare, q); 3234 + /* Wake up all pending sleeps in the thread */ 3235 + vb2_queue_error(q); 3237 3236 err = kthread_stop(threadio->thread); 3238 - q->fileio = NULL; 3239 - fileio->req.count = 0; 3240 - vb2_reqbufs(q, &fileio->req); 3241 - kfree(fileio); 3237 + __vb2_cleanup_fileio(q); 3242 3238 threadio->thread = NULL; 3243 3239 kfree(threadio); 3244 - q->fileio = NULL; 3245 3240 q->threadio = NULL; 3246 3241 return err; 3247 3242 }