When em28xx extensions are loaded/removed, there are two locks:
a single static em28xx_devlist_mutex that registers each extension
and the struct em28xx dev->lock.
When extensions are registered, em28xx_devlist_mutex is taken first,
and then dev->lock.
Be sure that, when extensions are being removed, the same order
will be used.
Reviewed-by: Frank Schäfer <fschaefer.oss@googlemail.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
dev->disconnected = 1;
if (dev->is_audio_only) {
- mutex_lock(&dev->lock);
em28xx_close_extension(dev);
- mutex_unlock(&dev->lock);
return;
}
em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE);
em28xx_uninit_usb_xfer(dev, EM28XX_DIGITAL_MODE);
}
+ mutex_unlock(&dev->lock);
em28xx_close_extension(dev);
+
/* NOTE: must be called BEFORE the resources are released */
+ mutex_lock(&dev->lock);
if (!dev->users)
em28xx_release_resources(dev);
const struct em28xx_ops *ops = NULL;
mutex_lock(&em28xx_devlist_mutex);
+ mutex_lock(&dev->lock);
list_for_each_entry(ops, &em28xx_extension_devlist, next) {
if (ops->fini)
ops->fini(dev);
}
+ mutex_unlock(&dev->lock);
list_del(&dev->devlist);
mutex_unlock(&em28xx_devlist_mutex);
}