Re: [PATCH v13 14/25] v4l: async: Allow binding notifiers to sub-devices

2017-09-20 Thread Sakari Ailus
Hi Laurent,

On Tue, Sep 19, 2017 at 08:52:56PM +0300, Laurent Pinchart wrote:
> Hi Sakari,
> 
> On Tuesday, 19 September 2017 18:17:32 EEST Sakari Ailus wrote:
> > On Tue, Sep 19, 2017 at 04:52:29PM +0300, Laurent Pinchart wrote:
> > > On Friday, 15 September 2017 17:17:13 EEST Sakari Ailus wrote:
> > > > Registering a notifier has required the knowledge of struct v4l2_device
> > >> for the reason that sub-devices generally are registered to the
> > >> v4l2_device (as well as the media device, also available through
> > >> v4l2_device).
> > >> 
> > >> This information is not available for sub-device drivers at probe time.
> > >> 
> > >> What this patch does is that it allows registering notifiers without
> > >> having v4l2_device around. Instead the sub-device pointer is stored in
> > >> the notifier. Once the sub-device of the driver that registered the
> > >> notifier is registered, the notifier will gain the knowledge of the
> > >> v4l2_device, and the binding of async sub-devices from the sub-device
> > >> driver's notifier may proceed.
> > >> 
> > >> The root notifier's complete callback is only called when all sub-device
> > >> notifiers are completed.
> > > 
> > > This is a bit hard to review, shouldn't it be split in two patches, one
> > > that refactors the functions, and another one that allows binding
> > > notifiers to subdevs ?
> > > 
> > >> Signed-off-by: Sakari Ailus 
> > >> ---
> > >> 
> > >>  drivers/media/v4l2-core/v4l2-async.c | 218 -
> > >>  include/media/v4l2-async.h   |  16 ++-
> > >>  2 files changed, 203 insertions(+), 31 deletions(-)
> > >> 
> > >> diff --git a/drivers/media/v4l2-core/v4l2-async.c
> > >> b/drivers/media/v4l2-core/v4l2-async.c index 4be2f16af051..52fe22b9b6b4
> > >> 100644
> > >> --- a/drivers/media/v4l2-core/v4l2-async.c
> > >> +++ b/drivers/media/v4l2-core/v4l2-async.c
> 
> [snip]
> 
> > >> +/* Unbind all sub-devices in the notifier tree. */
> > >> +static void v4l2_async_notifier_unbind_all_subdevs(
> > >> +struct v4l2_async_notifier *notifier)
> > >> +{
> > >> +struct v4l2_subdev *sd, *tmp;
> > >> 
> > >>  list_for_each_entry_safe(sd, tmp, >done, async_list) {
> > >> 
> > >> +struct v4l2_async_notifier *subdev_notifier =
> > >> +v4l2_async_find_subdev_notifier(sd);
> > >> +
> > >> +if (subdev_notifier)
> > >> +
> > >> v4l2_async_notifier_unbind_all_subdevs(subdev_notifier);
> > >> +
> > >>  v4l2_async_cleanup(sd);
> > >>  
> > >>  v4l2_async_notifier_call_unbind(notifier, sd, sd->asd);
> > >> -}
> > >> 
> > >> -mutex_unlock(_lock);
> > >> +list_del(>async_list);
> > >> +list_add(>async_list, _list);
> > > 
> > > How about list_move() ?
> > 
> > Yeah.
> > 
> > > This seems to be new code, and by the look of it, I wonder whether it
> > > doesn't belong in the reprobing removal patch.
> > 
> > This is not related to re-probing. Here we're moving an async sub-device
> > back to the global sub-device list when its notifier is going away.
> 
> In order to make the subdev bindable again when the notifier will be re-
> registered. This wasn't needed before, as reprobing took care of that.

Ah, I see what you mean now. That the async sub-device is returned to the
global list?

I also noticed the sd shouldn't be set NULL except to the notifier this is
directly called on. I'll fix that as well.

> 
> > >> +}
> > >> 
> > >> +notifier->parent = NULL;
> > >> +notifier->sd = NULL;
> > >>  notifier->v4l2_dev = NULL;
> > >>  }
> 

-- 
Regards,

Sakari Ailus
sakari.ai...@linux.intel.com


Re: [PATCH v13 14/25] v4l: async: Allow binding notifiers to sub-devices

2017-09-19 Thread Laurent Pinchart
Hi Sakari,

On Tuesday, 19 September 2017 18:17:32 EEST Sakari Ailus wrote:
> On Tue, Sep 19, 2017 at 04:52:29PM +0300, Laurent Pinchart wrote:
> > On Friday, 15 September 2017 17:17:13 EEST Sakari Ailus wrote:
> > > Registering a notifier has required the knowledge of struct v4l2_device
> >> for the reason that sub-devices generally are registered to the
> >> v4l2_device (as well as the media device, also available through
> >> v4l2_device).
> >> 
> >> This information is not available for sub-device drivers at probe time.
> >> 
> >> What this patch does is that it allows registering notifiers without
> >> having v4l2_device around. Instead the sub-device pointer is stored in
> >> the notifier. Once the sub-device of the driver that registered the
> >> notifier is registered, the notifier will gain the knowledge of the
> >> v4l2_device, and the binding of async sub-devices from the sub-device
> >> driver's notifier may proceed.
> >> 
> >> The root notifier's complete callback is only called when all sub-device
> >> notifiers are completed.
> > 
> > This is a bit hard to review, shouldn't it be split in two patches, one
> > that refactors the functions, and another one that allows binding
> > notifiers to subdevs ?
> > 
> >> Signed-off-by: Sakari Ailus 
> >> ---
> >> 
> >>  drivers/media/v4l2-core/v4l2-async.c | 218 -
> >>  include/media/v4l2-async.h   |  16 ++-
> >>  2 files changed, 203 insertions(+), 31 deletions(-)
> >> 
> >> diff --git a/drivers/media/v4l2-core/v4l2-async.c
> >> b/drivers/media/v4l2-core/v4l2-async.c index 4be2f16af051..52fe22b9b6b4
> >> 100644
> >> --- a/drivers/media/v4l2-core/v4l2-async.c
> >> +++ b/drivers/media/v4l2-core/v4l2-async.c

[snip]

> >> +/* Unbind all sub-devices in the notifier tree. */
> >> +static void v4l2_async_notifier_unbind_all_subdevs(
> >> +  struct v4l2_async_notifier *notifier)
> >> +{
> >> +  struct v4l2_subdev *sd, *tmp;
> >> 
> >>list_for_each_entry_safe(sd, tmp, >done, async_list) {
> >> 
> >> +  struct v4l2_async_notifier *subdev_notifier =
> >> +  v4l2_async_find_subdev_notifier(sd);
> >> +
> >> +  if (subdev_notifier)
> >> +  v4l2_async_notifier_unbind_all_subdevs(subdev_notifier);
> >> +
> >>v4l2_async_cleanup(sd);
> >>
> >>v4l2_async_notifier_call_unbind(notifier, sd, sd->asd);
> >> -  }
> >> 
> >> -  mutex_unlock(_lock);
> >> +  list_del(>async_list);
> >> +  list_add(>async_list, _list);
> > 
> > How about list_move() ?
> 
> Yeah.
> 
> > This seems to be new code, and by the look of it, I wonder whether it
> > doesn't belong in the reprobing removal patch.
> 
> This is not related to re-probing. Here we're moving an async sub-device
> back to the global sub-device list when its notifier is going away.

In order to make the subdev bindable again when the notifier will be re-
registered. This wasn't needed before, as reprobing took care of that.

> >> +  }
> >> 
> >> +  notifier->parent = NULL;
> >> +  notifier->sd = NULL;
> >>notifier->v4l2_dev = NULL;
> >>  }

-- 
Regards,

Laurent Pinchart



Re: [PATCH v13 14/25] v4l: async: Allow binding notifiers to sub-devices

2017-09-19 Thread Sakari Ailus
Hi Laurent,

On Tue, Sep 19, 2017 at 04:52:29PM +0300, Laurent Pinchart wrote:
> Hi Sakari,
> 
> Thank you for the patch.
> 
> On Friday, 15 September 2017 17:17:13 EEST Sakari Ailus wrote:
> > Registering a notifier has required the knowledge of struct v4l2_device
> > for the reason that sub-devices generally are registered to the
> > v4l2_device (as well as the media device, also available through
> > v4l2_device).
> > 
> > This information is not available for sub-device drivers at probe time.
> > 
> > What this patch does is that it allows registering notifiers without
> > having v4l2_device around. Instead the sub-device pointer is stored in the
> > notifier. Once the sub-device of the driver that registered the notifier
> > is registered, the notifier will gain the knowledge of the v4l2_device,
> > and the binding of async sub-devices from the sub-device driver's notifier
> > may proceed.
> > 
> > The root notifier's complete callback is only called when all sub-device
> > notifiers are completed.
> 
> This is a bit hard to review, shouldn't it be split in two patches, one that 
> refactors the functions, and another one that allows binding notifiers to 
> subdevs ?
> 
> > Signed-off-by: Sakari Ailus 
> > ---
> >  drivers/media/v4l2-core/v4l2-async.c | 218 +++-
> >  include/media/v4l2-async.h   |  16 ++-
> >  2 files changed, 203 insertions(+), 31 deletions(-)
> > 
> > diff --git a/drivers/media/v4l2-core/v4l2-async.c
> > b/drivers/media/v4l2-core/v4l2-async.c index 4be2f16af051..52fe22b9b6b4
> > 100644
> > --- a/drivers/media/v4l2-core/v4l2-async.c
> > +++ b/drivers/media/v4l2-core/v4l2-async.c
> > @@ -53,6 +53,10 @@ static int v4l2_async_notifier_call_complete(struct
> > v4l2_async_notifier *n) return n->ops->complete(n);
> >  }
> > 
> > +static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
> > +  struct v4l2_subdev *sd,
> > +  struct v4l2_async_subdev *asd);
> 
> Forward declarations are often a sign that something is wrong :-/ If you 
> really need to keep this I'd move it right before the function that needs it.

"Something being wrong" here is that we have a data structure (the graph)
and a portion of the graph is parsed at any given point of time; there is
no central location with the knowledge of each node in the graph. Therefore
the process is recursive: you only learn of new nodes to parse when you
have parsed something.

I can move the declaration closer to where it's used.

> 
> >  static bool match_i2c(struct v4l2_subdev *sd, struct v4l2_async_subdev
> > *asd) {
> >  #if IS_ENABLED(CONFIG_I2C)
> > @@ -124,14 +128,127 @@ static struct v4l2_async_subdev
> > *v4l2_async_find_match( return NULL;
> >  }
> > 
> > +/* Find the sub-device notifier registered by a sub-device driver. */
> > +static struct v4l2_async_notifier *v4l2_async_find_subdev_notifier(
> > +   struct v4l2_subdev *sd)
> > +{
> > +   struct v4l2_async_notifier *n;
> > +
> > +   list_for_each_entry(n, _list, list)
> > +   if (n->sd == sd)
> > +   return n;
> > +
> > +   return NULL;
> > +}
> > +
> > +/* Return true if all sub-device notifiers are complete, false otherwise.
> > */ 
> > +static bool v4l2_async_subdev_notifiers_complete(
> > +   struct v4l2_async_notifier *notifier)
> > +{
> > +   struct v4l2_subdev *sd;
> > +
> > +   if (!list_empty(>waiting))
> > +   return false;
> > +
> > +   list_for_each_entry(sd, >done, async_list) {
> > +   struct v4l2_async_notifier *subdev_notifier =
> > +   v4l2_async_find_subdev_notifier(sd);
> > +
> > +   if (subdev_notifier &&
> > +   !v4l2_async_subdev_notifiers_complete(subdev_notifier))
> > +   return false;
> 
> This will loop forever if two subdevs add each other to their respective 
> notifiers. We might not have any use case for that right now, but it's bound 
> to happen, at least as a bug during development, and an infinite loop (with 
> an 
> additional stack overflow bonus) isn't very nice to debug.

Well, yes. If you have a driver bug then this is what could happen.

One option is to check whether an fwnode has already been associated with
an async subdev and fail if it is. I was originally thinking of adding that
but then ended up postponing that for later. I can add that to v14.

> 
> > +   }
> > +
> > +   return true;
> > +}
> > +
> > +/* Get v4l2_device related to the notifier if one can be found. */
> > +static struct v4l2_device *v4l2_async_notifier_find_v4l2_dev(
> > +   struct v4l2_async_notifier *notifier)
> > +{
> > +   while (notifier->parent)
> > +   notifier = notifier->parent;
> > +
> > +   return notifier->v4l2_dev;
> > +}
> > +
> > +/* Test all async sub-devices in a notifier for a match. */
> > +static int v4l2_async_notifier_try_all_subdevs(
> > +   struct v4l2_async_notifier *notifier)
> > +{
> > +   struct 

Re: [PATCH v13 14/25] v4l: async: Allow binding notifiers to sub-devices

2017-09-19 Thread Laurent Pinchart
Hi Sakari,

Thank you for the patch.

On Friday, 15 September 2017 17:17:13 EEST Sakari Ailus wrote:
> Registering a notifier has required the knowledge of struct v4l2_device
> for the reason that sub-devices generally are registered to the
> v4l2_device (as well as the media device, also available through
> v4l2_device).
> 
> This information is not available for sub-device drivers at probe time.
> 
> What this patch does is that it allows registering notifiers without
> having v4l2_device around. Instead the sub-device pointer is stored in the
> notifier. Once the sub-device of the driver that registered the notifier
> is registered, the notifier will gain the knowledge of the v4l2_device,
> and the binding of async sub-devices from the sub-device driver's notifier
> may proceed.
> 
> The root notifier's complete callback is only called when all sub-device
> notifiers are completed.

This is a bit hard to review, shouldn't it be split in two patches, one that 
refactors the functions, and another one that allows binding notifiers to 
subdevs ?

> Signed-off-by: Sakari Ailus 
> ---
>  drivers/media/v4l2-core/v4l2-async.c | 218 +++-
>  include/media/v4l2-async.h   |  16 ++-
>  2 files changed, 203 insertions(+), 31 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-async.c
> b/drivers/media/v4l2-core/v4l2-async.c index 4be2f16af051..52fe22b9b6b4
> 100644
> --- a/drivers/media/v4l2-core/v4l2-async.c
> +++ b/drivers/media/v4l2-core/v4l2-async.c
> @@ -53,6 +53,10 @@ static int v4l2_async_notifier_call_complete(struct
> v4l2_async_notifier *n) return n->ops->complete(n);
>  }
> 
> +static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
> +struct v4l2_subdev *sd,
> +struct v4l2_async_subdev *asd);

Forward declarations are often a sign that something is wrong :-/ If you 
really need to keep this I'd move it right before the function that needs it.

>  static bool match_i2c(struct v4l2_subdev *sd, struct v4l2_async_subdev
> *asd) {
>  #if IS_ENABLED(CONFIG_I2C)
> @@ -124,14 +128,127 @@ static struct v4l2_async_subdev
> *v4l2_async_find_match( return NULL;
>  }
> 
> +/* Find the sub-device notifier registered by a sub-device driver. */
> +static struct v4l2_async_notifier *v4l2_async_find_subdev_notifier(
> + struct v4l2_subdev *sd)
> +{
> + struct v4l2_async_notifier *n;
> +
> + list_for_each_entry(n, _list, list)
> + if (n->sd == sd)
> + return n;
> +
> + return NULL;
> +}
> +
> +/* Return true if all sub-device notifiers are complete, false otherwise.
> */ 
> +static bool v4l2_async_subdev_notifiers_complete(
> + struct v4l2_async_notifier *notifier)
> +{
> + struct v4l2_subdev *sd;
> +
> + if (!list_empty(>waiting))
> + return false;
> +
> + list_for_each_entry(sd, >done, async_list) {
> + struct v4l2_async_notifier *subdev_notifier =
> + v4l2_async_find_subdev_notifier(sd);
> +
> + if (subdev_notifier &&
> + !v4l2_async_subdev_notifiers_complete(subdev_notifier))
> + return false;

This will loop forever if two subdevs add each other to their respective 
notifiers. We might not have any use case for that right now, but it's bound 
to happen, at least as a bug during development, and an infinite loop (with an 
additional stack overflow bonus) isn't very nice to debug.

> + }
> +
> + return true;
> +}
> +
> +/* Get v4l2_device related to the notifier if one can be found. */
> +static struct v4l2_device *v4l2_async_notifier_find_v4l2_dev(
> + struct v4l2_async_notifier *notifier)
> +{
> + while (notifier->parent)
> + notifier = notifier->parent;
> +
> + return notifier->v4l2_dev;
> +}
> +
> +/* Test all async sub-devices in a notifier for a match. */
> +static int v4l2_async_notifier_try_all_subdevs(
> + struct v4l2_async_notifier *notifier)
> +{
> + struct v4l2_subdev *sd;
> +
> + if (!v4l2_async_notifier_find_v4l2_dev(notifier))
> + return 0;
> +
> +again:
> + list_for_each_entry(sd, _list, async_list) {
> + struct v4l2_async_subdev *asd;
> + int ret;
> +
> + asd = v4l2_async_find_match(notifier, sd);
> + if (!asd)
> + continue;
> +
> + ret = v4l2_async_match_notify(notifier, sd, asd);
> + if (ret < 0)
> + return ret;
> +
> + /*
> +  * v4l2_async_match_notify() may lead to registering a
> +  * new notifier and thus changing the async subdevs
> +  * list. In order to proceed safely from here, restart
> +  * parsing the list from the beginning.
> +  */
> + goto again;
> + }
> +
> + return 0;
> +}
> +
> +/* Try completing a notifier. */
> 

Re: [PATCH v13 14/25] v4l: async: Allow binding notifiers to sub-devices

2017-09-19 Thread Hans Verkuil
On 09/15/2017 04:17 PM, Sakari Ailus wrote:
> Registering a notifier has required the knowledge of struct v4l2_device
> for the reason that sub-devices generally are registered to the
> v4l2_device (as well as the media device, also available through
> v4l2_device).
> 
> This information is not available for sub-device drivers at probe time.
> 
> What this patch does is that it allows registering notifiers without
> having v4l2_device around. Instead the sub-device pointer is stored in the
> notifier. Once the sub-device of the driver that registered the notifier
> is registered, the notifier will gain the knowledge of the v4l2_device,
> and the binding of async sub-devices from the sub-device driver's notifier
> may proceed.
> 
> The root notifier's complete callback is only called when all sub-device
> notifiers are completed.
> 
> Signed-off-by: Sakari Ailus 

Acked-by: Hans Verkuil 

Regards,

Hans

> ---
>  drivers/media/v4l2-core/v4l2-async.c | 218 
> ++-
>  include/media/v4l2-async.h   |  16 ++-
>  2 files changed, 203 insertions(+), 31 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-async.c 
> b/drivers/media/v4l2-core/v4l2-async.c
> index 4be2f16af051..52fe22b9b6b4 100644
> --- a/drivers/media/v4l2-core/v4l2-async.c
> +++ b/drivers/media/v4l2-core/v4l2-async.c
> @@ -53,6 +53,10 @@ static int v4l2_async_notifier_call_complete(struct 
> v4l2_async_notifier *n)
>   return n->ops->complete(n);
>  }
>  
> +static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
> +struct v4l2_subdev *sd,
> +struct v4l2_async_subdev *asd);
> +
>  static bool match_i2c(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
>  {
>  #if IS_ENABLED(CONFIG_I2C)
> @@ -124,14 +128,127 @@ static struct v4l2_async_subdev *v4l2_async_find_match(
>   return NULL;
>  }
>  
> +/* Find the sub-device notifier registered by a sub-device driver. */
> +static struct v4l2_async_notifier *v4l2_async_find_subdev_notifier(
> + struct v4l2_subdev *sd)
> +{
> + struct v4l2_async_notifier *n;
> +
> + list_for_each_entry(n, _list, list)
> + if (n->sd == sd)
> + return n;
> +
> + return NULL;
> +}
> +
> +/* Return true if all sub-device notifiers are complete, false otherwise. */
> +static bool v4l2_async_subdev_notifiers_complete(
> + struct v4l2_async_notifier *notifier)
> +{
> + struct v4l2_subdev *sd;
> +
> + if (!list_empty(>waiting))
> + return false;
> +
> + list_for_each_entry(sd, >done, async_list) {
> + struct v4l2_async_notifier *subdev_notifier =
> + v4l2_async_find_subdev_notifier(sd);
> +
> + if (subdev_notifier &&
> + !v4l2_async_subdev_notifiers_complete(subdev_notifier))
> + return false;
> + }
> +
> + return true;
> +}
> +
> +/* Get v4l2_device related to the notifier if one can be found. */
> +static struct v4l2_device *v4l2_async_notifier_find_v4l2_dev(
> + struct v4l2_async_notifier *notifier)
> +{
> + while (notifier->parent)
> + notifier = notifier->parent;
> +
> + return notifier->v4l2_dev;
> +}
> +
> +/* Test all async sub-devices in a notifier for a match. */
> +static int v4l2_async_notifier_try_all_subdevs(
> + struct v4l2_async_notifier *notifier)
> +{
> + struct v4l2_subdev *sd;
> +
> + if (!v4l2_async_notifier_find_v4l2_dev(notifier))
> + return 0;
> +
> +again:
> + list_for_each_entry(sd, _list, async_list) {
> + struct v4l2_async_subdev *asd;
> + int ret;
> +
> + asd = v4l2_async_find_match(notifier, sd);
> + if (!asd)
> + continue;
> +
> + ret = v4l2_async_match_notify(notifier, sd, asd);
> + if (ret < 0)
> + return ret;
> +
> + /*
> +  * v4l2_async_match_notify() may lead to registering a
> +  * new notifier and thus changing the async subdevs
> +  * list. In order to proceed safely from here, restart
> +  * parsing the list from the beginning.
> +  */
> + goto again;
> + }
> +
> + return 0;
> +}
> +
> +/* Try completing a notifier. */
> +static int v4l2_async_notifier_try_complete(
> + struct v4l2_async_notifier *notifier)
> +{
> + do {
> + int ret;
> +
> + /* Any local async sub-devices left? */
> + if (!list_empty(>waiting))
> + return 0;
> +
> + /*
> +  * Any sub-device notifiers waiting for async subdevs
> +  * to be bound?
> +  */
> + if (!v4l2_async_subdev_notifiers_complete(notifier))
> + return 0;
> +
> + /* Proceed completing the 

[PATCH v13 14/25] v4l: async: Allow binding notifiers to sub-devices

2017-09-15 Thread Sakari Ailus
Registering a notifier has required the knowledge of struct v4l2_device
for the reason that sub-devices generally are registered to the
v4l2_device (as well as the media device, also available through
v4l2_device).

This information is not available for sub-device drivers at probe time.

What this patch does is that it allows registering notifiers without
having v4l2_device around. Instead the sub-device pointer is stored in the
notifier. Once the sub-device of the driver that registered the notifier
is registered, the notifier will gain the knowledge of the v4l2_device,
and the binding of async sub-devices from the sub-device driver's notifier
may proceed.

The root notifier's complete callback is only called when all sub-device
notifiers are completed.

Signed-off-by: Sakari Ailus 
---
 drivers/media/v4l2-core/v4l2-async.c | 218 ++-
 include/media/v4l2-async.h   |  16 ++-
 2 files changed, 203 insertions(+), 31 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-async.c 
b/drivers/media/v4l2-core/v4l2-async.c
index 4be2f16af051..52fe22b9b6b4 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -53,6 +53,10 @@ static int v4l2_async_notifier_call_complete(struct 
v4l2_async_notifier *n)
return n->ops->complete(n);
 }
 
+static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
+  struct v4l2_subdev *sd,
+  struct v4l2_async_subdev *asd);
+
 static bool match_i2c(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
 {
 #if IS_ENABLED(CONFIG_I2C)
@@ -124,14 +128,127 @@ static struct v4l2_async_subdev *v4l2_async_find_match(
return NULL;
 }
 
+/* Find the sub-device notifier registered by a sub-device driver. */
+static struct v4l2_async_notifier *v4l2_async_find_subdev_notifier(
+   struct v4l2_subdev *sd)
+{
+   struct v4l2_async_notifier *n;
+
+   list_for_each_entry(n, _list, list)
+   if (n->sd == sd)
+   return n;
+
+   return NULL;
+}
+
+/* Return true if all sub-device notifiers are complete, false otherwise. */
+static bool v4l2_async_subdev_notifiers_complete(
+   struct v4l2_async_notifier *notifier)
+{
+   struct v4l2_subdev *sd;
+
+   if (!list_empty(>waiting))
+   return false;
+
+   list_for_each_entry(sd, >done, async_list) {
+   struct v4l2_async_notifier *subdev_notifier =
+   v4l2_async_find_subdev_notifier(sd);
+
+   if (subdev_notifier &&
+   !v4l2_async_subdev_notifiers_complete(subdev_notifier))
+   return false;
+   }
+
+   return true;
+}
+
+/* Get v4l2_device related to the notifier if one can be found. */
+static struct v4l2_device *v4l2_async_notifier_find_v4l2_dev(
+   struct v4l2_async_notifier *notifier)
+{
+   while (notifier->parent)
+   notifier = notifier->parent;
+
+   return notifier->v4l2_dev;
+}
+
+/* Test all async sub-devices in a notifier for a match. */
+static int v4l2_async_notifier_try_all_subdevs(
+   struct v4l2_async_notifier *notifier)
+{
+   struct v4l2_subdev *sd;
+
+   if (!v4l2_async_notifier_find_v4l2_dev(notifier))
+   return 0;
+
+again:
+   list_for_each_entry(sd, _list, async_list) {
+   struct v4l2_async_subdev *asd;
+   int ret;
+
+   asd = v4l2_async_find_match(notifier, sd);
+   if (!asd)
+   continue;
+
+   ret = v4l2_async_match_notify(notifier, sd, asd);
+   if (ret < 0)
+   return ret;
+
+   /*
+* v4l2_async_match_notify() may lead to registering a
+* new notifier and thus changing the async subdevs
+* list. In order to proceed safely from here, restart
+* parsing the list from the beginning.
+*/
+   goto again;
+   }
+
+   return 0;
+}
+
+/* Try completing a notifier. */
+static int v4l2_async_notifier_try_complete(
+   struct v4l2_async_notifier *notifier)
+{
+   do {
+   int ret;
+
+   /* Any local async sub-devices left? */
+   if (!list_empty(>waiting))
+   return 0;
+
+   /*
+* Any sub-device notifiers waiting for async subdevs
+* to be bound?
+*/
+   if (!v4l2_async_subdev_notifiers_complete(notifier))
+   return 0;
+
+   /* Proceed completing the notifier */
+   ret = v4l2_async_notifier_call_complete(notifier);
+   if (ret < 0)
+   return ret;
+
+   /*
+* Obtain notifier's parent. If there is one, repeat
+* the process, otherwise we're done