diff options
Diffstat (limited to 'drivers/media/video/gspca/gspca.c')
-rw-r--r-- | drivers/media/video/gspca/gspca.c | 56 |
1 files changed, 30 insertions, 26 deletions
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index e48fbfc8ad05..748a87e82e44 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c | |||
@@ -646,15 +646,14 @@ static void gspca_stream_off(struct gspca_dev *gspca_dev) | |||
646 | { | 646 | { |
647 | gspca_dev->streaming = 0; | 647 | gspca_dev->streaming = 0; |
648 | atomic_set(&gspca_dev->nevent, 0); | 648 | atomic_set(&gspca_dev->nevent, 0); |
649 | if (gspca_dev->present) { | 649 | if (gspca_dev->present |
650 | if (gspca_dev->sd_desc->stopN) | 650 | && gspca_dev->sd_desc->stopN) |
651 | gspca_dev->sd_desc->stopN(gspca_dev); | 651 | gspca_dev->sd_desc->stopN(gspca_dev); |
652 | destroy_urbs(gspca_dev); | 652 | destroy_urbs(gspca_dev); |
653 | gspca_set_alt0(gspca_dev); | 653 | gspca_set_alt0(gspca_dev); |
654 | if (gspca_dev->sd_desc->stop0) | 654 | if (gspca_dev->sd_desc->stop0) |
655 | gspca_dev->sd_desc->stop0(gspca_dev); | 655 | gspca_dev->sd_desc->stop0(gspca_dev); |
656 | PDEBUG(D_STREAM, "stream off OK"); | 656 | PDEBUG(D_STREAM, "stream off OK"); |
657 | } | ||
658 | } | 657 | } |
659 | 658 | ||
660 | static void gspca_set_default_mode(struct gspca_dev *gspca_dev) | 659 | static void gspca_set_default_mode(struct gspca_dev *gspca_dev) |
@@ -863,7 +862,7 @@ static int dev_open(struct inode *inode, struct file *file) | |||
863 | int ret; | 862 | int ret; |
864 | 863 | ||
865 | PDEBUG(D_STREAM, "%s open", current->comm); | 864 | PDEBUG(D_STREAM, "%s open", current->comm); |
866 | gspca_dev = (struct gspca_dev *) video_devdata(file); | 865 | gspca_dev = video_drvdata(file); |
867 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) | 866 | if (mutex_lock_interruptible(&gspca_dev->queue_lock)) |
868 | return -ERESTARTSYS; | 867 | return -ERESTARTSYS; |
869 | if (!gspca_dev->present) { | 868 | if (!gspca_dev->present) { |
@@ -875,6 +874,13 @@ static int dev_open(struct inode *inode, struct file *file) | |||
875 | ret = -EBUSY; | 874 | ret = -EBUSY; |
876 | goto out; | 875 | goto out; |
877 | } | 876 | } |
877 | |||
878 | /* protect the subdriver against rmmod */ | ||
879 | if (!try_module_get(gspca_dev->module)) { | ||
880 | ret = -ENODEV; | ||
881 | goto out; | ||
882 | } | ||
883 | |||
878 | gspca_dev->users++; | 884 | gspca_dev->users++; |
879 | 885 | ||
880 | /* one more user */ | 886 | /* one more user */ |
@@ -884,10 +890,10 @@ static int dev_open(struct inode *inode, struct file *file) | |||
884 | #ifdef GSPCA_DEBUG | 890 | #ifdef GSPCA_DEBUG |
885 | /* activate the v4l2 debug */ | 891 | /* activate the v4l2 debug */ |
886 | if (gspca_debug & D_V4L2) | 892 | if (gspca_debug & D_V4L2) |
887 | gspca_dev->vdev.debug |= V4L2_DEBUG_IOCTL | 893 | gspca_dev->vdev->debug |= V4L2_DEBUG_IOCTL |
888 | | V4L2_DEBUG_IOCTL_ARG; | 894 | | V4L2_DEBUG_IOCTL_ARG; |
889 | else | 895 | else |
890 | gspca_dev->vdev.debug &= ~(V4L2_DEBUG_IOCTL | 896 | gspca_dev->vdev->debug &= ~(V4L2_DEBUG_IOCTL |
891 | | V4L2_DEBUG_IOCTL_ARG); | 897 | | V4L2_DEBUG_IOCTL_ARG); |
892 | #endif | 898 | #endif |
893 | ret = 0; | 899 | ret = 0; |
@@ -921,6 +927,7 @@ static int dev_close(struct inode *inode, struct file *file) | |||
921 | gspca_dev->memory = GSPCA_MEMORY_NO; | 927 | gspca_dev->memory = GSPCA_MEMORY_NO; |
922 | } | 928 | } |
923 | file->private_data = NULL; | 929 | file->private_data = NULL; |
930 | module_put(gspca_dev->module); | ||
924 | mutex_unlock(&gspca_dev->queue_lock); | 931 | mutex_unlock(&gspca_dev->queue_lock); |
925 | 932 | ||
926 | PDEBUG(D_STREAM, "close done"); | 933 | PDEBUG(D_STREAM, "close done"); |
@@ -1748,11 +1755,6 @@ out: | |||
1748 | return ret; | 1755 | return ret; |
1749 | } | 1756 | } |
1750 | 1757 | ||
1751 | static void dev_release(struct video_device *vfd) | ||
1752 | { | ||
1753 | /* nothing */ | ||
1754 | } | ||
1755 | |||
1756 | static struct file_operations dev_fops = { | 1758 | static struct file_operations dev_fops = { |
1757 | .owner = THIS_MODULE, | 1759 | .owner = THIS_MODULE, |
1758 | .open = dev_open, | 1760 | .open = dev_open, |
@@ -1800,7 +1802,7 @@ static struct video_device gspca_template = { | |||
1800 | .name = "gspca main driver", | 1802 | .name = "gspca main driver", |
1801 | .fops = &dev_fops, | 1803 | .fops = &dev_fops, |
1802 | .ioctl_ops = &dev_ioctl_ops, | 1804 | .ioctl_ops = &dev_ioctl_ops, |
1803 | .release = dev_release, /* mandatory */ | 1805 | .release = video_device_release, |
1804 | .minor = -1, | 1806 | .minor = -1, |
1805 | }; | 1807 | }; |
1806 | 1808 | ||
@@ -1869,17 +1871,18 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
1869 | init_waitqueue_head(&gspca_dev->wq); | 1871 | init_waitqueue_head(&gspca_dev->wq); |
1870 | 1872 | ||
1871 | /* init video stuff */ | 1873 | /* init video stuff */ |
1872 | memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template); | 1874 | gspca_dev->vdev = video_device_alloc(); |
1873 | gspca_dev->vdev.parent = &dev->dev; | 1875 | memcpy(gspca_dev->vdev, &gspca_template, sizeof gspca_template); |
1874 | memcpy(&gspca_dev->fops, &dev_fops, sizeof gspca_dev->fops); | 1876 | gspca_dev->vdev->parent = &dev->dev; |
1875 | gspca_dev->vdev.fops = &gspca_dev->fops; | 1877 | gspca_dev->module = module; |
1876 | gspca_dev->fops.owner = module; /* module protection */ | ||
1877 | gspca_dev->present = 1; | 1878 | gspca_dev->present = 1; |
1878 | ret = video_register_device(&gspca_dev->vdev, | 1879 | video_set_drvdata(gspca_dev->vdev, gspca_dev); |
1880 | ret = video_register_device(gspca_dev->vdev, | ||
1879 | VFL_TYPE_GRABBER, | 1881 | VFL_TYPE_GRABBER, |
1880 | video_nr); | 1882 | video_nr); |
1881 | if (ret < 0) { | 1883 | if (ret < 0) { |
1882 | err("video_register_device err %d", ret); | 1884 | err("video_register_device err %d", ret); |
1885 | video_device_release(gspca_dev->vdev); | ||
1883 | goto out; | 1886 | goto out; |
1884 | } | 1887 | } |
1885 | 1888 | ||
@@ -1887,7 +1890,8 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
1887 | PDEBUG(D_PROBE, "probe ok"); | 1890 | PDEBUG(D_PROBE, "probe ok"); |
1888 | return 0; | 1891 | return 0; |
1889 | out: | 1892 | out: |
1890 | kref_put(&gspca_dev->kref, gspca_delete); | 1893 | kfree(gspca_dev->usb_buf); |
1894 | kfree(gspca_dev); | ||
1891 | return ret; | 1895 | return ret; |
1892 | } | 1896 | } |
1893 | EXPORT_SYMBOL(gspca_dev_probe); | 1897 | EXPORT_SYMBOL(gspca_dev_probe); |
@@ -1905,7 +1909,7 @@ void gspca_disconnect(struct usb_interface *intf) | |||
1905 | usb_set_intfdata(intf, NULL); | 1909 | usb_set_intfdata(intf, NULL); |
1906 | 1910 | ||
1907 | /* We don't want people trying to open up the device */ | 1911 | /* We don't want people trying to open up the device */ |
1908 | video_unregister_device(&gspca_dev->vdev); | 1912 | video_unregister_device(gspca_dev->vdev); |
1909 | 1913 | ||
1910 | gspca_dev->present = 0; | 1914 | gspca_dev->present = 0; |
1911 | gspca_dev->streaming = 0; | 1915 | gspca_dev->streaming = 0; |