diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index a593ea0598b551b45f0bb0b594f9e9086b415cee..0ddc3554f1a4cb5778cc8d2737c5449e27fb746c 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -28,6 +28,7 @@ #include <media/v4l2-common.h> #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> +#include <media/v4l2-event.h> #define VIDEO_NUM_DEVICES 256 #define VIDEO_NAME "video4linux" @@ -1086,6 +1087,8 @@ void video_unregister_device(struct video_device *vdev) */ clear_bit(V4L2_FL_REGISTERED, &vdev->flags); mutex_unlock(&videodev_lock); + if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags)) + v4l2_event_wake_all(vdev); device_unregister(&vdev->dev); } EXPORT_SYMBOL(video_unregister_device); diff --git a/drivers/media/v4l2-core/v4l2-event.c b/drivers/media/v4l2-core/v4l2-event.c index 290c6b2131797c2d1229a027c5fef050b5553d8e..caad58bde32689786c7f78d3b43e0eb73555a099 100644 --- a/drivers/media/v4l2-core/v4l2-event.c +++ b/drivers/media/v4l2-core/v4l2-event.c @@ -187,6 +187,23 @@ int v4l2_event_pending(struct v4l2_fh *fh) } EXPORT_SYMBOL_GPL(v4l2_event_pending); +void v4l2_event_wake_all(struct video_device *vdev) +{ + struct v4l2_fh *fh; + unsigned long flags; + + if (!vdev) + return; + + spin_lock_irqsave(&vdev->fh_lock, flags); + + list_for_each_entry(fh, &vdev->fh_list, list) + wake_up_all(&fh->wait); + + spin_unlock_irqrestore(&vdev->fh_lock, flags); +} +EXPORT_SYMBOL_GPL(v4l2_event_wake_all); + static void __v4l2_event_unsubscribe(struct v4l2_subscribed_event *sev) { struct v4l2_fh *fh = sev->fh; diff --git a/include/media/v4l2-event.h b/include/media/v4l2-event.h index 3f0281d06ec7d0fad1a2ba0cd6d688bb48a43015..4ffa914ade3a16b18bd3572b3461a4e1632bc90e 100644 --- a/include/media/v4l2-event.h +++ b/include/media/v4l2-event.h @@ -101,7 +101,7 @@ int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event, * * .. note:: * The driver's only responsibility is to fill in the type and the data - * fields.The other fields will be filled in by V4L2. + * fields. The other fields will be filled in by V4L2. */ void v4l2_event_queue(struct video_device *vdev, const struct v4l2_event *ev); @@ -116,10 +116,19 @@ void v4l2_event_queue(struct video_device *vdev, const struct v4l2_event *ev); * * .. note:: * The driver's only responsibility is to fill in the type and the data - * fields.The other fields will be filled in by V4L2. + * fields. The other fields will be filled in by V4L2. */ void v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *ev); +/** + * v4l2_event_wake_all - Wake all filehandles. + * + * Used when unregistering a video device. + * + * @vdev: pointer to &struct video_device + */ +void v4l2_event_wake_all(struct video_device *vdev); + /** * v4l2_event_pending - Check if an event is available *