Skip to content

Commit f729ef5

Browse files
Hans Verkuilmchehab
authored andcommitted
media: videobuf2-v4l2.c: add vb2_video_unregister_device helper function
If a driver calls (_)vb2_fop_release(), then such a driver should also call vb2_video_unregister_device() instead of video_unregister_device(). This helper will call vb2_queue_release() if a filehandle is marked as owner of the queue. This ensures that at unregister time any streaming is cancelled and all buffers are returned to userspace. This is very useful for complex drivers since this stops all streaming in all subdevs in the pipeline controlled by this video device. Otherwise this would be delayed until the owner filehandle is closed, which can be quite some time later. Bonus points for ordering the includes :-) Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
1 parent 0832e07 commit f729ef5

File tree

2 files changed

+62
-6
lines changed

2 files changed

+62
-6
lines changed

drivers/media/common/videobuf2/videobuf2-v4l2.c

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,22 @@
1414
* the Free Software Foundation.
1515
*/
1616

17+
#include <linux/device.h>
1718
#include <linux/err.h>
19+
#include <linux/freezer.h>
1820
#include <linux/kernel.h>
19-
#include <linux/module.h>
21+
#include <linux/kthread.h>
2022
#include <linux/mm.h>
23+
#include <linux/module.h>
2124
#include <linux/poll.h>
22-
#include <linux/slab.h>
2325
#include <linux/sched.h>
24-
#include <linux/freezer.h>
25-
#include <linux/kthread.h>
26+
#include <linux/slab.h>
2627

28+
#include <media/v4l2-common.h>
2729
#include <media/v4l2-dev.h>
2830
#include <media/v4l2-device.h>
29-
#include <media/v4l2-fh.h>
3031
#include <media/v4l2-event.h>
31-
#include <media/v4l2-common.h>
32+
#include <media/v4l2-fh.h>
3233

3334
#include <media/videobuf2-v4l2.h>
3435

@@ -1234,6 +1235,44 @@ unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
12341235
EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area);
12351236
#endif
12361237

1238+
void vb2_video_unregister_device(struct video_device *vdev)
1239+
{
1240+
/* Check if vdev was ever registered at all */
1241+
if (!vdev || !video_is_registered(vdev))
1242+
return;
1243+
1244+
/*
1245+
* Calling this function only makes sense if vdev->queue is set.
1246+
* If it is NULL, then just call video_unregister_device() instead.
1247+
*/
1248+
WARN_ON(!vdev->queue);
1249+
1250+
/*
1251+
* Take a reference to the device since video_unregister_device()
1252+
* calls device_unregister(), but we don't want that to release
1253+
* the device since we want to clean up the queue first.
1254+
*/
1255+
get_device(&vdev->dev);
1256+
video_unregister_device(vdev);
1257+
if (vdev->queue && vdev->queue->owner) {
1258+
struct mutex *lock = vdev->queue->lock ?
1259+
vdev->queue->lock : vdev->lock;
1260+
1261+
if (lock)
1262+
mutex_lock(lock);
1263+
vb2_queue_release(vdev->queue);
1264+
vdev->queue->owner = NULL;
1265+
if (lock)
1266+
mutex_unlock(lock);
1267+
}
1268+
/*
1269+
* Now we put the device, and in most cases this will release
1270+
* everything.
1271+
*/
1272+
put_device(&vdev->dev);
1273+
}
1274+
EXPORT_SYMBOL_GPL(vb2_video_unregister_device);
1275+
12371276
/* vb2_ops helpers. Only use if vq->lock is non-NULL. */
12381277

12391278
void vb2_ops_wait_prepare(struct vb2_queue *vq)

include/media/videobuf2-v4l2.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#error VB2_MAX_PLANES != VIDEO_MAX_PLANES
2424
#endif
2525

26+
struct video_device;
27+
2628
/**
2729
* struct vb2_v4l2_buffer - video buffer information for v4l2.
2830
*
@@ -319,6 +321,21 @@ unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
319321
unsigned long len, unsigned long pgoff, unsigned long flags);
320322
#endif
321323

324+
/**
325+
* vb2_video_unregister_device - unregister the video device and release queue
326+
*
327+
* @vdev: pointer to &struct video_device
328+
*
329+
* If the driver uses vb2_fop_release()/_vb2_fop_release(), then it should use
330+
* vb2_video_unregister_device() instead of video_unregister_device().
331+
*
332+
* This function will call video_unregister_device() and then release the
333+
* vb2_queue if streaming is in progress. This will stop streaming and
334+
* this will simplify the unbind sequence since after this call all subdevs
335+
* will have stopped streaming as well.
336+
*/
337+
void vb2_video_unregister_device(struct video_device *vdev);
338+
322339
/**
323340
* vb2_ops_wait_prepare - helper function to lock a struct &vb2_queue
324341
*

0 commit comments

Comments
 (0)