The patch number 14809 was added via Douglas Schilling Landgraf 
<[email protected]>
to http://linuxtv.org/hg/v4l-dvb master development tree.

Kernel patches in this development tree may be modified to be backward
compatible with older kernels. Compatibility modifications will be
removed before inclusion into the mainstream Kernel

If anyone has any objections, please let us know by sending a message to:
        Linux Media Mailing List <[email protected]>

------

From: Hans Verkuil  <[email protected]>
hdpvr: fix disconnect sequence


Disconnecting the HDPVR caused a kernel oops if lockdep was enabled.
In addition, if an app still had video0 open and attempted to call ioctl
when the device was already disconnected the system would crash.

Move the freeing and cleanup code to the release function: that is the
right place for it since you know when you get there that nobody is
using the device.

Also removed usb_set_intfdata: v4l2_device_register sets this already
to v4l2_dev.

Priority: normal

Signed-off-by: Hans Verkuil <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
Signed-off-by: Douglas Schilling Landgraf <[email protected]>


---

 linux/drivers/media/video/hdpvr/hdpvr-core.c  |   33 ++----------------
 linux/drivers/media/video/hdpvr/hdpvr-video.c |   18 +++++++++
 linux/drivers/media/video/hdpvr/hdpvr.h       |    5 ++
 3 files changed, 28 insertions(+), 28 deletions(-)

diff -r 972954a1a821 -r 29037c55d591 
linux/drivers/media/video/hdpvr/hdpvr-core.c
--- a/linux/drivers/media/video/hdpvr/hdpvr-core.c      Wed May 12 15:38:17 
2010 -0300
+++ b/linux/drivers/media/video/hdpvr/hdpvr-core.c      Wed May 12 15:39:25 
2010 -0300
@@ -373,9 +373,6 @@
        }
 #endif /* CONFIG_I2C */
 
-       /* save our data pointer in this interface device */
-       usb_set_intfdata(interface, dev);
-
        /* let the user know what node this device is now attached to */
        v4l2_info(&dev->v4l2_dev, "device now attached to %s\n",
                  video_device_node_name(dev->video_dev));
@@ -391,44 +388,24 @@
 
 static void hdpvr_disconnect(struct usb_interface *interface)
 {
-       struct hdpvr_device *dev;
+       struct hdpvr_device *dev = to_hdpvr_dev(usb_get_intfdata(interface));
 
-       dev = usb_get_intfdata(interface);
-       usb_set_intfdata(interface, NULL);
-
+       v4l2_info(&dev->v4l2_dev, "device %s disconnected\n",
+                 video_device_node_name(dev->video_dev));
        /* prevent more I/O from starting and stop any ongoing */
        mutex_lock(&dev->io_mutex);
        dev->status = STATUS_DISCONNECTED;
-       v4l2_device_disconnect(&dev->v4l2_dev);
-       video_unregister_device(dev->video_dev);
        wake_up_interruptible(&dev->wait_data);
        wake_up_interruptible(&dev->wait_buffer);
        mutex_unlock(&dev->io_mutex);
+       v4l2_device_disconnect(&dev->v4l2_dev);
        msleep(100);
        flush_workqueue(dev->workqueue);
        mutex_lock(&dev->io_mutex);
        hdpvr_cancel_queue(dev);
-       destroy_workqueue(dev->workqueue);
        mutex_unlock(&dev->io_mutex);
-
-       /* deregister I2C adapter */
-#ifdef CONFIG_I2C
-       mutex_lock(&dev->i2c_mutex);
-       if (dev->i2c_adapter)
-               i2c_del_adapter(dev->i2c_adapter);
-       kfree(dev->i2c_adapter);
-       dev->i2c_adapter = NULL;
-       mutex_unlock(&dev->i2c_mutex);
-#endif /* CONFIG_I2C */
-
+       video_unregister_device(dev->video_dev);
        atomic_dec(&dev_nr);
-
-       v4l2_info(&dev->v4l2_dev, "device %s disconnected\n",
-                 video_device_node_name(dev->video_dev));
-
-       v4l2_device_unregister(&dev->v4l2_dev);
-       kfree(dev->usbc_buf);
-       kfree(dev);
 }
 
 
diff -r 972954a1a821 -r 29037c55d591 
linux/drivers/media/video/hdpvr/hdpvr-video.c
--- a/linux/drivers/media/video/hdpvr/hdpvr-video.c     Wed May 12 15:38:17 
2010 -0300
+++ b/linux/drivers/media/video/hdpvr/hdpvr-video.c     Wed May 12 15:39:25 
2010 -0300
@@ -1214,6 +1214,24 @@
        struct hdpvr_device *dev = video_get_drvdata(vdev);
 
        hdpvr_delete(dev);
+       mutex_lock(&dev->io_mutex);
+       destroy_workqueue(dev->workqueue);
+       mutex_unlock(&dev->io_mutex);
+
+       v4l2_device_unregister(&dev->v4l2_dev);
+
+       /* deregister I2C adapter */
+#ifdef CONFIG_I2C
+       mutex_lock(&dev->i2c_mutex);
+       if (dev->i2c_adapter)
+               i2c_del_adapter(dev->i2c_adapter);
+       kfree(dev->i2c_adapter);
+       dev->i2c_adapter = NULL;
+       mutex_unlock(&dev->i2c_mutex);
+#endif /* CONFIG_I2C */
+
+       kfree(dev->usbc_buf);
+       kfree(dev);
 }
 
 static const struct video_device hdpvr_video_template = {
diff -r 972954a1a821 -r 29037c55d591 linux/drivers/media/video/hdpvr/hdpvr.h
--- a/linux/drivers/media/video/hdpvr/hdpvr.h   Wed May 12 15:38:17 2010 -0300
+++ b/linux/drivers/media/video/hdpvr/hdpvr.h   Wed May 12 15:39:25 2010 -0300
@@ -111,6 +111,11 @@
        u8                      *usbc_buf;
 };
 
+static inline struct hdpvr_device *to_hdpvr_dev(struct v4l2_device *v4l2_dev)
+{
+       return container_of(v4l2_dev, struct hdpvr_device, v4l2_dev);
+}
+
 
 /* buffer one bulk urb of data */
 struct hdpvr_buffer {


---

Patch is available at: 
http://linuxtv.org/hg/v4l-dvb/rev/29037c55d591d22e37f8fae2e1aadf35cacec966

_______________________________________________
linuxtv-commits mailing list
[email protected]
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits

Reply via email to