diff options
-rw-r--r-- | drivers/media/video/v4l2-dev.c | 10 | ||||
-rw-r--r-- | drivers/media/video/v4l2-device.c | 16 | ||||
-rw-r--r-- | include/media/v4l2-device.h | 11 |
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) | |||
143 | static void v4l2_device_release(struct device *cd) | 143 | static 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 | ||
174 | static struct class video_class = { | 179 | static 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 | } |
55 | EXPORT_SYMBOL_GPL(v4l2_device_register); | 56 | EXPORT_SYMBOL_GPL(v4l2_device_register); |
56 | 57 | ||
58 | static 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 | |||
67 | int v4l2_device_put(struct v4l2_device *v4l2_dev) | ||
68 | { | ||
69 | return kref_put(&v4l2_dev->ref, v4l2_device_release); | ||
70 | } | ||
71 | EXPORT_SYMBOL_GPL(v4l2_device_put); | ||
72 | |||
57 | int v4l2_device_set_name(struct v4l2_device *v4l2_dev, const char *basename, | 73 | int 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 | ||
69 | static inline void v4l2_device_get(struct v4l2_device *v4l2_dev) | ||
70 | { | ||
71 | kref_get(&v4l2_dev->ref); | ||
72 | } | ||
73 | |||
74 | int 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. */ |