Skip to content

Commit

Permalink
media: videobuf2-v4l2.c: add vb2_video_unregister_device helper function
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Hans Verkuil authored and Mauro Carvalho Chehab committed Aug 28, 2020
1 parent 0832e07 commit f729ef5
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 6 deletions.
51 changes: 45 additions & 6 deletions drivers/media/common/videobuf2/videobuf2-v4l2.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,22 @@
* the Free Software Foundation.
*/

#include <linux/device.h>
#include <linux/err.h>
#include <linux/freezer.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kthread.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/freezer.h>
#include <linux/kthread.h>
#include <linux/slab.h>

#include <media/v4l2-common.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fh.h>
#include <media/v4l2-event.h>
#include <media/v4l2-common.h>
#include <media/v4l2-fh.h>

#include <media/videobuf2-v4l2.h>

Expand Down Expand Up @@ -1234,6 +1235,44 @@ unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area);
#endif

void vb2_video_unregister_device(struct video_device *vdev)
{
/* Check if vdev was ever registered at all */
if (!vdev || !video_is_registered(vdev))
return;

/*
* Calling this function only makes sense if vdev->queue is set.
* If it is NULL, then just call video_unregister_device() instead.
*/
WARN_ON(!vdev->queue);

/*
* Take a reference to the device since video_unregister_device()
* calls device_unregister(), but we don't want that to release
* the device since we want to clean up the queue first.
*/
get_device(&vdev->dev);
video_unregister_device(vdev);
if (vdev->queue && vdev->queue->owner) {
struct mutex *lock = vdev->queue->lock ?
vdev->queue->lock : vdev->lock;

if (lock)
mutex_lock(lock);
vb2_queue_release(vdev->queue);
vdev->queue->owner = NULL;
if (lock)
mutex_unlock(lock);
}
/*
* Now we put the device, and in most cases this will release
* everything.
*/
put_device(&vdev->dev);
}
EXPORT_SYMBOL_GPL(vb2_video_unregister_device);

/* vb2_ops helpers. Only use if vq->lock is non-NULL. */

void vb2_ops_wait_prepare(struct vb2_queue *vq)
Expand Down
17 changes: 17 additions & 0 deletions include/media/videobuf2-v4l2.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#error VB2_MAX_PLANES != VIDEO_MAX_PLANES
#endif

struct video_device;

/**
* struct vb2_v4l2_buffer - video buffer information for v4l2.
*
Expand Down Expand Up @@ -319,6 +321,21 @@ unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
unsigned long len, unsigned long pgoff, unsigned long flags);
#endif

/**
* vb2_video_unregister_device - unregister the video device and release queue
*
* @vdev: pointer to &struct video_device
*
* If the driver uses vb2_fop_release()/_vb2_fop_release(), then it should use
* vb2_video_unregister_device() instead of video_unregister_device().
*
* This function will call video_unregister_device() and then release the
* vb2_queue if streaming is in progress. This will stop streaming and
* this will simplify the unbind sequence since after this call all subdevs
* will have stopped streaming as well.
*/
void vb2_video_unregister_device(struct video_device *vdev);

/**
* vb2_ops_wait_prepare - helper function to lock a struct &vb2_queue
*
Expand Down

0 comments on commit f729ef5

Please sign in to comment.