There is no good reason to hold the list_lock when reprobing 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@xxxxxxxxxxxx> --- drivers/media/v4l2-core/v4l2-async.c | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index 0acf288d7227ba97..8fc84f7962386ddd 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -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; @@ -222,37 +222,28 @@ 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); + if (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); + mutex_unlock(&list_lock); - /* - * Store device at the device cache, in order to call - * put_device() on the final step - */ + for (i = 0; i < count; i++) { + /* If we handled USB devices, we'd have to lock the parent too */ if (dev) - dev[i++] = d; - else - put_device(d); + device_release_driver(dev[i]); } - mutex_unlock(&list_lock); - /* * Call device_attach() to reprobe devices - * - * NOTE: If dev allocation fails, i is 0, and the whole loop won't be - * executed. */ - while (i--) { + for (i = 0; dev && i < count; i++) { struct device *d = dev[i]; if (d && device_attach(d) < 0) { -- 2.13.1