diff options
Diffstat (limited to 'drivers/media/video/stk-webcam.c')
-rw-r--r-- | drivers/media/video/stk-webcam.c | 90 |
1 files changed, 28 insertions, 62 deletions
diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c index ad36af30e099..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 | dev->vdev.priv = 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 | */ |
@@ -689,34 +673,24 @@ static int v4l_stk_open(struct inode *inode, struct file *fp) | |||
689 | vdev = video_devdata(fp); | 673 | vdev = video_devdata(fp); |
690 | dev = vdev_to_camera(vdev); | 674 | dev = vdev_to_camera(vdev); |
691 | 675 | ||
692 | if (dev == NULL || !is_present(dev)) | 676 | lock_kernel(); |
677 | if (dev == NULL || !is_present(dev)) { | ||
678 | unlock_kernel(); | ||
693 | return -ENXIO; | 679 | return -ENXIO; |
694 | fp->private_data = vdev; | 680 | } |
695 | kref_get(&dev->kref); | 681 | fp->private_data = dev; |
696 | usb_autopm_get_interface(dev->interface); | 682 | usb_autopm_get_interface(dev->interface); |
683 | unlock_kernel(); | ||
697 | 684 | ||
698 | return 0; | 685 | return 0; |
699 | } | 686 | } |
700 | 687 | ||
701 | static int v4l_stk_release(struct inode *inode, struct file *fp) | 688 | static int v4l_stk_release(struct inode *inode, struct file *fp) |
702 | { | 689 | { |
703 | struct stk_camera *dev; | 690 | struct stk_camera *dev = fp->private_data; |
704 | struct video_device *vdev; | ||
705 | |||
706 | vdev = video_devdata(fp); | ||
707 | if (vdev == NULL) { | ||
708 | STK_ERROR("v4l_release called w/o video devdata\n"); | ||
709 | return -EFAULT; | ||
710 | } | ||
711 | dev = vdev_to_camera(vdev); | ||
712 | if (dev == NULL) { | ||
713 | STK_ERROR("v4l_release called on removed device\n"); | ||
714 | return -ENODEV; | ||
715 | } | ||
716 | 691 | ||
717 | if (dev->owner != fp) { | 692 | if (dev->owner != fp) { |
718 | usb_autopm_put_interface(dev->interface); | 693 | usb_autopm_put_interface(dev->interface); |
719 | kref_put(&dev->kref, stk_camera_cleanup); | ||
720 | return 0; | 694 | return 0; |
721 | } | 695 | } |
722 | 696 | ||
@@ -727,7 +701,6 @@ static int v4l_stk_release(struct inode *inode, struct file *fp) | |||
727 | dev->owner = NULL; | 701 | dev->owner = NULL; |
728 | 702 | ||
729 | usb_autopm_put_interface(dev->interface); | 703 | usb_autopm_put_interface(dev->interface); |
730 | kref_put(&dev->kref, stk_camera_cleanup); | ||
731 | 704 | ||
732 | return 0; | 705 | return 0; |
733 | } | 706 | } |
@@ -738,14 +711,8 @@ static ssize_t v4l_stk_read(struct file *fp, char __user *buf, | |||
738 | int i; | 711 | int i; |
739 | int ret; | 712 | int ret; |
740 | unsigned long flags; | 713 | unsigned long flags; |
741 | struct stk_camera *dev; | ||
742 | struct video_device *vdev; | ||
743 | struct stk_sio_buffer *sbuf; | 714 | struct stk_sio_buffer *sbuf; |
744 | 715 | struct stk_camera *dev = fp->private_data; | |
745 | vdev = video_devdata(fp); | ||
746 | if (vdev == NULL) | ||
747 | return -EFAULT; | ||
748 | dev = vdev_to_camera(vdev); | ||
749 | 716 | ||
750 | if (dev == NULL) | 717 | if (dev == NULL) |
751 | return -EIO; | 718 | return -EIO; |
@@ -804,15 +771,8 @@ static ssize_t v4l_stk_read(struct file *fp, char __user *buf, | |||
804 | 771 | ||
805 | 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) |
806 | { | 773 | { |
807 | struct stk_camera *dev; | 774 | struct stk_camera *dev = fp->private_data; |
808 | struct video_device *vdev; | ||
809 | |||
810 | vdev = video_devdata(fp); | ||
811 | |||
812 | if (vdev == NULL) | ||
813 | return -EFAULT; | ||
814 | 775 | ||
815 | dev = vdev_to_camera(vdev); | ||
816 | if (dev == NULL) | 776 | if (dev == NULL) |
817 | return -ENODEV; | 777 | return -ENODEV; |
818 | 778 | ||
@@ -850,16 +810,12 @@ static int v4l_stk_mmap(struct file *fp, struct vm_area_struct *vma) | |||
850 | unsigned int i; | 810 | unsigned int i; |
851 | int ret; | 811 | int ret; |
852 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; | 812 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; |
853 | struct stk_camera *dev; | 813 | struct stk_camera *dev = fp->private_data; |
854 | struct video_device *vdev; | ||
855 | struct stk_sio_buffer *sbuf = NULL; | 814 | struct stk_sio_buffer *sbuf = NULL; |
856 | 815 | ||
857 | if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) | 816 | if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) |
858 | return -EINVAL; | 817 | return -EINVAL; |
859 | 818 | ||
860 | vdev = video_devdata(fp); | ||
861 | dev = vdev_to_camera(vdev); | ||
862 | |||
863 | for (i = 0; i < dev->n_sbufs; i++) { | 819 | for (i = 0; i < dev->n_sbufs; i++) { |
864 | if (dev->sio_bufs[i].v4lbuf.m.offset == offset) { | 820 | if (dev->sio_bufs[i].v4lbuf.m.offset == offset) { |
865 | sbuf = dev->sio_bufs + i; | 821 | sbuf = dev->sio_bufs + i; |
@@ -1355,6 +1311,12 @@ static const struct v4l2_ioctl_ops v4l_stk_ioctl_ops = { | |||
1355 | 1311 | ||
1356 | static void stk_v4l_dev_release(struct video_device *vd) | 1312 | static void stk_v4l_dev_release(struct video_device *vd) |
1357 | { | 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); | ||
1358 | } | 1320 | } |
1359 | 1321 | ||
1360 | static struct video_device stk_v4l_data = { | 1322 | static struct video_device stk_v4l_data = { |
@@ -1375,7 +1337,6 @@ static int stk_register_video_device(struct stk_camera *dev) | |||
1375 | dev->vdev = stk_v4l_data; | 1337 | dev->vdev = stk_v4l_data; |
1376 | dev->vdev.debug = debug; | 1338 | dev->vdev.debug = debug; |
1377 | dev->vdev.parent = &dev->interface->dev; | 1339 | dev->vdev.parent = &dev->interface->dev; |
1378 | dev->vdev.priv = dev; | ||
1379 | err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1); | 1340 | err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1); |
1380 | if (err) | 1341 | if (err) |
1381 | STK_ERROR("v4l registration failed\n"); | 1342 | STK_ERROR("v4l registration failed\n"); |
@@ -1392,7 +1353,7 @@ static int stk_camera_probe(struct usb_interface *interface, | |||
1392 | const struct usb_device_id *id) | 1353 | const struct usb_device_id *id) |
1393 | { | 1354 | { |
1394 | int i; | 1355 | int i; |
1395 | int err; | 1356 | int err = 0; |
1396 | 1357 | ||
1397 | struct stk_camera *dev = NULL; | 1358 | struct stk_camera *dev = NULL; |
1398 | struct usb_device *udev = interface_to_usbdev(interface); | 1359 | struct usb_device *udev = interface_to_usbdev(interface); |
@@ -1405,7 +1366,6 @@ static int stk_camera_probe(struct usb_interface *interface, | |||
1405 | return -ENOMEM; | 1366 | return -ENOMEM; |
1406 | } | 1367 | } |
1407 | 1368 | ||
1408 | kref_init(&dev->kref); | ||
1409 | spin_lock_init(&dev->spinlock); | 1369 | spin_lock_init(&dev->spinlock); |
1410 | init_waitqueue_head(&dev->wait_frame); | 1370 | init_waitqueue_head(&dev->wait_frame); |
1411 | 1371 | ||
@@ -1438,8 +1398,8 @@ static int stk_camera_probe(struct usb_interface *interface, | |||
1438 | } | 1398 | } |
1439 | if (!dev->isoc_ep) { | 1399 | if (!dev->isoc_ep) { |
1440 | STK_ERROR("Could not find isoc-in endpoint"); | 1400 | STK_ERROR("Could not find isoc-in endpoint"); |
1441 | kref_put(&dev->kref, stk_camera_cleanup); | 1401 | err = -ENODEV; |
1442 | return -ENODEV; | 1402 | goto error; |
1443 | } | 1403 | } |
1444 | dev->vsettings.brightness = 0x7fff; | 1404 | dev->vsettings.brightness = 0x7fff; |
1445 | dev->vsettings.palette = V4L2_PIX_FMT_RGB565; | 1405 | dev->vsettings.palette = V4L2_PIX_FMT_RGB565; |
@@ -1453,14 +1413,17 @@ static int stk_camera_probe(struct usb_interface *interface, | |||
1453 | 1413 | ||
1454 | err = stk_register_video_device(dev); | 1414 | err = stk_register_video_device(dev); |
1455 | if (err) { | 1415 | if (err) { |
1456 | kref_put(&dev->kref, stk_camera_cleanup); | 1416 | goto error; |
1457 | return err; | ||
1458 | } | 1417 | } |
1459 | 1418 | ||
1460 | stk_create_sysfs_files(&dev->vdev); | 1419 | stk_create_sysfs_files(&dev->vdev); |
1461 | usb_autopm_enable(dev->interface); | 1420 | usb_autopm_enable(dev->interface); |
1462 | 1421 | ||
1463 | return 0; | 1422 | return 0; |
1423 | |||
1424 | error: | ||
1425 | kfree(dev); | ||
1426 | return err; | ||
1464 | } | 1427 | } |
1465 | 1428 | ||
1466 | static void stk_camera_disconnect(struct usb_interface *interface) | 1429 | static void stk_camera_disconnect(struct usb_interface *interface) |
@@ -1473,7 +1436,10 @@ static void stk_camera_disconnect(struct usb_interface *interface) | |||
1473 | wake_up_interruptible(&dev->wait_frame); | 1436 | wake_up_interruptible(&dev->wait_frame); |
1474 | stk_remove_sysfs_files(&dev->vdev); | 1437 | stk_remove_sysfs_files(&dev->vdev); |
1475 | 1438 | ||
1476 | 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); | ||
1477 | } | 1443 | } |
1478 | 1444 | ||
1479 | #ifdef CONFIG_PM | 1445 | #ifdef CONFIG_PM |