diff options
author | David Ellingsworth <david@identd.dyndns.org> | 2008-09-21 03:12:03 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-10-12 07:37:08 -0400 |
commit | 4aaec3ea41addf6fe4fe029aa535f3c019ee0e6d (patch) | |
tree | caa372c064a2dacea481c0fd15ea28bf188e05fe /drivers/media/video | |
parent | 714b9a1e0ae3224728d1d96d77150ceea7487a61 (diff) |
V4L/DVB (9034): With the recent patch to v4l2 titled "v4l2: use register_chrdev_region
instead of register_chrdev", the internal reference count is no longer
necessary in order to free the internal stk_webcam struct. This patch
removes the reference counter from the stk_webcam struct and frees the
struct via the video_device release callback. It also fixes an
associated bug in stk_camera_probe which could result from
video_unregister_device being called before video_register_device.
Lastly, it simplifies access to the stk_webcam struct in several
places. This patch should apply cleanly against the "working" branch
of the v4l-dvb git repository.
This patch is identical to the patch I sent a couple of months back
titled "stk-webcam: Fix video_device handling" except that it has been
rebased against current modifications to stk-webcam and it no longer
depends on any other outstanding patches.
Acked-by: Jaime Velasco Juan <jsagarribay@gmail.com>
Signed-off-by: David Ellingsworth <david@identd.dyndns.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video')
-rw-r--r-- | drivers/media/video/stk-webcam.c | 84 | ||||
-rw-r--r-- | drivers/media/video/stk-webcam.h | 2 |
2 files changed, 23 insertions, 63 deletions
diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c index 8dda5680094d..db69bc5556d6 100644 --- a/drivers/media/video/stk-webcam.c +++ b/drivers/media/video/stk-webcam.c | |||
@@ -65,22 +65,6 @@ static struct usb_device_id stkwebcam_table[] = { | |||
65 | }; | 65 | }; |
66 | MODULE_DEVICE_TABLE(usb, stkwebcam_table); | 66 | MODULE_DEVICE_TABLE(usb, stkwebcam_table); |
67 | 67 | ||
68 | static void stk_camera_cleanup(struct kref *kref) | ||
69 | { | ||
70 | struct stk_camera *dev = to_stk_camera(kref); | ||
71 | |||
72 | STK_INFO("Syntek USB2.0 Camera release resources" | ||
73 | " video device /dev/video%d\n", dev->vdev.minor); | ||
74 | video_unregister_device(&dev->vdev); | ||
75 | video_set_drvdata(&dev->vdev, NULL); | ||
76 | |||
77 | if (dev->sio_bufs != NULL || dev->isobufs != NULL) | ||
78 | STK_ERROR("We are leaking memory\n"); | ||
79 | usb_put_intf(dev->interface); | ||
80 | kfree(dev); | ||
81 | } | ||
82 | |||
83 | |||
84 | /* | 68 | /* |
85 | * Basic stuff | 69 | * Basic stuff |
86 | */ | 70 | */ |
@@ -694,8 +678,7 @@ static int v4l_stk_open(struct inode *inode, struct file *fp) | |||
694 | unlock_kernel(); | 678 | unlock_kernel(); |
695 | return -ENXIO; | 679 | return -ENXIO; |
696 | } | 680 | } |
697 | fp->private_data = vdev; | 681 | fp->private_data = dev; |
698 | kref_get(&dev->kref); | ||
699 | usb_autopm_get_interface(dev->interface); | 682 | usb_autopm_get_interface(dev->interface); |
700 | unlock_kernel(); | 683 | unlock_kernel(); |
701 | 684 | ||
@@ -704,23 +687,10 @@ static int v4l_stk_open(struct inode *inode, struct file *fp) | |||
704 | 687 | ||
705 | static int v4l_stk_release(struct inode *inode, struct file *fp) | 688 | static int v4l_stk_release(struct inode *inode, struct file *fp) |
706 | { | 689 | { |
707 | struct stk_camera *dev; | 690 | struct stk_camera *dev = fp->private_data; |
708 | struct video_device *vdev; | ||
709 | |||
710 | vdev = video_devdata(fp); | ||
711 | if (vdev == NULL) { | ||
712 | STK_ERROR("v4l_release called w/o video devdata\n"); | ||
713 | return -EFAULT; | ||
714 | } | ||
715 | dev = vdev_to_camera(vdev); | ||
716 | if (dev == NULL) { | ||
717 | STK_ERROR("v4l_release called on removed device\n"); | ||
718 | return -ENODEV; | ||
719 | } | ||
720 | 691 | ||
721 | if (dev->owner != fp) { | 692 | if (dev->owner != fp) { |
722 | usb_autopm_put_interface(dev->interface); | 693 | usb_autopm_put_interface(dev->interface); |
723 | kref_put(&dev->kref, stk_camera_cleanup); | ||
724 | return 0; | 694 | return 0; |
725 | } | 695 | } |
726 | 696 | ||
@@ -731,7 +701,6 @@ static int v4l_stk_release(struct inode *inode, struct file *fp) | |||
731 | dev->owner = NULL; | 701 | dev->owner = NULL; |
732 | 702 | ||
733 | usb_autopm_put_interface(dev->interface); | 703 | usb_autopm_put_interface(dev->interface); |
734 | kref_put(&dev->kref, stk_camera_cleanup); | ||
735 | 704 | ||
736 | return 0; | 705 | return 0; |
737 | } | 706 | } |
@@ -742,14 +711,8 @@ static ssize_t v4l_stk_read(struct file *fp, char __user *buf, | |||
742 | int i; | 711 | int i; |
743 | int ret; | 712 | int ret; |
744 | unsigned long flags; | 713 | unsigned long flags; |
745 | struct stk_camera *dev; | ||
746 | struct video_device *vdev; | ||
747 | struct stk_sio_buffer *sbuf; | 714 | struct stk_sio_buffer *sbuf; |
748 | 715 | struct stk_camera *dev = fp->private_data; | |
749 | vdev = video_devdata(fp); | ||
750 | if (vdev == NULL) | ||
751 | return -EFAULT; | ||
752 | dev = vdev_to_camera(vdev); | ||
753 | 716 | ||
754 | if (dev == NULL) | 717 | if (dev == NULL) |
755 | return -EIO; | 718 | return -EIO; |
@@ -808,15 +771,8 @@ static ssize_t v4l_stk_read(struct file *fp, char __user *buf, | |||
808 | 771 | ||
809 | static unsigned int v4l_stk_poll(struct file *fp, poll_table *wait) | 772 | static unsigned int v4l_stk_poll(struct file *fp, poll_table *wait) |
810 | { | 773 | { |
811 | struct stk_camera *dev; | 774 | struct stk_camera *dev = fp->private_data; |
812 | struct video_device *vdev; | ||
813 | |||
814 | vdev = video_devdata(fp); | ||
815 | |||
816 | if (vdev == NULL) | ||
817 | return -EFAULT; | ||
818 | 775 | ||
819 | dev = vdev_to_camera(vdev); | ||
820 | if (dev == NULL) | 776 | if (dev == NULL) |
821 | return -ENODEV; | 777 | return -ENODEV; |
822 | 778 | ||
@@ -854,16 +810,12 @@ static int v4l_stk_mmap(struct file *fp, struct vm_area_struct *vma) | |||
854 | unsigned int i; | 810 | unsigned int i; |
855 | int ret; | 811 | int ret; |
856 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; | 812 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; |
857 | struct stk_camera *dev; | 813 | struct stk_camera *dev = fp->private_data; |
858 | struct video_device *vdev; | ||
859 | struct stk_sio_buffer *sbuf = NULL; | 814 | struct stk_sio_buffer *sbuf = NULL; |
860 | 815 | ||
861 | if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) | 816 | if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) |
862 | return -EINVAL; | 817 | return -EINVAL; |
863 | 818 | ||
864 | vdev = video_devdata(fp); | ||
865 | dev = vdev_to_camera(vdev); | ||
866 | |||
867 | for (i = 0; i < dev->n_sbufs; i++) { | 819 | for (i = 0; i < dev->n_sbufs; i++) { |
868 | if (dev->sio_bufs[i].v4lbuf.m.offset == offset) { | 820 | if (dev->sio_bufs[i].v4lbuf.m.offset == offset) { |
869 | sbuf = dev->sio_bufs + i; | 821 | sbuf = dev->sio_bufs + i; |
@@ -1359,6 +1311,12 @@ static const struct v4l2_ioctl_ops v4l_stk_ioctl_ops = { | |||
1359 | 1311 | ||
1360 | static void stk_v4l_dev_release(struct video_device *vd) | 1312 | static void stk_v4l_dev_release(struct video_device *vd) |
1361 | { | 1313 | { |
1314 | struct stk_camera *dev = vdev_to_camera(vd); | ||
1315 | |||
1316 | if (dev->sio_bufs != NULL || dev->isobufs != NULL) | ||
1317 | STK_ERROR("We are leaking memory\n"); | ||
1318 | usb_put_intf(dev->interface); | ||
1319 | kfree(dev); | ||
1362 | } | 1320 | } |
1363 | 1321 | ||
1364 | static struct video_device stk_v4l_data = { | 1322 | static struct video_device stk_v4l_data = { |
@@ -1379,7 +1337,6 @@ static int stk_register_video_device(struct stk_camera *dev) | |||
1379 | dev->vdev = stk_v4l_data; | 1337 | dev->vdev = stk_v4l_data; |
1380 | dev->vdev.debug = debug; | 1338 | dev->vdev.debug = debug; |
1381 | dev->vdev.parent = &dev->interface->dev; | 1339 | dev->vdev.parent = &dev->interface->dev; |
1382 | video_set_drvdata(&dev->vdev, dev); | ||
1383 | err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1); | 1340 | err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1); |
1384 | if (err) | 1341 | if (err) |
1385 | STK_ERROR("v4l registration failed\n"); | 1342 | STK_ERROR("v4l registration failed\n"); |
@@ -1396,7 +1353,7 @@ static int stk_camera_probe(struct usb_interface *interface, | |||
1396 | const struct usb_device_id *id) | 1353 | const struct usb_device_id *id) |
1397 | { | 1354 | { |
1398 | int i; | 1355 | int i; |
1399 | int err; | 1356 | int err = 0; |
1400 | 1357 | ||
1401 | struct stk_camera *dev = NULL; | 1358 | struct stk_camera *dev = NULL; |
1402 | struct usb_device *udev = interface_to_usbdev(interface); | 1359 | struct usb_device *udev = interface_to_usbdev(interface); |
@@ -1409,7 +1366,6 @@ static int stk_camera_probe(struct usb_interface *interface, | |||
1409 | return -ENOMEM; | 1366 | return -ENOMEM; |
1410 | } | 1367 | } |
1411 | 1368 | ||
1412 | kref_init(&dev->kref); | ||
1413 | spin_lock_init(&dev->spinlock); | 1369 | spin_lock_init(&dev->spinlock); |
1414 | init_waitqueue_head(&dev->wait_frame); | 1370 | init_waitqueue_head(&dev->wait_frame); |
1415 | 1371 | ||
@@ -1442,8 +1398,8 @@ static int stk_camera_probe(struct usb_interface *interface, | |||
1442 | } | 1398 | } |
1443 | if (!dev->isoc_ep) { | 1399 | if (!dev->isoc_ep) { |
1444 | STK_ERROR("Could not find isoc-in endpoint"); | 1400 | STK_ERROR("Could not find isoc-in endpoint"); |
1445 | kref_put(&dev->kref, stk_camera_cleanup); | 1401 | err = -ENODEV; |
1446 | return -ENODEV; | 1402 | goto error; |
1447 | } | 1403 | } |
1448 | dev->vsettings.brightness = 0x7fff; | 1404 | dev->vsettings.brightness = 0x7fff; |
1449 | dev->vsettings.palette = V4L2_PIX_FMT_RGB565; | 1405 | dev->vsettings.palette = V4L2_PIX_FMT_RGB565; |
@@ -1457,14 +1413,17 @@ static int stk_camera_probe(struct usb_interface *interface, | |||
1457 | 1413 | ||
1458 | err = stk_register_video_device(dev); | 1414 | err = stk_register_video_device(dev); |
1459 | if (err) { | 1415 | if (err) { |
1460 | kref_put(&dev->kref, stk_camera_cleanup); | 1416 | goto error; |
1461 | return err; | ||
1462 | } | 1417 | } |
1463 | 1418 | ||
1464 | stk_create_sysfs_files(&dev->vdev); | 1419 | stk_create_sysfs_files(&dev->vdev); |
1465 | usb_autopm_enable(dev->interface); | 1420 | usb_autopm_enable(dev->interface); |
1466 | 1421 | ||
1467 | return 0; | 1422 | return 0; |
1423 | |||
1424 | error: | ||
1425 | kfree(dev); | ||
1426 | return err; | ||
1468 | } | 1427 | } |
1469 | 1428 | ||
1470 | static void stk_camera_disconnect(struct usb_interface *interface) | 1429 | static void stk_camera_disconnect(struct usb_interface *interface) |
@@ -1477,7 +1436,10 @@ static void stk_camera_disconnect(struct usb_interface *interface) | |||
1477 | wake_up_interruptible(&dev->wait_frame); | 1436 | wake_up_interruptible(&dev->wait_frame); |
1478 | stk_remove_sysfs_files(&dev->vdev); | 1437 | stk_remove_sysfs_files(&dev->vdev); |
1479 | 1438 | ||
1480 | kref_put(&dev->kref, stk_camera_cleanup); | 1439 | STK_INFO("Syntek USB2.0 Camera release resources" |
1440 | "video device /dev/video%d\n", dev->vdev.minor); | ||
1441 | |||
1442 | video_unregister_device(&dev->vdev); | ||
1481 | } | 1443 | } |
1482 | 1444 | ||
1483 | #ifdef CONFIG_PM | 1445 | #ifdef CONFIG_PM |
diff --git a/drivers/media/video/stk-webcam.h b/drivers/media/video/stk-webcam.h index df4dfefc5327..084a85bdd16e 100644 --- a/drivers/media/video/stk-webcam.h +++ b/drivers/media/video/stk-webcam.h | |||
@@ -99,7 +99,6 @@ struct stk_camera { | |||
99 | 99 | ||
100 | u8 isoc_ep; | 100 | u8 isoc_ep; |
101 | 101 | ||
102 | struct kref kref; | ||
103 | /* Not sure if this is right */ | 102 | /* Not sure if this is right */ |
104 | atomic_t urbs_used; | 103 | atomic_t urbs_used; |
105 | 104 | ||
@@ -121,7 +120,6 @@ struct stk_camera { | |||
121 | unsigned sequence; | 120 | unsigned sequence; |
122 | }; | 121 | }; |
123 | 122 | ||
124 | #define to_stk_camera(d) container_of(d, struct stk_camera, kref) | ||
125 | #define vdev_to_camera(d) container_of(d, struct stk_camera, vdev) | 123 | #define vdev_to_camera(d) container_of(d, struct stk_camera, vdev) |
126 | 124 | ||
127 | void stk_camera_delete(struct kref *); | 125 | void stk_camera_delete(struct kref *); |