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

Commit d7222e7d authored by Chris Rankin's avatar Chris Rankin Committed by Mauro Carvalho Chehab
Browse files

[media] em28xx: fix race on disconnect



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: default avatarChris Rankin <rankincj@yahoo.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent bd829e9d
Loading
Loading
Loading
Loading
+3 −5
Original line number Diff line number Diff line
@@ -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)
{
@@ -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);
@@ -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)
+5 −18
Original line number Diff line number Diff line
@@ -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
 */
@@ -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_del(&dev->devlist);
	mutex_unlock(&em28xx_devlist_mutex);
}