V4L/DVB (9691): gspca: Move the video device to a separate area.
authorJean-Francois Moine <moinejf@free.fr>
Wed, 19 Nov 2008 09:37:53 +0000 (06:37 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 24 Nov 2008 14:01:38 +0000 (12:01 -0200)
The video device was part of the gspca device. On device disconnection
while streaming, the device structure is freed at close time.
In this case, the remaining close job on the video device run out of
allocated memory.

Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/gspca/gspca.c
drivers/media/video/gspca/gspca.h

index a565f37648378df80b107a7c62bf9a7df9137e94..748a87e82e4423e2b9ecfb4c4ac621a339231e4a 100644 (file)
@@ -862,7 +862,7 @@ static int dev_open(struct inode *inode, struct file *file)
        int ret;
 
        PDEBUG(D_STREAM, "%s open", current->comm);
-       gspca_dev = (struct gspca_dev *) video_devdata(file);
+       gspca_dev = video_drvdata(file);
        if (mutex_lock_interruptible(&gspca_dev->queue_lock))
                return -ERESTARTSYS;
        if (!gspca_dev->present) {
@@ -890,10 +890,10 @@ static int dev_open(struct inode *inode, struct file *file)
 #ifdef GSPCA_DEBUG
        /* activate the v4l2 debug */
        if (gspca_debug & D_V4L2)
-               gspca_dev->vdev.debug |= V4L2_DEBUG_IOCTL
+               gspca_dev->vdev->debug |= V4L2_DEBUG_IOCTL
                                        | V4L2_DEBUG_IOCTL_ARG;
        else
-               gspca_dev->vdev.debug &= ~(V4L2_DEBUG_IOCTL
+               gspca_dev->vdev->debug &= ~(V4L2_DEBUG_IOCTL
                                        | V4L2_DEBUG_IOCTL_ARG);
 #endif
        ret = 0;
@@ -1755,11 +1755,6 @@ out:
        return ret;
 }
 
-static void dev_release(struct video_device *vfd)
-{
-       /* nothing */
-}
-
 static struct file_operations dev_fops = {
        .owner = THIS_MODULE,
        .open = dev_open,
@@ -1807,7 +1802,7 @@ static struct video_device gspca_template = {
        .name = "gspca main driver",
        .fops = &dev_fops,
        .ioctl_ops = &dev_ioctl_ops,
-       .release = dev_release,         /* mandatory */
+       .release = video_device_release,
        .minor = -1,
 };
 
@@ -1876,16 +1871,18 @@ int gspca_dev_probe(struct usb_interface *intf,
        init_waitqueue_head(&gspca_dev->wq);
 
        /* init video stuff */
-       memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template);
-       gspca_dev->vdev.parent = &dev->dev;
-       gspca_dev->vdev.fops = &dev_fops;
+       gspca_dev->vdev = video_device_alloc();
+       memcpy(gspca_dev->vdev, &gspca_template, sizeof gspca_template);
+       gspca_dev->vdev->parent = &dev->dev;
        gspca_dev->module = module;
        gspca_dev->present = 1;
-       ret = video_register_device(&gspca_dev->vdev,
+       video_set_drvdata(gspca_dev->vdev, gspca_dev);
+       ret = video_register_device(gspca_dev->vdev,
                                  VFL_TYPE_GRABBER,
                                  video_nr);
        if (ret < 0) {
                err("video_register_device err %d", ret);
+               video_device_release(gspca_dev->vdev);
                goto out;
        }
 
@@ -1893,7 +1890,8 @@ int gspca_dev_probe(struct usb_interface *intf,
        PDEBUG(D_PROBE, "probe ok");
        return 0;
 out:
-       kref_put(&gspca_dev->kref, gspca_delete);
+       kfree(gspca_dev->usb_buf);
+       kfree(gspca_dev);
        return ret;
 }
 EXPORT_SYMBOL(gspca_dev_probe);
@@ -1911,7 +1909,7 @@ void gspca_disconnect(struct usb_interface *intf)
        usb_set_intfdata(intf, NULL);
 
 /* We don't want people trying to open up the device */
-       video_unregister_device(&gspca_dev->vdev);
+       video_unregister_device(gspca_dev->vdev);
 
        gspca_dev->present = 0;
        gspca_dev->streaming = 0;
index 2ae1ad7c1483ea8d235f0c9396cbb4f75c3ea632..d25e8d69373b8d94335579d4d337054e80164f31 100644 (file)
@@ -120,7 +120,7 @@ struct gspca_frame {
 };
 
 struct gspca_dev {
-       struct video_device vdev;       /* !! must be the first item */
+       struct video_device *vdev;
        struct module *module;          /* subdriver handling the device */
        struct usb_device *dev;
        struct kref kref;