From 4aaec3ea41addf6fe4fe029aa535f3c019ee0e6d Mon Sep 17 00:00:00 2001 From: David Ellingsworth Date: Sun, 21 Sep 2008 04:12:03 -0300 Subject: 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 Signed-off-by: David Ellingsworth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/stk-webcam.c | 84 +++++++++++----------------------------- 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[] = { }; MODULE_DEVICE_TABLE(usb, stkwebcam_table); -static void stk_camera_cleanup(struct kref *kref) -{ - struct stk_camera *dev = to_stk_camera(kref); - - STK_INFO("Syntek USB2.0 Camera release resources" - " video device /dev/video%d\n", dev->vdev.minor); - video_unregister_device(&dev->vdev); - video_set_drvdata(&dev->vdev, NULL); - - if (dev->sio_bufs != NULL || dev->isobufs != NULL) - STK_ERROR("We are leaking memory\n"); - usb_put_intf(dev->interface); - kfree(dev); -} - - /* * Basic stuff */ @@ -694,8 +678,7 @@ static int v4l_stk_open(struct inode *inode, struct file *fp) unlock_kernel(); return -ENXIO; } - fp->private_data = vdev; - kref_get(&dev->kref); + fp->private_data = dev; usb_autopm_get_interface(dev->interface); unlock_kernel(); @@ -704,23 +687,10 @@ static int v4l_stk_open(struct inode *inode, struct file *fp) static int v4l_stk_release(struct inode *inode, struct file *fp) { - struct stk_camera *dev; - struct video_device *vdev; - - vdev = video_devdata(fp); - if (vdev == NULL) { - STK_ERROR("v4l_release called w/o video devdata\n"); - return -EFAULT; - } - dev = vdev_to_camera(vdev); - if (dev == NULL) { - STK_ERROR("v4l_release called on removed device\n"); - return -ENODEV; - } + struct stk_camera *dev = fp->private_data; if (dev->owner != fp) { usb_autopm_put_interface(dev->interface); - kref_put(&dev->kref, stk_camera_cleanup); return 0; } @@ -731,7 +701,6 @@ static int v4l_stk_release(struct inode *inode, struct file *fp) dev->owner = NULL; usb_autopm_put_interface(dev->interface); - kref_put(&dev->kref, stk_camera_cleanup); return 0; } @@ -742,14 +711,8 @@ static ssize_t v4l_stk_read(struct file *fp, char __user *buf, int i; int ret; unsigned long flags; - struct stk_camera *dev; - struct video_device *vdev; struct stk_sio_buffer *sbuf; - - vdev = video_devdata(fp); - if (vdev == NULL) - return -EFAULT; - dev = vdev_to_camera(vdev); + struct stk_camera *dev = fp->private_data; if (dev == NULL) return -EIO; @@ -808,15 +771,8 @@ static ssize_t v4l_stk_read(struct file *fp, char __user *buf, static unsigned int v4l_stk_poll(struct file *fp, poll_table *wait) { - struct stk_camera *dev; - struct video_device *vdev; - - vdev = video_devdata(fp); - - if (vdev == NULL) - return -EFAULT; + struct stk_camera *dev = fp->private_data; - dev = vdev_to_camera(vdev); if (dev == NULL) return -ENODEV; @@ -854,16 +810,12 @@ static int v4l_stk_mmap(struct file *fp, struct vm_area_struct *vma) unsigned int i; int ret; unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; - struct stk_camera *dev; - struct video_device *vdev; + struct stk_camera *dev = fp->private_data; struct stk_sio_buffer *sbuf = NULL; if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) return -EINVAL; - vdev = video_devdata(fp); - dev = vdev_to_camera(vdev); - for (i = 0; i < dev->n_sbufs; i++) { if (dev->sio_bufs[i].v4lbuf.m.offset == offset) { sbuf = dev->sio_bufs + i; @@ -1359,6 +1311,12 @@ static const struct v4l2_ioctl_ops v4l_stk_ioctl_ops = { static void stk_v4l_dev_release(struct video_device *vd) { + struct stk_camera *dev = vdev_to_camera(vd); + + if (dev->sio_bufs != NULL || dev->isobufs != NULL) + STK_ERROR("We are leaking memory\n"); + usb_put_intf(dev->interface); + kfree(dev); } static struct video_device stk_v4l_data = { @@ -1379,7 +1337,6 @@ static int stk_register_video_device(struct stk_camera *dev) dev->vdev = stk_v4l_data; dev->vdev.debug = debug; dev->vdev.parent = &dev->interface->dev; - video_set_drvdata(&dev->vdev, dev); err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1); if (err) STK_ERROR("v4l registration failed\n"); @@ -1396,7 +1353,7 @@ static int stk_camera_probe(struct usb_interface *interface, const struct usb_device_id *id) { int i; - int err; + int err = 0; struct stk_camera *dev = NULL; struct usb_device *udev = interface_to_usbdev(interface); @@ -1409,7 +1366,6 @@ static int stk_camera_probe(struct usb_interface *interface, return -ENOMEM; } - kref_init(&dev->kref); spin_lock_init(&dev->spinlock); init_waitqueue_head(&dev->wait_frame); @@ -1442,8 +1398,8 @@ static int stk_camera_probe(struct usb_interface *interface, } if (!dev->isoc_ep) { STK_ERROR("Could not find isoc-in endpoint"); - kref_put(&dev->kref, stk_camera_cleanup); - return -ENODEV; + err = -ENODEV; + goto error; } dev->vsettings.brightness = 0x7fff; dev->vsettings.palette = V4L2_PIX_FMT_RGB565; @@ -1457,14 +1413,17 @@ static int stk_camera_probe(struct usb_interface *interface, err = stk_register_video_device(dev); if (err) { - kref_put(&dev->kref, stk_camera_cleanup); - return err; + goto error; } stk_create_sysfs_files(&dev->vdev); usb_autopm_enable(dev->interface); return 0; + +error: + kfree(dev); + return err; } static void stk_camera_disconnect(struct usb_interface *interface) @@ -1477,7 +1436,10 @@ static void stk_camera_disconnect(struct usb_interface *interface) wake_up_interruptible(&dev->wait_frame); stk_remove_sysfs_files(&dev->vdev); - kref_put(&dev->kref, stk_camera_cleanup); + STK_INFO("Syntek USB2.0 Camera release resources" + "video device /dev/video%d\n", dev->vdev.minor); + + video_unregister_device(&dev->vdev); } #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 { u8 isoc_ep; - struct kref kref; /* Not sure if this is right */ atomic_t urbs_used; @@ -121,7 +120,6 @@ struct stk_camera { unsigned sequence; }; -#define to_stk_camera(d) container_of(d, struct stk_camera, kref) #define vdev_to_camera(d) container_of(d, struct stk_camera, vdev) void stk_camera_delete(struct kref *); -- cgit v1.2.2