[media] v4l2-device: add kref and a release function

The video_device struct has proper ref counting and its release function
will be called when the last user releases it. But no such support was
available for struct v4l2_device. This made it hard to determine when a
USB driver can release the device if it has multiple device nodes.

With one device node it is easy of course, since when the device node is
released, the whole device can be released.

This patch adds refcounting to v4l2_device. When registering device nodes
the v4l2_device refcount will be increased, when releasing device nodes
it will be decreased. The (optional) release function will be called when
the last device node was released.

Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
index 6b1ef85..1898099 100644
--- a/drivers/media/video/v4l2-dev.c
+++ b/drivers/media/video/v4l2-dev.c
@@ -143,6 +143,7 @@
 static void v4l2_device_release(struct device *cd)
 {
 	struct video_device *vdev = to_video_device(cd);
+	struct v4l2_device *v4l2_dev = vdev->v4l2_dev;
 
 	mutex_lock(&videodev_lock);
 	if (video_device[vdev->minor] != vdev) {
@@ -169,6 +170,10 @@
 	/* Release video_device and perform other
 	   cleanups as needed. */
 	vdev->release(vdev);
+
+	/* Decrease v4l2_device refcount */
+	if (v4l2_dev)
+		v4l2_device_put(v4l2_dev);
 }
 
 static struct class video_class = {
@@ -676,6 +681,11 @@
 	if (nr != -1 && nr != vdev->num && warn_if_nr_in_use)
 		printk(KERN_WARNING "%s: requested %s%d, got %s\n", __func__,
 			name_base, nr, video_device_node_name(vdev));
+
+	/* Increase v4l2_device refcount */
+	if (vdev->v4l2_dev)
+		v4l2_device_get(vdev->v4l2_dev);
+
 #if defined(CONFIG_MEDIA_CONTROLLER)
 	/* Part 5: Register the entity. */
 	if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) {