Skip to content

Commit

Permalink
[media] em28xx: fix race on disconnect
Browse files Browse the repository at this point in the history
This patch closes the race on the device and extension lists at USB disconnect
time. Previously, the device was removed from the device list during
em28xx_release_resources(), and then passed to the em28xx_close_extension()
function so that all extensions could run their fini() operations. However, this
left a (brief, theoretical, highly unlikely ;-)) window between these two calls
during which a new module could call em28xx_register_extension(). The result
would have been that the em28xx_usb_disconnect() function would also have passed
the device to the new extension's fini() function, despite never having called
the extension's init() function.

This patch also restores em28xx_close_extension()'s symmetry with
em28xx_init_extension(), and establishes the property that every device in the
device list must have been initialised for every extension in the extension list.

Signed-off-by: Chris Rankin <rankincj@yahoo.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Chris Rankin authored and Mauro Carvalho Chehab committed Sep 24, 2011
1 parent bd829e9 commit d7222e7
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 23 deletions.
8 changes: 3 additions & 5 deletions drivers/media/video/em28xx/em28xx-cards.c
Original file line number Diff line number Diff line change
Expand Up @@ -2800,9 +2800,9 @@ static void flush_request_modules(struct em28xx *dev)
#endif /* CONFIG_MODULES */

/*
* em28xx_realease_resources()
* em28xx_release_resources()
* unregisters the v4l2,i2c and usb devices
* called when the device gets disconected or at module unload
* called when the device gets disconnected or at module unload
*/
void em28xx_release_resources(struct em28xx *dev)
{
Expand All @@ -2816,8 +2816,6 @@ void em28xx_release_resources(struct em28xx *dev)

em28xx_release_analog_resources(dev);

em28xx_remove_from_devlist(dev);

em28xx_i2c_unregister(dev);

v4l2_device_unregister(&dev->v4l2_dev);
Expand Down Expand Up @@ -3255,7 +3253,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,

/*
* em28xx_usb_disconnect()
* called when the device gets diconencted
* called when the device gets disconnected
* video device will be unregistered on v4l2_close in case it is still open
*/
static void em28xx_usb_disconnect(struct usb_interface *interface)
Expand Down
23 changes: 5 additions & 18 deletions drivers/media/video/em28xx/em28xx-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1183,18 +1183,6 @@ void em28xx_wake_i2c(struct em28xx *dev)
static LIST_HEAD(em28xx_devlist);
static DEFINE_MUTEX(em28xx_devlist_mutex);

/*
* em28xx_realease_resources()
* unregisters the v4l2,i2c and usb devices
* called when the device gets disconected or at module unload
*/
void em28xx_remove_from_devlist(struct em28xx *dev)
{
mutex_lock(&em28xx_devlist_mutex);
list_del(&dev->devlist);
mutex_unlock(&em28xx_devlist_mutex);
};

/*
* Extension interface
*/
Expand Down Expand Up @@ -1245,14 +1233,13 @@ void em28xx_init_extension(struct em28xx *dev)

void em28xx_close_extension(struct em28xx *dev)
{
struct em28xx_ops *ops = NULL;
const struct em28xx_ops *ops = NULL;

mutex_lock(&em28xx_devlist_mutex);
if (!list_empty(&em28xx_extension_devlist)) {
list_for_each_entry(ops, &em28xx_extension_devlist, next) {
if (ops->fini)
ops->fini(dev);
}
list_for_each_entry(ops, &em28xx_extension_devlist, next) {
if (ops->fini)
ops->fini(dev);
}
list_del(&dev->devlist);
mutex_unlock(&em28xx_devlist_mutex);
}

0 comments on commit d7222e7

Please sign in to comment.