@@ -206,7 +206,7 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier)
unsigned int notif_n_subdev = notifier->num_subdevs;
unsigned int n_subdev = min(notif_n_subdev, V4L2_MAX_SUBDEVS);
struct device **dev;
- int i = 0;
+ int i, count = 0;
if (!notifier->v4l2_dev)
return;
@@ -223,27 +223,26 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier)
list_del(¬ifier->list);
list_for_each_entry_safe(sd, tmp, ¬ifier->done, async_list) {
- struct device *d;
-
- d = get_device(sd->dev);
+ dev[count] = get_device(sd->dev);
+ count++;
if (notifier->unbind)
notifier->unbind(notifier, sd, sd->asd);
v4l2_async_cleanup(sd);
-
- /* If we handled USB devices, we'd have to lock the parent too */
- device_release_driver(d);
-
- dev[i++] = d;
}
mutex_unlock(&list_lock);
+ for (i = 0; i < count; i++) {
+ /* If we handled USB devices, we'd have to lock the parent too */
+ device_release_driver(dev[i]);
+ }
+
/*
* Call device_attach() to reprobe devices
*/
- while (i--) {
+ for (i = 0; i < count; i++) {
struct device *d = dev[i];
if (d && device_attach(d) < 0) {
There is no good reason to hold the list_lock when re-probing the devices and it prevents a clean implementation of subdevice notifiers. Move the actual release of the devices outside of the loop which requires the lock to be held. Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> --- drivers/media/v4l2-core/v4l2-async.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-)