[media] V4L: fix incorrect refcounting
authorHans Verkuil <hans.verkuil@cisco.com>
Thu, 19 Apr 2012 15:27:56 +0000 (12:27 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Thu, 19 Apr 2012 20:23:38 +0000 (17:23 -0300)
Both radio-keene and dsbr100 did one v4l2_device_get too many. Thus the refcount
never became 0 and that causes a memory leak.

Also updated the V4L2 framework documentation accordingly.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Documentation/video4linux/v4l2-framework.txt
drivers/media/radio/dsbr100.c
drivers/media/radio/radio-keene.c

index 659b2ba12a4fd69297073c0e68c69ec992d83b1f..e3dfc268d9c13fcee9dbfce7f42e6498fb49fdf6 100644 (file)
@@ -182,11 +182,11 @@ static int __devinit drv_probe(struct pci_dev *pdev,
 }
 
 If you have multiple device nodes then it can be difficult to know when it is
-safe to unregister v4l2_device. For this purpose v4l2_device has refcounting
-support. The refcount is increased whenever video_register_device is called and
-it is decreased whenever that device node is released. When the refcount reaches
-zero, then the v4l2_device release() callback is called. You can do your final
-cleanup there.
+safe to unregister v4l2_device for hotpluggable devices. For this purpose
+v4l2_device has refcounting support. The refcount is increased whenever
+video_register_device is called and it is decreased whenever that device node
+is released. When the refcount reaches zero, then the v4l2_device release()
+callback is called. You can do your final cleanup there.
 
 If other device nodes (e.g. ALSA) are created, then you can increase and
 decrease the refcount manually as well by calling:
@@ -197,6 +197,10 @@ or:
 
 int v4l2_device_put(struct v4l2_device *v4l2_dev);
 
+Since the initial refcount is 1 you also need to call v4l2_device_put in the
+disconnect() callback (for USB devices) or in the remove() callback (for e.g.
+PCI devices), otherwise the refcount will never reach 0.
+
 struct v4l2_subdev
 ------------------
 
index f36905b6364538202cb0f515e59bdd05f9faad24..bf813a63ab2adc54760dac28b87b96177f1ee29a 100644 (file)
@@ -481,7 +481,6 @@ static void usb_dsbr100_disconnect(struct usb_interface *intf)
 {
        struct dsbr100_device *radio = usb_get_intfdata(intf);
 
-       v4l2_device_get(&radio->v4l2_dev);
        mutex_lock(&radio->v4l2_lock);
        usb_set_intfdata(intf, NULL);
        video_unregister_device(&radio->videodev);
index 26a2b7a0304efe11b32e8f84f29d29eda668c8cf..5f33047d0d43d5096df76b6b2f914c616afbb851 100644 (file)
@@ -148,7 +148,6 @@ static void usb_keene_disconnect(struct usb_interface *intf)
 {
        struct keene_device *radio = to_keene_dev(usb_get_intfdata(intf));
 
-       v4l2_device_get(&radio->v4l2_dev);
        mutex_lock(&radio->lock);
        usb_set_intfdata(intf, NULL);
        video_unregister_device(&radio->vdev);