aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/v4l2-dev.c10
-rw-r--r--drivers/media/video/v4l2-device.c16
-rw-r--r--include/media/v4l2-device.h11
3 files changed, 37 insertions, 0 deletions
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
index 6b1ef85d8cc8..1898099ec65a 100644
--- a/drivers/media/video/v4l2-dev.c
+++ b/drivers/media/video/v4l2-dev.c
@@ -143,6 +143,7 @@ static inline void video_put(struct video_device *vdev)
143static void v4l2_device_release(struct device *cd) 143static void v4l2_device_release(struct device *cd)
144{ 144{
145 struct video_device *vdev = to_video_device(cd); 145 struct video_device *vdev = to_video_device(cd);
146 struct v4l2_device *v4l2_dev = vdev->v4l2_dev;
146 147
147 mutex_lock(&videodev_lock); 148 mutex_lock(&videodev_lock);
148 if (video_device[vdev->minor] != vdev) { 149 if (video_device[vdev->minor] != vdev) {
@@ -169,6 +170,10 @@ static void v4l2_device_release(struct device *cd)
169 /* Release video_device and perform other 170 /* Release video_device and perform other
170 cleanups as needed. */ 171 cleanups as needed. */
171 vdev->release(vdev); 172 vdev->release(vdev);
173
174 /* Decrease v4l2_device refcount */
175 if (v4l2_dev)
176 v4l2_device_put(v4l2_dev);
172} 177}
173 178
174static struct class video_class = { 179static struct class video_class = {
@@ -676,6 +681,11 @@ int __video_register_device(struct video_device *vdev, int type, int nr,
676 if (nr != -1 && nr != vdev->num && warn_if_nr_in_use) 681 if (nr != -1 && nr != vdev->num && warn_if_nr_in_use)
677 printk(KERN_WARNING "%s: requested %s%d, got %s\n", __func__, 682 printk(KERN_WARNING "%s: requested %s%d, got %s\n", __func__,
678 name_base, nr, video_device_node_name(vdev)); 683 name_base, nr, video_device_node_name(vdev));
684
685 /* Increase v4l2_device refcount */
686 if (vdev->v4l2_dev)
687 v4l2_device_get(vdev->v4l2_dev);
688
679#if defined(CONFIG_MEDIA_CONTROLLER) 689#if defined(CONFIG_MEDIA_CONTROLLER)
680 /* Part 5: Register the entity. */ 690 /* Part 5: Register the entity. */
681 if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) { 691 if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) {
diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c
index fd7a445ce34c..5aeaf876ba9b 100644
--- a/drivers/media/video/v4l2-device.c
+++ b/drivers/media/video/v4l2-device.c
@@ -37,6 +37,7 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)
37 spin_lock_init(&v4l2_dev->lock); 37 spin_lock_init(&v4l2_dev->lock);
38 mutex_init(&v4l2_dev->ioctl_lock); 38 mutex_init(&v4l2_dev->ioctl_lock);
39 v4l2_prio_init(&v4l2_dev->prio); 39 v4l2_prio_init(&v4l2_dev->prio);
40 kref_init(&v4l2_dev->ref);
40 v4l2_dev->dev = dev; 41 v4l2_dev->dev = dev;
41 if (dev == NULL) { 42 if (dev == NULL) {
42 /* If dev == NULL, then name must be filled in by the caller */ 43 /* If dev == NULL, then name must be filled in by the caller */
@@ -54,6 +55,21 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)
54} 55}
55EXPORT_SYMBOL_GPL(v4l2_device_register); 56EXPORT_SYMBOL_GPL(v4l2_device_register);
56 57
58static void v4l2_device_release(struct kref *ref)
59{
60 struct v4l2_device *v4l2_dev =
61 container_of(ref, struct v4l2_device, ref);
62
63 if (v4l2_dev->release)
64 v4l2_dev->release(v4l2_dev);
65}
66
67int v4l2_device_put(struct v4l2_device *v4l2_dev)
68{
69 return kref_put(&v4l2_dev->ref, v4l2_device_release);
70}
71EXPORT_SYMBOL_GPL(v4l2_device_put);
72
57int v4l2_device_set_name(struct v4l2_device *v4l2_dev, const char *basename, 73int v4l2_device_set_name(struct v4l2_device *v4l2_dev, const char *basename,
58 atomic_t *instance) 74 atomic_t *instance)
59{ 75{
diff --git a/include/media/v4l2-device.h b/include/media/v4l2-device.h
index 3b723283da26..bd102cf509ac 100644
--- a/include/media/v4l2-device.h
+++ b/include/media/v4l2-device.h
@@ -60,8 +60,19 @@ struct v4l2_device {
60 struct v4l2_prio_state prio; 60 struct v4l2_prio_state prio;
61 /* BKL replacement mutex. Temporary solution only. */ 61 /* BKL replacement mutex. Temporary solution only. */
62 struct mutex ioctl_lock; 62 struct mutex ioctl_lock;
63 /* Keep track of the references to this struct. */
64 struct kref ref;
65 /* Release function that is called when the ref count goes to 0. */
66 void (*release)(struct v4l2_device *v4l2_dev);
63}; 67};
64 68
69static inline void v4l2_device_get(struct v4l2_device *v4l2_dev)
70{
71 kref_get(&v4l2_dev->ref);
72}
73
74int v4l2_device_put(struct v4l2_device *v4l2_dev);
75
65/* Initialize v4l2_dev and make dev->driver_data point to v4l2_dev. 76/* Initialize v4l2_dev and make dev->driver_data point to v4l2_dev.
66 dev may be NULL in rare cases (ISA devices). In that case you 77 dev may be NULL in rare cases (ISA devices). In that case you
67 must fill in the v4l2_dev->name field before calling this function. */ 78 must fill in the v4l2_dev->name field before calling this function. */