Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4aaec3ea authored by David Ellingsworth's avatar David Ellingsworth Committed by Mauro Carvalho Chehab
Browse files

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: default avatarJaime Velasco Juan <jsagarribay@gmail.com>
Signed-off-by: default avatarDavid Ellingsworth <david@identd.dyndns.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 714b9a1e
Loading
Loading
Loading
Loading
+23 −61
Original line number Original line Diff line number Diff line
@@ -65,22 +65,6 @@ static struct usb_device_id stkwebcam_table[] = {
};
};
MODULE_DEVICE_TABLE(usb, 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
 * Basic stuff
 */
 */
@@ -694,8 +678,7 @@ static int v4l_stk_open(struct inode *inode, struct file *fp)
		unlock_kernel();
		unlock_kernel();
		return -ENXIO;
		return -ENXIO;
	}
	}
	fp->private_data = vdev;
	fp->private_data = dev;
	kref_get(&dev->kref);
	usb_autopm_get_interface(dev->interface);
	usb_autopm_get_interface(dev->interface);
	unlock_kernel();
	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)
static int v4l_stk_release(struct inode *inode, struct file *fp)
{
{
	struct stk_camera *dev;
	struct stk_camera *dev = fp->private_data;
	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;
	}


	if (dev->owner != fp) {
	if (dev->owner != fp) {
		usb_autopm_put_interface(dev->interface);
		usb_autopm_put_interface(dev->interface);
		kref_put(&dev->kref, stk_camera_cleanup);
		return 0;
		return 0;
	}
	}


@@ -731,7 +701,6 @@ static int v4l_stk_release(struct inode *inode, struct file *fp)
	dev->owner = NULL;
	dev->owner = NULL;


	usb_autopm_put_interface(dev->interface);
	usb_autopm_put_interface(dev->interface);
	kref_put(&dev->kref, stk_camera_cleanup);


	return 0;
	return 0;
}
}
@@ -742,14 +711,8 @@ static ssize_t v4l_stk_read(struct file *fp, char __user *buf,
	int i;
	int i;
	int ret;
	int ret;
	unsigned long flags;
	unsigned long flags;
	struct stk_camera *dev;
	struct video_device *vdev;
	struct stk_sio_buffer *sbuf;
	struct stk_sio_buffer *sbuf;

	struct stk_camera *dev = fp->private_data;
	vdev = video_devdata(fp);
	if (vdev == NULL)
		return -EFAULT;
	dev = vdev_to_camera(vdev);


	if (dev == NULL)
	if (dev == NULL)
		return -EIO;
		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)
static unsigned int v4l_stk_poll(struct file *fp, poll_table *wait)
{
{
	struct stk_camera *dev;
	struct stk_camera *dev = fp->private_data;
	struct video_device *vdev;

	vdev = video_devdata(fp);

	if (vdev == NULL)
		return -EFAULT;


	dev = vdev_to_camera(vdev);
	if (dev == NULL)
	if (dev == NULL)
		return -ENODEV;
		return -ENODEV;


@@ -854,16 +810,12 @@ static int v4l_stk_mmap(struct file *fp, struct vm_area_struct *vma)
	unsigned int i;
	unsigned int i;
	int ret;
	int ret;
	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
	struct stk_camera *dev;
	struct stk_camera *dev = fp->private_data;
	struct video_device *vdev;
	struct stk_sio_buffer *sbuf = NULL;
	struct stk_sio_buffer *sbuf = NULL;


	if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED))
	if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED))
		return -EINVAL;
		return -EINVAL;


	vdev = video_devdata(fp);
	dev = vdev_to_camera(vdev);

	for (i = 0; i < dev->n_sbufs; i++) {
	for (i = 0; i < dev->n_sbufs; i++) {
		if (dev->sio_bufs[i].v4lbuf.m.offset == offset) {
		if (dev->sio_bufs[i].v4lbuf.m.offset == offset) {
			sbuf = dev->sio_bufs + i;
			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)
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 = {
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 = stk_v4l_data;
	dev->vdev.debug = debug;
	dev->vdev.debug = debug;
	dev->vdev.parent = &dev->interface->dev;
	dev->vdev.parent = &dev->interface->dev;
	video_set_drvdata(&dev->vdev, dev);
	err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1);
	err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1);
	if (err)
	if (err)
		STK_ERROR("v4l registration failed\n");
		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)
		const struct usb_device_id *id)
{
{
	int i;
	int i;
	int err;
	int err = 0;


	struct stk_camera *dev = NULL;
	struct stk_camera *dev = NULL;
	struct usb_device *udev = interface_to_usbdev(interface);
	struct usb_device *udev = interface_to_usbdev(interface);
@@ -1409,7 +1366,6 @@ static int stk_camera_probe(struct usb_interface *interface,
		return -ENOMEM;
		return -ENOMEM;
	}
	}


	kref_init(&dev->kref);
	spin_lock_init(&dev->spinlock);
	spin_lock_init(&dev->spinlock);
	init_waitqueue_head(&dev->wait_frame);
	init_waitqueue_head(&dev->wait_frame);


@@ -1442,8 +1398,8 @@ static int stk_camera_probe(struct usb_interface *interface,
	}
	}
	if (!dev->isoc_ep) {
	if (!dev->isoc_ep) {
		STK_ERROR("Could not find isoc-in endpoint");
		STK_ERROR("Could not find isoc-in endpoint");
		kref_put(&dev->kref, stk_camera_cleanup);
		err = -ENODEV;
		return -ENODEV;
		goto error;
	}
	}
	dev->vsettings.brightness = 0x7fff;
	dev->vsettings.brightness = 0x7fff;
	dev->vsettings.palette = V4L2_PIX_FMT_RGB565;
	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);
	err = stk_register_video_device(dev);
	if (err) {
	if (err) {
		kref_put(&dev->kref, stk_camera_cleanup);
		goto error;
		return err;
	}
	}


	stk_create_sysfs_files(&dev->vdev);
	stk_create_sysfs_files(&dev->vdev);
	usb_autopm_enable(dev->interface);
	usb_autopm_enable(dev->interface);


	return 0;
	return 0;

error:
	kfree(dev);
	return err;
}
}


static void stk_camera_disconnect(struct usb_interface *interface)
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);
	wake_up_interruptible(&dev->wait_frame);
	stk_remove_sysfs_files(&dev->vdev);
	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
#ifdef CONFIG_PM
+0 −2
Original line number Original line Diff line number Diff line
@@ -99,7 +99,6 @@ struct stk_camera {


	u8 isoc_ep;
	u8 isoc_ep;


	struct kref kref;
	/* Not sure if this is right */
	/* Not sure if this is right */
	atomic_t urbs_used;
	atomic_t urbs_used;


@@ -121,7 +120,6 @@ struct stk_camera {
	unsigned sequence;
	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)
#define vdev_to_camera(d) container_of(d, struct stk_camera, vdev)


void stk_camera_delete(struct kref *);
void stk_camera_delete(struct kref *);