diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index 6ce623a1245a..cf9279a2d990 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -423,14 +423,18 @@ static int v4l2_open(struct inode *inode, struct file *filp) } /* and increase the device refcount */ video_get(vdev); - mutex_unlock(&videodev_lock); if (!video_is_registered(vdev)) { ret = -ENODEV; goto done; } + set_bit(V4L2_FL_BUSY, &vdev->flags); + mutex_unlock(&videodev_lock); + ret = vdev->fops->open(filp); + + mutex_lock(&videodev_lock); if (ret) goto done; @@ -448,6 +452,8 @@ static int v4l2_open(struct inode *inode, struct file *filp) /* decrease the refcount in case of an error */ if (ret) video_put(vdev); + clear_bit(V4L2_FL_BUSY, &vdev->flags); + mutex_unlock(&videodev_lock); return ret; } @@ -1121,6 +1127,11 @@ void video_unregister_device(struct video_device *vdev) return; mutex_lock(&videodev_lock); + while (test_bit(V4L2_FL_BUSY, &vdev->flags)) { + mutex_unlock(&videodev_lock); + cond_resched(); + mutex_lock(&videodev_lock); + } /* This must be in a critical section to prevent a race with v4l2_open. * Once this bit has been cleared video_get may never be called again. */ diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 2e0f6d2e6a78..83feb0a4f4d3 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -95,6 +95,7 @@ enum v4l2_video_device_flags { V4L2_FL_USES_V4L2_FH = 1, V4L2_FL_QUIRK_INVERTED_CROP = 2, V4L2_FL_SUBDEV_RO_DEVNODE = 3, + V4L2_FL_BUSY = 4, }; /* Priority helper functions */