diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-01-10 09:20:01 -0200 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-01-10 22:35:29 -0200 |
commit | 7528cd273e14020117e6cdb6cc307f223e97c5ed (patch) | |
tree | 872fdcc3f4f8d7349befe6c2a10f079962438827 /drivers/media/video/cx231xx/cx231xx-cards.c | |
parent | 959a119f86d51085ba4e0ec5a68dee6a21c48dfe (diff) | |
download | talos-obmc-linux-7528cd273e14020117e6cdb6cc307f223e97c5ed.tar.gz talos-obmc-linux-7528cd273e14020117e6cdb6cc307f223e97c5ed.zip |
[media] cx231xx: Fix unregister logic
There are several weirdness at the unregister logic.
First of all, IR has a poll thread. This thread needs to be
removed, as it uses some resources associated to the main driver.
So, the driver needs to explicitly unregister the I2C client for
ir-kbd-i2c.
If, for some reason, the driver needs to wait for a close()
to happen, not all memories will be freed, because the free
logic were in the wrong place.
Also, v4l2_device_unregister() seems to be called too early,
as devices are still using it.
Finally, even with the device disconnected, there is one
USB function call that will still try to talk with it.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cx231xx/cx231xx-cards.c')
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-cards.c | 29 |
1 files changed, 16 insertions, 13 deletions
diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c index 2a28882ee1d3..bd82f017ccdf 100644 --- a/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/drivers/media/video/cx231xx/cx231xx-cards.c @@ -843,15 +843,25 @@ void cx231xx_release_resources(struct cx231xx *dev) cx231xx_remove_from_devlist(dev); + cx231xx_ir_exit(dev); + /* Release I2C buses */ cx231xx_dev_uninit(dev); - cx231xx_ir_exit(dev); + /* delete v4l2 device */ + v4l2_device_unregister(&dev->v4l2_dev); usb_put_dev(dev->udev); /* Mark device as unused */ cx231xx_devused &= ~(1 << dev->devno); + + kfree(dev->video_mode.alt_max_pkt_size); + kfree(dev->vbi_mode.alt_max_pkt_size); + kfree(dev->sliced_cc_mode.alt_max_pkt_size); + kfree(dev->ts1_mode.alt_max_pkt_size); + kfree(dev); + dev = NULL; } /* @@ -1329,9 +1339,6 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface) flush_request_modules(dev); - /* delete v4l2 device */ - v4l2_device_unregister(&dev->v4l2_dev); - /* wait until all current v4l2 io is finished then deallocate resources */ mutex_lock(&dev->lock); @@ -1344,6 +1351,9 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface) "deallocation are deferred on close.\n", video_device_node_name(dev->vdev)); + /* Even having users, it is safe to remove the RC i2c driver */ + cx231xx_ir_exit(dev); + dev->state |= DEV_MISCONFIGURED; if (dev->USE_ISO) cx231xx_uninit_isoc(dev); @@ -1354,21 +1364,14 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface) wake_up_interruptible(&dev->wait_stream); } else { dev->state |= DEV_DISCONNECTED; - cx231xx_release_resources(dev); } cx231xx_close_extension(dev); mutex_unlock(&dev->lock); - if (!dev->users) { - kfree(dev->video_mode.alt_max_pkt_size); - kfree(dev->vbi_mode.alt_max_pkt_size); - kfree(dev->sliced_cc_mode.alt_max_pkt_size); - kfree(dev->ts1_mode.alt_max_pkt_size); - kfree(dev); - dev = NULL; - } + if (!dev->users) + cx231xx_release_resources(dev); } static struct usb_driver cx231xx_usb_driver = { |