[libcamera-devel,5/5] media: v4l2-async: Create links during v4l2_async_match_notify()
diff mbox series

Message ID 20211213232849.40071-6-djrscally@gmail.com
State Not Applicable
Headers show
Series
  • Introduce ancillary links
Related show

Commit Message

Daniel Scally Dec. 13, 2021, 11:28 p.m. UTC
Upon an async fwnode match, there's some typical behaviour that the
notifier and matching subdev will want to do. For example, a notifier
representing a sensor matching to an async subdev representing its
VCM will want to create an ancillary link to expose that relationship
to userspace.

To avoid lots of code in individual drivers, try to build these links
within v4l2 core.

Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
Changes since the rfc:

	- None

 drivers/media/v4l2-core/v4l2-async.c | 51 ++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

Comments

Laurent Pinchart Dec. 14, 2021, 10:22 p.m. UTC | #1
Hi Daniel,

Thank you for the patch.

On Mon, Dec 13, 2021 at 11:28:49PM +0000, Daniel Scally wrote:
> Upon an async fwnode match, there's some typical behaviour that the
> notifier and matching subdev will want to do. For example, a notifier
> representing a sensor matching to an async subdev representing its
> VCM will want to create an ancillary link to expose that relationship
> to userspace.
> 
> To avoid lots of code in individual drivers, try to build these links
> within v4l2 core.
> 
> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> Changes since the rfc:
> 
> 	- None
> 
>  drivers/media/v4l2-core/v4l2-async.c | 51 ++++++++++++++++++++++++++++
>  1 file changed, 51 insertions(+)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> index 0404267f1ae4..6575b1cbe95f 100644
> --- a/drivers/media/v4l2-core/v4l2-async.c
> +++ b/drivers/media/v4l2-core/v4l2-async.c
> @@ -275,6 +275,45 @@ v4l2_async_nf_try_complete(struct v4l2_async_notifier *notifier)
>  static int
>  v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier);
>  
> +static int
> +__v4l2_async_create_ancillary_link(struct v4l2_async_notifier *notifier,
> +				   struct v4l2_subdev *sd)
> +{
> +	struct media_link *link;
> +
> +	if (sd->entity.function != MEDIA_ENT_F_LENS &&
> +	    sd->entity.function != MEDIA_ENT_F_FLASH)
> +		return -EINVAL;
> +
> +	link = media_create_ancillary_link(&notifier->sd->entity, &sd->entity,

Is there a guarantee at this point that notifier->sd->entity has already
been registered with the media_device ? That's done by
media_device_register_entity() called from
v4l2_device_register_subdev().

> +					   MEDIA_LNK_FL_ENABLED |
> +					   MEDIA_LNK_FL_IMMUTABLE);
> +
> +	return IS_ERR(link) ? PTR_ERR(link) : 0;
> +}
> +
> +/*
> + * Setup links on behalf of the notifier and subdev, where it's obvious what

s/Setup/Create/ ("link setup" refers to another operation, enabling and
disabling links at runtime)

> + * should be done. At the moment, we only support cases where the notifier
> + * is a sensor and the subdev is a lens.

s/sensor/camera sensor/
s/lens/lens controller/

> + *
> + * TODO: Setup pad links if the notifier's function is MEDIA_ENT_F_VID_IF_BRIDGE
> + * and the subdev's is MEDIA_ENT_F_CAM_SENSOR
> + */
> +static int v4l2_async_try_create_links(struct v4l2_async_notifier *notifier,
> +				       struct v4l2_subdev *sd)
> +{
> +	if (!notifier->sd)
> +		return 0;
> +
> +	switch (notifier->sd->entity.function) {
> +	case MEDIA_ENT_F_CAM_SENSOR:
> +		return __v4l2_async_create_ancillary_link(notifier, sd);
> +	default:
> +		return 0;
> +	}
> +}
> +
>  static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
>  				   struct v4l2_device *v4l2_dev,
>  				   struct v4l2_subdev *sd,
> @@ -293,6 +332,18 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
>  		return ret;
>  	}
>  
> +	/*
> +	 * Depending of the function of the entities involved, we may want to
> +	 * create links between them (for example between a sensor and its lens
> +	 * or between a sensor's source pad and the connected device's sink
> +	 * pad)

s/)/)./

> +	 */
> +	ret = v4l2_async_try_create_links(notifier, sd);
> +	if (ret) {
> +		v4l2_device_unregister_subdev(sd);
> +		return ret;
> +	}
> +
>  	/* Remove from the waiting list */
>  	list_del(&asd->list);
>  	sd->asd = asd;
Daniel Scally Dec. 14, 2021, 10:36 p.m. UTC | #2
Hi Laurent

On 14/12/2021 22:22, Laurent Pinchart wrote:
> Hi Daniel,
> 
> Thank you for the patch.
> 
> On Mon, Dec 13, 2021 at 11:28:49PM +0000, Daniel Scally wrote:
>> Upon an async fwnode match, there's some typical behaviour that the
>> notifier and matching subdev will want to do. For example, a notifier
>> representing a sensor matching to an async subdev representing its
>> VCM will want to create an ancillary link to expose that relationship
>> to userspace.
>>
>> To avoid lots of code in individual drivers, try to build these links
>> within v4l2 core.
>>
>> Signed-off-by: Daniel Scally <djrscally@gmail.com>
>> ---
>> Changes since the rfc:
>>
>> 	- None
>>
>>  drivers/media/v4l2-core/v4l2-async.c | 51 ++++++++++++++++++++++++++++
>>  1 file changed, 51 insertions(+)
>>
>> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
>> index 0404267f1ae4..6575b1cbe95f 100644
>> --- a/drivers/media/v4l2-core/v4l2-async.c
>> +++ b/drivers/media/v4l2-core/v4l2-async.c
>> @@ -275,6 +275,45 @@ v4l2_async_nf_try_complete(struct v4l2_async_notifier *notifier)
>>  static int
>>  v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier);
>>  
>> +static int
>> +__v4l2_async_create_ancillary_link(struct v4l2_async_notifier *notifier,
>> +				   struct v4l2_subdev *sd)
>> +{
>> +	struct media_link *link;
>> +
>> +	if (sd->entity.function != MEDIA_ENT_F_LENS &&
>> +	    sd->entity.function != MEDIA_ENT_F_FLASH)
>> +		return -EINVAL;
>> +
>> +	link = media_create_ancillary_link(&notifier->sd->entity, &sd->entity,
> 
> Is there a guarantee at this point that notifier->sd->entity has already
> been registered with the media_device ? That's done by
> media_device_register_entity() called from
> v4l2_device_register_subdev().

v4l2_async_match_notify() calls v4l2_device_register_subdev() before the
point that I've added the call to v4l2_async_try_create_links(), so I
think that's covered there.

>> +					   MEDIA_LNK_FL_ENABLED |
>> +					   MEDIA_LNK_FL_IMMUTABLE);
>> +
>> +	return IS_ERR(link) ? PTR_ERR(link) : 0;
>> +}
>> +
>> +/*
>> + * Setup links on behalf of the notifier and subdev, where it's obvious what
> 
> s/Setup/Create/ ("link setup" refers to another operation, enabling and
> disabling links at runtime)

Yes, good point; although that too is a piece of terminology I find a
bit jarring to be honest; I would have named that function
media_entity_configure_link()

> 
>> + * should be done. At the moment, we only support cases where the notifier
>> + * is a sensor and the subdev is a lens.
> 
> s/sensor/camera sensor/
> s/lens/lens controller/
> 
>> + *
>> + * TODO: Setup pad links if the notifier's function is MEDIA_ENT_F_VID_IF_BRIDGE
>> + * and the subdev's is MEDIA_ENT_F_CAM_SENSOR
>> + */
>> +static int v4l2_async_try_create_links(struct v4l2_async_notifier *notifier,
>> +				       struct v4l2_subdev *sd)
>> +{
>> +	if (!notifier->sd)
>> +		return 0;
>> +
>> +	switch (notifier->sd->entity.function) {
>> +	case MEDIA_ENT_F_CAM_SENSOR:
>> +		return __v4l2_async_create_ancillary_link(notifier, sd);
>> +	default:
>> +		return 0;
>> +	}
>> +}
>> +
>>  static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
>>  				   struct v4l2_device *v4l2_dev,
>>  				   struct v4l2_subdev *sd,
>> @@ -293,6 +332,18 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
>>  		return ret;
>>  	}
>>  
>> +	/*
>> +	 * Depending of the function of the entities involved, we may want to
>> +	 * create links between them (for example between a sensor and its lens
>> +	 * or between a sensor's source pad and the connected device's sink
>> +	 * pad)
> 
> s/)/)./
> 
>> +	 */
>> +	ret = v4l2_async_try_create_links(notifier, sd);
>> +	if (ret) {
>> +		v4l2_device_unregister_subdev(sd);
>> +		return ret;
>> +	}
>> +
>>  	/* Remove from the waiting list */
>>  	list_del(&asd->list);
>>  	sd->asd = asd;
>
Laurent Pinchart Dec. 14, 2021, 11:01 p.m. UTC | #3
Hi Daniel,

On Tue, Dec 14, 2021 at 10:36:01PM +0000, Daniel Scally wrote:
> On 14/12/2021 22:22, Laurent Pinchart wrote:
> > On Mon, Dec 13, 2021 at 11:28:49PM +0000, Daniel Scally wrote:
> >> Upon an async fwnode match, there's some typical behaviour that the
> >> notifier and matching subdev will want to do. For example, a notifier
> >> representing a sensor matching to an async subdev representing its
> >> VCM will want to create an ancillary link to expose that relationship
> >> to userspace.
> >>
> >> To avoid lots of code in individual drivers, try to build these links
> >> within v4l2 core.
> >>
> >> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> >> ---
> >> Changes since the rfc:
> >>
> >> 	- None
> >>
> >>  drivers/media/v4l2-core/v4l2-async.c | 51 ++++++++++++++++++++++++++++
> >>  1 file changed, 51 insertions(+)
> >>
> >> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> >> index 0404267f1ae4..6575b1cbe95f 100644
> >> --- a/drivers/media/v4l2-core/v4l2-async.c
> >> +++ b/drivers/media/v4l2-core/v4l2-async.c
> >> @@ -275,6 +275,45 @@ v4l2_async_nf_try_complete(struct v4l2_async_notifier *notifier)
> >>  static int
> >>  v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier);
> >>  
> >> +static int
> >> +__v4l2_async_create_ancillary_link(struct v4l2_async_notifier *notifier,
> >> +				   struct v4l2_subdev *sd)
> >> +{
> >> +	struct media_link *link;
> >> +
> >> +	if (sd->entity.function != MEDIA_ENT_F_LENS &&
> >> +	    sd->entity.function != MEDIA_ENT_F_FLASH)
> >> +		return -EINVAL;
> >> +
> >> +	link = media_create_ancillary_link(&notifier->sd->entity, &sd->entity,
> > 
> > Is there a guarantee at this point that notifier->sd->entity has already
> > been registered with the media_device ? That's done by
> > media_device_register_entity() called from
> > v4l2_device_register_subdev().
> 
> v4l2_async_match_notify() calls v4l2_device_register_subdev() before the
> point that I've added the call to v4l2_async_try_create_links(), so I
> think that's covered there.

It calls it on sd, not notifier->sd. It's the latter that concerns me.

> >> +					   MEDIA_LNK_FL_ENABLED |
> >> +					   MEDIA_LNK_FL_IMMUTABLE);
> >> +
> >> +	return IS_ERR(link) ? PTR_ERR(link) : 0;
> >> +}
> >> +
> >> +/*
> >> + * Setup links on behalf of the notifier and subdev, where it's obvious what
> > 
> > s/Setup/Create/ ("link setup" refers to another operation, enabling and
> > disabling links at runtime)
> 
> Yes, good point; although that too is a piece of terminology I find a
> bit jarring to be honest; I would have named that function
> media_entity_configure_link()
> 
> >> + * should be done. At the moment, we only support cases where the notifier
> >> + * is a sensor and the subdev is a lens.
> > 
> > s/sensor/camera sensor/
> > s/lens/lens controller/
> > 
> >> + *
> >> + * TODO: Setup pad links if the notifier's function is MEDIA_ENT_F_VID_IF_BRIDGE
> >> + * and the subdev's is MEDIA_ENT_F_CAM_SENSOR
> >> + */
> >> +static int v4l2_async_try_create_links(struct v4l2_async_notifier *notifier,
> >> +				       struct v4l2_subdev *sd)
> >> +{
> >> +	if (!notifier->sd)
> >> +		return 0;
> >> +
> >> +	switch (notifier->sd->entity.function) {
> >> +	case MEDIA_ENT_F_CAM_SENSOR:
> >> +		return __v4l2_async_create_ancillary_link(notifier, sd);
> >> +	default:
> >> +		return 0;
> >> +	}
> >> +}
> >> +
> >>  static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
> >>  				   struct v4l2_device *v4l2_dev,
> >>  				   struct v4l2_subdev *sd,
> >> @@ -293,6 +332,18 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
> >>  		return ret;
> >>  	}
> >>  
> >> +	/*
> >> +	 * Depending of the function of the entities involved, we may want to
> >> +	 * create links between them (for example between a sensor and its lens
> >> +	 * or between a sensor's source pad and the connected device's sink
> >> +	 * pad)
> > 
> > s/)/)./
> > 
> >> +	 */
> >> +	ret = v4l2_async_try_create_links(notifier, sd);
> >> +	if (ret) {
> >> +		v4l2_device_unregister_subdev(sd);
> >> +		return ret;
> >> +	}
> >> +
> >>  	/* Remove from the waiting list */
> >>  	list_del(&asd->list);
> >>  	sd->asd = asd;
Daniel Scally Dec. 14, 2021, 11:41 p.m. UTC | #4
Hi Laurent

On 14/12/2021 23:01, Laurent Pinchart wrote:
> Hi Daniel,
>
> On Tue, Dec 14, 2021 at 10:36:01PM +0000, Daniel Scally wrote:
>> On 14/12/2021 22:22, Laurent Pinchart wrote:
>>> On Mon, Dec 13, 2021 at 11:28:49PM +0000, Daniel Scally wrote:
>>>> Upon an async fwnode match, there's some typical behaviour that the
>>>> notifier and matching subdev will want to do. For example, a notifier
>>>> representing a sensor matching to an async subdev representing its
>>>> VCM will want to create an ancillary link to expose that relationship
>>>> to userspace.
>>>>
>>>> To avoid lots of code in individual drivers, try to build these links
>>>> within v4l2 core.
>>>>
>>>> Signed-off-by: Daniel Scally <djrscally@gmail.com>
>>>> ---
>>>> Changes since the rfc:
>>>>
>>>> 	- None
>>>>
>>>>  drivers/media/v4l2-core/v4l2-async.c | 51 ++++++++++++++++++++++++++++
>>>>  1 file changed, 51 insertions(+)
>>>>
>>>> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
>>>> index 0404267f1ae4..6575b1cbe95f 100644
>>>> --- a/drivers/media/v4l2-core/v4l2-async.c
>>>> +++ b/drivers/media/v4l2-core/v4l2-async.c
>>>> @@ -275,6 +275,45 @@ v4l2_async_nf_try_complete(struct v4l2_async_notifier *notifier)
>>>>  static int
>>>>  v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier);
>>>>  
>>>> +static int
>>>> +__v4l2_async_create_ancillary_link(struct v4l2_async_notifier *notifier,
>>>> +				   struct v4l2_subdev *sd)
>>>> +{
>>>> +	struct media_link *link;
>>>> +
>>>> +	if (sd->entity.function != MEDIA_ENT_F_LENS &&
>>>> +	    sd->entity.function != MEDIA_ENT_F_FLASH)
>>>> +		return -EINVAL;
>>>> +
>>>> +	link = media_create_ancillary_link(&notifier->sd->entity, &sd->entity,
>>> Is there a guarantee at this point that notifier->sd->entity has already
>>> been registered with the media_device ? That's done by
>>> media_device_register_entity() called from
>>> v4l2_device_register_subdev().
>> v4l2_async_match_notify() calls v4l2_device_register_subdev() before the
>> point that I've added the call to v4l2_async_try_create_links(), so I
>> think that's covered there.
> It calls it on sd, not notifier->sd. It's the latter that concerns me.


Ah, you're right of course...I guess in that case the notifier->sd would
get registered during the v4l2_async_match_notify() where the sensor
driver's subdev is sd, but I don't think there's any guarantee that that
would happen first...I haven't traced it through but my guess is that it
would depend on the order in which the ipu3-cio2, sensor and lens
controller drivers probed. I'll check to try and be sure how it works
tomorrow

>
>>>> +					   MEDIA_LNK_FL_ENABLED |
>>>> +					   MEDIA_LNK_FL_IMMUTABLE);
>>>> +
>>>> +	return IS_ERR(link) ? PTR_ERR(link) : 0;
>>>> +}
>>>> +
>>>> +/*
>>>> + * Setup links on behalf of the notifier and subdev, where it's obvious what
>>> s/Setup/Create/ ("link setup" refers to another operation, enabling and
>>> disabling links at runtime)
>> Yes, good point; although that too is a piece of terminology I find a
>> bit jarring to be honest; I would have named that function
>> media_entity_configure_link()
>>
>>>> + * should be done. At the moment, we only support cases where the notifier
>>>> + * is a sensor and the subdev is a lens.
>>> s/sensor/camera sensor/
>>> s/lens/lens controller/
>>>
>>>> + *
>>>> + * TODO: Setup pad links if the notifier's function is MEDIA_ENT_F_VID_IF_BRIDGE
>>>> + * and the subdev's is MEDIA_ENT_F_CAM_SENSOR
>>>> + */
>>>> +static int v4l2_async_try_create_links(struct v4l2_async_notifier *notifier,
>>>> +				       struct v4l2_subdev *sd)
>>>> +{
>>>> +	if (!notifier->sd)
>>>> +		return 0;
>>>> +
>>>> +	switch (notifier->sd->entity.function) {
>>>> +	case MEDIA_ENT_F_CAM_SENSOR:
>>>> +		return __v4l2_async_create_ancillary_link(notifier, sd);
>>>> +	default:
>>>> +		return 0;
>>>> +	}
>>>> +}
>>>> +
>>>>  static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
>>>>  				   struct v4l2_device *v4l2_dev,
>>>>  				   struct v4l2_subdev *sd,
>>>> @@ -293,6 +332,18 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
>>>>  		return ret;
>>>>  	}
>>>>  
>>>> +	/*
>>>> +	 * Depending of the function of the entities involved, we may want to
>>>> +	 * create links between them (for example between a sensor and its lens
>>>> +	 * or between a sensor's source pad and the connected device's sink
>>>> +	 * pad)
>>> s/)/)./
>>>
>>>> +	 */
>>>> +	ret = v4l2_async_try_create_links(notifier, sd);
>>>> +	if (ret) {
>>>> +		v4l2_device_unregister_subdev(sd);
>>>> +		return ret;
>>>> +	}
>>>> +
>>>>  	/* Remove from the waiting list */
>>>>  	list_del(&asd->list);
>>>>  	sd->asd = asd;
Laurent Pinchart Dec. 15, 2021, 9:04 a.m. UTC | #5
Hi Dan,

On Tue, Dec 14, 2021 at 11:41:27PM +0000, Daniel Scally wrote:
> On 14/12/2021 23:01, Laurent Pinchart wrote:
> > On Tue, Dec 14, 2021 at 10:36:01PM +0000, Daniel Scally wrote:
> >> On 14/12/2021 22:22, Laurent Pinchart wrote:
> >>> On Mon, Dec 13, 2021 at 11:28:49PM +0000, Daniel Scally wrote:
> >>>> Upon an async fwnode match, there's some typical behaviour that the
> >>>> notifier and matching subdev will want to do. For example, a notifier
> >>>> representing a sensor matching to an async subdev representing its
> >>>> VCM will want to create an ancillary link to expose that relationship
> >>>> to userspace.
> >>>>
> >>>> To avoid lots of code in individual drivers, try to build these links
> >>>> within v4l2 core.
> >>>>
> >>>> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> >>>> ---
> >>>> Changes since the rfc:
> >>>>
> >>>> 	- None
> >>>>
> >>>>  drivers/media/v4l2-core/v4l2-async.c | 51 ++++++++++++++++++++++++++++
> >>>>  1 file changed, 51 insertions(+)
> >>>>
> >>>> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> >>>> index 0404267f1ae4..6575b1cbe95f 100644
> >>>> --- a/drivers/media/v4l2-core/v4l2-async.c
> >>>> +++ b/drivers/media/v4l2-core/v4l2-async.c
> >>>> @@ -275,6 +275,45 @@ v4l2_async_nf_try_complete(struct v4l2_async_notifier *notifier)
> >>>>  static int
> >>>>  v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier);
> >>>>  
> >>>> +static int
> >>>> +__v4l2_async_create_ancillary_link(struct v4l2_async_notifier *notifier,
> >>>> +				   struct v4l2_subdev *sd)
> >>>> +{
> >>>> +	struct media_link *link;
> >>>> +
> >>>> +	if (sd->entity.function != MEDIA_ENT_F_LENS &&
> >>>> +	    sd->entity.function != MEDIA_ENT_F_FLASH)
> >>>> +		return -EINVAL;
> >>>> +
> >>>> +	link = media_create_ancillary_link(&notifier->sd->entity, &sd->entity,
> >>>
> >>> Is there a guarantee at this point that notifier->sd->entity has already
> >>> been registered with the media_device ? That's done by
> >>> media_device_register_entity() called from
> >>> v4l2_device_register_subdev().
> >>
> >> v4l2_async_match_notify() calls v4l2_device_register_subdev() before the
> >> point that I've added the call to v4l2_async_try_create_links(), so I
> >> think that's covered there.
> >
> > It calls it on sd, not notifier->sd. It's the latter that concerns me.
> 
> Ah, you're right of course...I guess in that case the notifier->sd would
> get registered during the v4l2_async_match_notify() where the sensor
> driver's subdev is sd, but I don't think there's any guarantee that that
> would happen first...I haven't traced it through but my guess is that it
> would depend on the order in which the ipu3-cio2, sensor and lens
> controller drivers probed. I'll check to try and be sure how it works
> tomorrow

I was looking at media_device_register_entity(), and it sets

	INIT_LIST_HEAD(&entity->links);
	entity->num_links = 0;
	entity->num_backlinks = 0;

If we create links before that, things may go bad.

> >>>> +					   MEDIA_LNK_FL_ENABLED |
> >>>> +					   MEDIA_LNK_FL_IMMUTABLE);
> >>>> +
> >>>> +	return IS_ERR(link) ? PTR_ERR(link) : 0;
> >>>> +}
> >>>> +
> >>>> +/*
> >>>> + * Setup links on behalf of the notifier and subdev, where it's obvious what
> >>>
> >>> s/Setup/Create/ ("link setup" refers to another operation, enabling and
> >>> disabling links at runtime)
> >>
> >> Yes, good point; although that too is a piece of terminology I find a
> >> bit jarring to be honest; I would have named that function
> >> media_entity_configure_link()
> >>
> >>>> + * should be done. At the moment, we only support cases where the notifier
> >>>> + * is a sensor and the subdev is a lens.
> >>>
> >>> s/sensor/camera sensor/
> >>> s/lens/lens controller/
> >>>
> >>>> + *
> >>>> + * TODO: Setup pad links if the notifier's function is MEDIA_ENT_F_VID_IF_BRIDGE
> >>>> + * and the subdev's is MEDIA_ENT_F_CAM_SENSOR
> >>>> + */
> >>>> +static int v4l2_async_try_create_links(struct v4l2_async_notifier *notifier,
> >>>> +				       struct v4l2_subdev *sd)
> >>>> +{
> >>>> +	if (!notifier->sd)
> >>>> +		return 0;
> >>>> +
> >>>> +	switch (notifier->sd->entity.function) {
> >>>> +	case MEDIA_ENT_F_CAM_SENSOR:
> >>>> +		return __v4l2_async_create_ancillary_link(notifier, sd);
> >>>> +	default:
> >>>> +		return 0;
> >>>> +	}
> >>>> +}
> >>>> +
> >>>>  static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
> >>>>  				   struct v4l2_device *v4l2_dev,
> >>>>  				   struct v4l2_subdev *sd,
> >>>> @@ -293,6 +332,18 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
> >>>>  		return ret;
> >>>>  	}
> >>>>  
> >>>> +	/*
> >>>> +	 * Depending of the function of the entities involved, we may want to
> >>>> +	 * create links between them (for example between a sensor and its lens
> >>>> +	 * or between a sensor's source pad and the connected device's sink
> >>>> +	 * pad)
> >>>
> >>> s/)/)./
> >>>
> >>>> +	 */
> >>>> +	ret = v4l2_async_try_create_links(notifier, sd);
> >>>> +	if (ret) {
> >>>> +		v4l2_device_unregister_subdev(sd);
> >>>> +		return ret;
> >>>> +	}
> >>>> +
> >>>>  	/* Remove from the waiting list */
> >>>>  	list_del(&asd->list);
> >>>>  	sd->asd = asd;
Sakari Ailus Dec. 15, 2021, 9:44 a.m. UTC | #6
On Wed, Dec 15, 2021 at 11:04:44AM +0200, Laurent Pinchart wrote:
> Hi Dan,
> 
> On Tue, Dec 14, 2021 at 11:41:27PM +0000, Daniel Scally wrote:
> > On 14/12/2021 23:01, Laurent Pinchart wrote:
> > > On Tue, Dec 14, 2021 at 10:36:01PM +0000, Daniel Scally wrote:
> > >> On 14/12/2021 22:22, Laurent Pinchart wrote:
> > >>> On Mon, Dec 13, 2021 at 11:28:49PM +0000, Daniel Scally wrote:
> > >>>> Upon an async fwnode match, there's some typical behaviour that the
> > >>>> notifier and matching subdev will want to do. For example, a notifier
> > >>>> representing a sensor matching to an async subdev representing its
> > >>>> VCM will want to create an ancillary link to expose that relationship
> > >>>> to userspace.
> > >>>>
> > >>>> To avoid lots of code in individual drivers, try to build these links
> > >>>> within v4l2 core.
> > >>>>
> > >>>> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> > >>>> ---
> > >>>> Changes since the rfc:
> > >>>>
> > >>>> 	- None
> > >>>>
> > >>>>  drivers/media/v4l2-core/v4l2-async.c | 51 ++++++++++++++++++++++++++++
> > >>>>  1 file changed, 51 insertions(+)
> > >>>>
> > >>>> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> > >>>> index 0404267f1ae4..6575b1cbe95f 100644
> > >>>> --- a/drivers/media/v4l2-core/v4l2-async.c
> > >>>> +++ b/drivers/media/v4l2-core/v4l2-async.c
> > >>>> @@ -275,6 +275,45 @@ v4l2_async_nf_try_complete(struct v4l2_async_notifier *notifier)
> > >>>>  static int
> > >>>>  v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier);
> > >>>>  
> > >>>> +static int
> > >>>> +__v4l2_async_create_ancillary_link(struct v4l2_async_notifier *notifier,
> > >>>> +				   struct v4l2_subdev *sd)
> > >>>> +{
> > >>>> +	struct media_link *link;
> > >>>> +
> > >>>> +	if (sd->entity.function != MEDIA_ENT_F_LENS &&
> > >>>> +	    sd->entity.function != MEDIA_ENT_F_FLASH)
> > >>>> +		return -EINVAL;
> > >>>> +
> > >>>> +	link = media_create_ancillary_link(&notifier->sd->entity, &sd->entity,
> > >>>
> > >>> Is there a guarantee at this point that notifier->sd->entity has already
> > >>> been registered with the media_device ? That's done by
> > >>> media_device_register_entity() called from
> > >>> v4l2_device_register_subdev().
> > >>
> > >> v4l2_async_match_notify() calls v4l2_device_register_subdev() before the
> > >> point that I've added the call to v4l2_async_try_create_links(), so I
> > >> think that's covered there.
> > >
> > > It calls it on sd, not notifier->sd. It's the latter that concerns me.
> > 
> > Ah, you're right of course...I guess in that case the notifier->sd would
> > get registered during the v4l2_async_match_notify() where the sensor
> > driver's subdev is sd, but I don't think there's any guarantee that that
> > would happen first...I haven't traced it through but my guess is that it
> > would depend on the order in which the ipu3-cio2, sensor and lens
> > controller drivers probed. I'll check to try and be sure how it works
> > tomorrow
> 
> I was looking at media_device_register_entity(), and it sets
> 
> 	INIT_LIST_HEAD(&entity->links);
> 	entity->num_links = 0;
> 	entity->num_backlinks = 0;
> 
> If we create links before that, things may go bad.

Yes.

There's a guarantee that the notifier's complete callback is called once
the notifier's subdevs as well as sub-notifiers are bound and complete. But
there's no guarantee on the initialisation of related entities.

Especially for sensors, the async subdev is registered after the sensor's
own async notifier.

I wonder if the ugly registered callback could be used for this purpose.
Better of course would be to avoid that.
Laurent Pinchart Dec. 15, 2021, 9:55 a.m. UTC | #7
Hi Sakari,

On Wed, Dec 15, 2021 at 11:44:29AM +0200, Sakari Ailus wrote:
> On Wed, Dec 15, 2021 at 11:04:44AM +0200, Laurent Pinchart wrote:
> > On Tue, Dec 14, 2021 at 11:41:27PM +0000, Daniel Scally wrote:
> > > On 14/12/2021 23:01, Laurent Pinchart wrote:
> > > > On Tue, Dec 14, 2021 at 10:36:01PM +0000, Daniel Scally wrote:
> > > >> On 14/12/2021 22:22, Laurent Pinchart wrote:
> > > >>> On Mon, Dec 13, 2021 at 11:28:49PM +0000, Daniel Scally wrote:
> > > >>>> Upon an async fwnode match, there's some typical behaviour that the
> > > >>>> notifier and matching subdev will want to do. For example, a notifier
> > > >>>> representing a sensor matching to an async subdev representing its
> > > >>>> VCM will want to create an ancillary link to expose that relationship
> > > >>>> to userspace.
> > > >>>>
> > > >>>> To avoid lots of code in individual drivers, try to build these links
> > > >>>> within v4l2 core.
> > > >>>>
> > > >>>> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> > > >>>> ---
> > > >>>> Changes since the rfc:
> > > >>>>
> > > >>>> 	- None
> > > >>>>
> > > >>>>  drivers/media/v4l2-core/v4l2-async.c | 51 ++++++++++++++++++++++++++++
> > > >>>>  1 file changed, 51 insertions(+)
> > > >>>>
> > > >>>> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> > > >>>> index 0404267f1ae4..6575b1cbe95f 100644
> > > >>>> --- a/drivers/media/v4l2-core/v4l2-async.c
> > > >>>> +++ b/drivers/media/v4l2-core/v4l2-async.c
> > > >>>> @@ -275,6 +275,45 @@ v4l2_async_nf_try_complete(struct v4l2_async_notifier *notifier)
> > > >>>>  static int
> > > >>>>  v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier);
> > > >>>>  
> > > >>>> +static int
> > > >>>> +__v4l2_async_create_ancillary_link(struct v4l2_async_notifier *notifier,
> > > >>>> +				   struct v4l2_subdev *sd)
> > > >>>> +{
> > > >>>> +	struct media_link *link;
> > > >>>> +
> > > >>>> +	if (sd->entity.function != MEDIA_ENT_F_LENS &&
> > > >>>> +	    sd->entity.function != MEDIA_ENT_F_FLASH)
> > > >>>> +		return -EINVAL;
> > > >>>> +
> > > >>>> +	link = media_create_ancillary_link(&notifier->sd->entity, &sd->entity,
> > > >>>
> > > >>> Is there a guarantee at this point that notifier->sd->entity has already
> > > >>> been registered with the media_device ? That's done by
> > > >>> media_device_register_entity() called from
> > > >>> v4l2_device_register_subdev().
> > > >>
> > > >> v4l2_async_match_notify() calls v4l2_device_register_subdev() before the
> > > >> point that I've added the call to v4l2_async_try_create_links(), so I
> > > >> think that's covered there.
> > > >
> > > > It calls it on sd, not notifier->sd. It's the latter that concerns me.
> > > 
> > > Ah, you're right of course...I guess in that case the notifier->sd would
> > > get registered during the v4l2_async_match_notify() where the sensor
> > > driver's subdev is sd, but I don't think there's any guarantee that that
> > > would happen first...I haven't traced it through but my guess is that it
> > > would depend on the order in which the ipu3-cio2, sensor and lens
> > > controller drivers probed. I'll check to try and be sure how it works
> > > tomorrow
> > 
> > I was looking at media_device_register_entity(), and it sets
> > 
> > 	INIT_LIST_HEAD(&entity->links);
> > 	entity->num_links = 0;
> > 	entity->num_backlinks = 0;
> > 
> > If we create links before that, things may go bad.
> 
> Yes.
> 
> There's a guarantee that the notifier's complete callback is called once
> the notifier's subdevs as well as sub-notifiers are bound and complete. But
> there's no guarantee on the initialisation of related entities.
> 
> Especially for sensors, the async subdev is registered after the sensor's
> own async notifier.
> 
> I wonder if the ugly registered callback could be used for this purpose.
> Better of course would be to avoid that.

I'd really like all these links to be created automatically by the code,
but given the very loosely defined rules regarding entity
initialization, I'm worried this may not be possible without quite a bit
of cleanup first :-(

It looks like quite a bit of the work done in
media_device_register_entity() could (and likely should) be moved to
media_entity_init(), but I'm not sure if that would be enough to
properly fix the issue.
Daniel Scally Dec. 15, 2021, 11:10 p.m. UTC | #8
Hi Laurent, Sakari

On 15/12/2021 09:55, Laurent Pinchart wrote:
> Hi Sakari,
> 
> On Wed, Dec 15, 2021 at 11:44:29AM +0200, Sakari Ailus wrote:
>> On Wed, Dec 15, 2021 at 11:04:44AM +0200, Laurent Pinchart wrote:
>>> On Tue, Dec 14, 2021 at 11:41:27PM +0000, Daniel Scally wrote:
>>>> On 14/12/2021 23:01, Laurent Pinchart wrote:
>>>>> On Tue, Dec 14, 2021 at 10:36:01PM +0000, Daniel Scally wrote:
>>>>>> On 14/12/2021 22:22, Laurent Pinchart wrote:
>>>>>>> On Mon, Dec 13, 2021 at 11:28:49PM +0000, Daniel Scally wrote:
>>>>>>>> Upon an async fwnode match, there's some typical behaviour that the
>>>>>>>> notifier and matching subdev will want to do. For example, a notifier
>>>>>>>> representing a sensor matching to an async subdev representing its
>>>>>>>> VCM will want to create an ancillary link to expose that relationship
>>>>>>>> to userspace.
>>>>>>>>
>>>>>>>> To avoid lots of code in individual drivers, try to build these links
>>>>>>>> within v4l2 core.
>>>>>>>>
>>>>>>>> Signed-off-by: Daniel Scally <djrscally@gmail.com>
>>>>>>>> ---
>>>>>>>> Changes since the rfc:
>>>>>>>>
>>>>>>>> 	- None
>>>>>>>>
>>>>>>>>  drivers/media/v4l2-core/v4l2-async.c | 51 ++++++++++++++++++++++++++++
>>>>>>>>  1 file changed, 51 insertions(+)
>>>>>>>>
>>>>>>>> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
>>>>>>>> index 0404267f1ae4..6575b1cbe95f 100644
>>>>>>>> --- a/drivers/media/v4l2-core/v4l2-async.c
>>>>>>>> +++ b/drivers/media/v4l2-core/v4l2-async.c
>>>>>>>> @@ -275,6 +275,45 @@ v4l2_async_nf_try_complete(struct v4l2_async_notifier *notifier)
>>>>>>>>  static int
>>>>>>>>  v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier);
>>>>>>>>  
>>>>>>>> +static int
>>>>>>>> +__v4l2_async_create_ancillary_link(struct v4l2_async_notifier *notifier,
>>>>>>>> +				   struct v4l2_subdev *sd)
>>>>>>>> +{
>>>>>>>> +	struct media_link *link;
>>>>>>>> +
>>>>>>>> +	if (sd->entity.function != MEDIA_ENT_F_LENS &&
>>>>>>>> +	    sd->entity.function != MEDIA_ENT_F_FLASH)
>>>>>>>> +		return -EINVAL;
>>>>>>>> +
>>>>>>>> +	link = media_create_ancillary_link(&notifier->sd->entity, &sd->entity,
>>>>>>>
>>>>>>> Is there a guarantee at this point that notifier->sd->entity has already
>>>>>>> been registered with the media_device ? That's done by
>>>>>>> media_device_register_entity() called from
>>>>>>> v4l2_device_register_subdev().
>>>>>>
>>>>>> v4l2_async_match_notify() calls v4l2_device_register_subdev() before the
>>>>>> point that I've added the call to v4l2_async_try_create_links(), so I
>>>>>> think that's covered there.
>>>>>
>>>>> It calls it on sd, not notifier->sd. It's the latter that concerns me.
>>>>
>>>> Ah, you're right of course...I guess in that case the notifier->sd would
>>>> get registered during the v4l2_async_match_notify() where the sensor
>>>> driver's subdev is sd, but I don't think there's any guarantee that that
>>>> would happen first...I haven't traced it through but my guess is that it
>>>> would depend on the order in which the ipu3-cio2, sensor and lens
>>>> controller drivers probed. I'll check to try and be sure how it works
>>>> tomorrow
>>>
>>> I was looking at media_device_register_entity(), and it sets
>>>
>>> 	INIT_LIST_HEAD(&entity->links);
>>> 	entity->num_links = 0;
>>> 	entity->num_backlinks = 0;
>>>
>>> If we create links before that, things may go bad.

Yep, that definitely looks like it would make things go badly wrong. I'm
building with a delayed ov8865 probe now, let's see what happens...

>>
>> Yes.
>>
>> There's a guarantee that the notifier's complete callback is called once
>> the notifier's subdevs as well as sub-notifiers are bound and complete. But
>> there's no guarantee on the initialisation of related entities.
>>
>> Especially for sensors, the async subdev is registered after the sensor's
>> own async notifier.
>>
>> I wonder if the ugly registered callback could be used for this purpose.
>> Better of course would be to avoid that.
> 
> I'd really like all these links to be created automatically by the code,
> but given the very loosely defined rules regarding entity
> initialization, I'm worried this may not be possible without quite a bit
> of cleanup first :-(


Yeah. At present at least the primary entity would need to be linked to
the media dev, as it's taking primary->graph_obj.mdev as the pointer to
use in media_gobj_create() in media_create_ancillary_link(). That's a
pretty big problem actually...but I'd really like to try and solve it as
we could cut a lot of code out the other drivers if we do the same thing
for the data links.

One way around it might be to defer matching in v4l2_async_find_match()
if the notifier's subdev hasn't picked up an mdev itself yet...which
could guarantee the ordering but sort of breaks the asynchronicity of it
all. I'm almost certainly missing some other reason that that's a
terrible idea too.

I'll try and explore some ways to do this that still keeps the link
setup within core - thanks for pointing it out Laurent

> It looks like quite a bit of the work done in
> media_device_register_entity() could (and likely should) be moved to
> media_entity_init(), but I'm not sure if that would be enough to
> properly fix the issue.

I guess you mean media_entity_pads_init()? Or media_device_init()?
>
Laurent Pinchart Dec. 15, 2021, 11:14 p.m. UTC | #9
Hi Dan,

On Wed, Dec 15, 2021 at 11:10:09PM +0000, Daniel Scally wrote:
> On 15/12/2021 09:55, Laurent Pinchart wrote:
> > On Wed, Dec 15, 2021 at 11:44:29AM +0200, Sakari Ailus wrote:
> >> On Wed, Dec 15, 2021 at 11:04:44AM +0200, Laurent Pinchart wrote:
> >>> On Tue, Dec 14, 2021 at 11:41:27PM +0000, Daniel Scally wrote:
> >>>> On 14/12/2021 23:01, Laurent Pinchart wrote:
> >>>>> On Tue, Dec 14, 2021 at 10:36:01PM +0000, Daniel Scally wrote:
> >>>>>> On 14/12/2021 22:22, Laurent Pinchart wrote:
> >>>>>>> On Mon, Dec 13, 2021 at 11:28:49PM +0000, Daniel Scally wrote:
> >>>>>>>> Upon an async fwnode match, there's some typical behaviour that the
> >>>>>>>> notifier and matching subdev will want to do. For example, a notifier
> >>>>>>>> representing a sensor matching to an async subdev representing its
> >>>>>>>> VCM will want to create an ancillary link to expose that relationship
> >>>>>>>> to userspace.
> >>>>>>>>
> >>>>>>>> To avoid lots of code in individual drivers, try to build these links
> >>>>>>>> within v4l2 core.
> >>>>>>>>
> >>>>>>>> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> >>>>>>>> ---
> >>>>>>>> Changes since the rfc:
> >>>>>>>>
> >>>>>>>> 	- None
> >>>>>>>>
> >>>>>>>>  drivers/media/v4l2-core/v4l2-async.c | 51 ++++++++++++++++++++++++++++
> >>>>>>>>  1 file changed, 51 insertions(+)
> >>>>>>>>
> >>>>>>>> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> >>>>>>>> index 0404267f1ae4..6575b1cbe95f 100644
> >>>>>>>> --- a/drivers/media/v4l2-core/v4l2-async.c
> >>>>>>>> +++ b/drivers/media/v4l2-core/v4l2-async.c
> >>>>>>>> @@ -275,6 +275,45 @@ v4l2_async_nf_try_complete(struct v4l2_async_notifier *notifier)
> >>>>>>>>  static int
> >>>>>>>>  v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier);
> >>>>>>>>  
> >>>>>>>> +static int
> >>>>>>>> +__v4l2_async_create_ancillary_link(struct v4l2_async_notifier *notifier,
> >>>>>>>> +				   struct v4l2_subdev *sd)
> >>>>>>>> +{
> >>>>>>>> +	struct media_link *link;
> >>>>>>>> +
> >>>>>>>> +	if (sd->entity.function != MEDIA_ENT_F_LENS &&
> >>>>>>>> +	    sd->entity.function != MEDIA_ENT_F_FLASH)
> >>>>>>>> +		return -EINVAL;
> >>>>>>>> +
> >>>>>>>> +	link = media_create_ancillary_link(&notifier->sd->entity, &sd->entity,
> >>>>>>>
> >>>>>>> Is there a guarantee at this point that notifier->sd->entity has already
> >>>>>>> been registered with the media_device ? That's done by
> >>>>>>> media_device_register_entity() called from
> >>>>>>> v4l2_device_register_subdev().
> >>>>>>
> >>>>>> v4l2_async_match_notify() calls v4l2_device_register_subdev() before the
> >>>>>> point that I've added the call to v4l2_async_try_create_links(), so I
> >>>>>> think that's covered there.
> >>>>>
> >>>>> It calls it on sd, not notifier->sd. It's the latter that concerns me.
> >>>>
> >>>> Ah, you're right of course...I guess in that case the notifier->sd would
> >>>> get registered during the v4l2_async_match_notify() where the sensor
> >>>> driver's subdev is sd, but I don't think there's any guarantee that that
> >>>> would happen first...I haven't traced it through but my guess is that it
> >>>> would depend on the order in which the ipu3-cio2, sensor and lens
> >>>> controller drivers probed. I'll check to try and be sure how it works
> >>>> tomorrow
> >>>
> >>> I was looking at media_device_register_entity(), and it sets
> >>>
> >>> 	INIT_LIST_HEAD(&entity->links);
> >>> 	entity->num_links = 0;
> >>> 	entity->num_backlinks = 0;
> >>>
> >>> If we create links before that, things may go bad.
> 
> Yep, that definitely looks like it would make things go badly wrong. I'm
> building with a delayed ov8865 probe now, let's see what happens...
> 
> >> Yes.
> >>
> >> There's a guarantee that the notifier's complete callback is called once
> >> the notifier's subdevs as well as sub-notifiers are bound and complete. But
> >> there's no guarantee on the initialisation of related entities.
> >>
> >> Especially for sensors, the async subdev is registered after the sensor's
> >> own async notifier.
> >>
> >> I wonder if the ugly registered callback could be used for this purpose.
> >> Better of course would be to avoid that.
> > 
> > I'd really like all these links to be created automatically by the code,
> > but given the very loosely defined rules regarding entity
> > initialization, I'm worried this may not be possible without quite a bit
> > of cleanup first :-(
> 
> Yeah. At present at least the primary entity would need to be linked to
> the media dev, as it's taking primary->graph_obj.mdev as the pointer to
> use in media_gobj_create() in media_create_ancillary_link(). That's a
> pretty big problem actually...but I'd really like to try and solve it as
> we could cut a lot of code out the other drivers if we do the same thing
> for the data links.
> 
> One way around it might be to defer matching in v4l2_async_find_match()
> if the notifier's subdev hasn't picked up an mdev itself yet...which
> could guarantee the ordering but sort of breaks the asynchronicity of it
> all. I'm almost certainly missing some other reason that that's a
> terrible idea too.

v4l2-async is a mess, that's the main reason why everybody is reluctant
to touch it :-) On my long todo list is a task to rewrite it from
scratch, with an API that wouldn't be V4L2-specific.

> I'll try and explore some ways to do this that still keeps the link
> setup within core - thanks for pointing it out Laurent
> 
> > It looks like quite a bit of the work done in
> > media_device_register_entity() could (and likely should) be moved to
> > media_entity_init(), but I'm not sure if that would be enough to
> > properly fix the issue.
> 
> I guess you mean media_entity_pads_init()? Or media_device_init()?

The former, sorry.
kernel test robot Dec. 16, 2021, 11:10 a.m. UTC | #10
Hi Daniel,

I love your patch! Yet something to improve:

[auto build test ERROR on media-tree/master]
[also build test ERROR on v5.16-rc5 next-20211215]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Daniel-Scally/Introduce-ancillary-links/20211214-073020
base:   git://linuxtv.org/media_tree.git master
config: x86_64-randconfig-r015-20211216 (https://download.01.org/0day-ci/archive/20211216/202112161906.gHHRLukN-lkp@intel.com/config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project dd245bab9fbb364faa1581e4f92ba3119a872fba)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/7e7fcd65e8144f3ffa337760c26fb786f4028466
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Daniel-Scally/Introduce-ancillary-links/20211214-073020
        git checkout 7e7fcd65e8144f3ffa337760c26fb786f4028466
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash drivers/media/v4l2-core/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> drivers/media/v4l2-core/v4l2-async.c:284:10: error: no member named 'entity' in 'struct v4l2_subdev'
           if (sd->entity.function != MEDIA_ENT_F_LENS &&
               ~~  ^
   drivers/media/v4l2-core/v4l2-async.c:285:10: error: no member named 'entity' in 'struct v4l2_subdev'
               sd->entity.function != MEDIA_ENT_F_FLASH)
               ~~  ^
   drivers/media/v4l2-core/v4l2-async.c:288:52: error: no member named 'entity' in 'struct v4l2_subdev'
           link = media_create_ancillary_link(&notifier->sd->entity, &sd->entity,
                                               ~~~~~~~~~~~~  ^
   drivers/media/v4l2-core/v4l2-async.c:288:65: error: no member named 'entity' in 'struct v4l2_subdev'
           link = media_create_ancillary_link(&notifier->sd->entity, &sd->entity,
                                                                      ~~  ^
   drivers/media/v4l2-core/v4l2-async.c:309:24: error: no member named 'entity' in 'struct v4l2_subdev'
           switch (notifier->sd->entity.function) {
                   ~~~~~~~~~~~~  ^
   5 errors generated.


vim +284 drivers/media/v4l2-core/v4l2-async.c

   277	
   278	static int
   279	__v4l2_async_create_ancillary_link(struct v4l2_async_notifier *notifier,
   280					   struct v4l2_subdev *sd)
   281	{
   282		struct media_link *link;
   283	
 > 284		if (sd->entity.function != MEDIA_ENT_F_LENS &&
   285		    sd->entity.function != MEDIA_ENT_F_FLASH)
   286			return -EINVAL;
   287	
   288		link = media_create_ancillary_link(&notifier->sd->entity, &sd->entity,
   289						   MEDIA_LNK_FL_ENABLED |
   290						   MEDIA_LNK_FL_IMMUTABLE);
   291	
   292		return IS_ERR(link) ? PTR_ERR(link) : 0;
   293	}
   294	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Daniel Scally Dec. 16, 2021, 11:14 a.m. UTC | #11
I guess this needs to be a no-op if the media controller API isn't
configured.

On 16/12/2021 11:10, kernel test robot wrote:
> Hi Daniel,
>
> I love your patch! Yet something to improve:
>
> [auto build test ERROR on media-tree/master]
> [also build test ERROR on v5.16-rc5 next-20211215]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch]
>
> url:    https://github.com/0day-ci/linux/commits/Daniel-Scally/Introduce-ancillary-links/20211214-073020
> base:   git://linuxtv.org/media_tree.git master
> config: x86_64-randconfig-r015-20211216 (https://download.01.org/0day-ci/archive/20211216/202112161906.gHHRLukN-lkp@intel.com/config)
> compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project dd245bab9fbb364faa1581e4f92ba3119a872fba)
> reproduce (this is a W=1 build):
>         wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
>         chmod +x ~/bin/make.cross
>         # https://github.com/0day-ci/linux/commit/7e7fcd65e8144f3ffa337760c26fb786f4028466
>         git remote add linux-review https://github.com/0day-ci/linux
>         git fetch --no-tags linux-review Daniel-Scally/Introduce-ancillary-links/20211214-073020
>         git checkout 7e7fcd65e8144f3ffa337760c26fb786f4028466
>         # save the config file to linux build tree
>         mkdir build_dir
>         COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash drivers/media/v4l2-core/
>
> If you fix the issue, kindly add following tag as appropriate
> Reported-by: kernel test robot <lkp@intel.com>
>
> All errors (new ones prefixed by >>):
>
>>> drivers/media/v4l2-core/v4l2-async.c:284:10: error: no member named 'entity' in 'struct v4l2_subdev'
>            if (sd->entity.function != MEDIA_ENT_F_LENS &&
>                ~~  ^
>    drivers/media/v4l2-core/v4l2-async.c:285:10: error: no member named 'entity' in 'struct v4l2_subdev'
>                sd->entity.function != MEDIA_ENT_F_FLASH)
>                ~~  ^
>    drivers/media/v4l2-core/v4l2-async.c:288:52: error: no member named 'entity' in 'struct v4l2_subdev'
>            link = media_create_ancillary_link(&notifier->sd->entity, &sd->entity,
>                                                ~~~~~~~~~~~~  ^
>    drivers/media/v4l2-core/v4l2-async.c:288:65: error: no member named 'entity' in 'struct v4l2_subdev'
>            link = media_create_ancillary_link(&notifier->sd->entity, &sd->entity,
>                                                                       ~~  ^
>    drivers/media/v4l2-core/v4l2-async.c:309:24: error: no member named 'entity' in 'struct v4l2_subdev'
>            switch (notifier->sd->entity.function) {
>                    ~~~~~~~~~~~~  ^
>    5 errors generated.
>
>
> vim +284 drivers/media/v4l2-core/v4l2-async.c
>
>    277	
>    278	static int
>    279	__v4l2_async_create_ancillary_link(struct v4l2_async_notifier *notifier,
>    280					   struct v4l2_subdev *sd)
>    281	{
>    282		struct media_link *link;
>    283	
>  > 284		if (sd->entity.function != MEDIA_ENT_F_LENS &&
>    285		    sd->entity.function != MEDIA_ENT_F_FLASH)
>    286			return -EINVAL;
>    287	
>    288		link = media_create_ancillary_link(&notifier->sd->entity, &sd->entity,
>    289						   MEDIA_LNK_FL_ENABLED |
>    290						   MEDIA_LNK_FL_IMMUTABLE);
>    291	
>    292		return IS_ERR(link) ? PTR_ERR(link) : 0;
>    293	}
>    294	
>
> ---
> 0-DAY CI Kernel Test Service, Intel Corporation
> https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Daniel Scally Jan. 16, 2022, 12:01 a.m. UTC | #12
Hi Laurent

On 15/12/2021 09:04, Laurent Pinchart wrote:

A month to the day! Sorry about the delay - more on that below...

> Hi Dan,
>
> On Tue, Dec 14, 2021 at 11:41:27PM +0000, Daniel Scally wrote:
>> On 14/12/2021 23:01, Laurent Pinchart wrote:
>>> On Tue, Dec 14, 2021 at 10:36:01PM +0000, Daniel Scally wrote:
>>>> On 14/12/2021 22:22, Laurent Pinchart wrote:
>>>>> On Mon, Dec 13, 2021 at 11:28:49PM +0000, Daniel Scally wrote:
>>>>>> Upon an async fwnode match, there's some typical behaviour that the
>>>>>> notifier and matching subdev will want to do. For example, a notifier
>>>>>> representing a sensor matching to an async subdev representing its
>>>>>> VCM will want to create an ancillary link to expose that relationship
>>>>>> to userspace.
>>>>>>
>>>>>> To avoid lots of code in individual drivers, try to build these links
>>>>>> within v4l2 core.
>>>>>>
>>>>>> Signed-off-by: Daniel Scally <djrscally@gmail.com>
>>>>>> ---
>>>>>> Changes since the rfc:
>>>>>>
>>>>>> 	- None
>>>>>>
>>>>>>  drivers/media/v4l2-core/v4l2-async.c | 51 ++++++++++++++++++++++++++++
>>>>>>  1 file changed, 51 insertions(+)
>>>>>>
>>>>>> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
>>>>>> index 0404267f1ae4..6575b1cbe95f 100644
>>>>>> --- a/drivers/media/v4l2-core/v4l2-async.c
>>>>>> +++ b/drivers/media/v4l2-core/v4l2-async.c
>>>>>> @@ -275,6 +275,45 @@ v4l2_async_nf_try_complete(struct v4l2_async_notifier *notifier)
>>>>>>  static int
>>>>>>  v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier);
>>>>>>  
>>>>>> +static int
>>>>>> +__v4l2_async_create_ancillary_link(struct v4l2_async_notifier *notifier,
>>>>>> +				   struct v4l2_subdev *sd)
>>>>>> +{
>>>>>> +	struct media_link *link;
>>>>>> +
>>>>>> +	if (sd->entity.function != MEDIA_ENT_F_LENS &&
>>>>>> +	    sd->entity.function != MEDIA_ENT_F_FLASH)
>>>>>> +		return -EINVAL;
>>>>>> +
>>>>>> +	link = media_create_ancillary_link(&notifier->sd->entity, &sd->entity,
>>>>> Is there a guarantee at this point that notifier->sd->entity has already
>>>>> been registered with the media_device ? That's done by
>>>>> media_device_register_entity() called from
>>>>> v4l2_device_register_subdev().
>>>> v4l2_async_match_notify() calls v4l2_device_register_subdev() before the
>>>> point that I've added the call to v4l2_async_try_create_links(), so I
>>>> think that's covered there.
>>> It calls it on sd, not notifier->sd. It's the latter that concerns me.
>> Ah, you're right of course...I guess in that case the notifier->sd would
>> get registered during the v4l2_async_match_notify() where the sensor
>> driver's subdev is sd, but I don't think there's any guarantee that that
>> would happen first...I haven't traced it through but my guess is that it
>> would depend on the order in which the ipu3-cio2, sensor and lens
>> controller drivers probed. I'll check to try and be sure how it works
>> tomorrow
> I was looking at media_device_register_entity(), and it sets
>
> 	INIT_LIST_HEAD(&entity->links);
> 	entity->num_links = 0;
> 	entity->num_backlinks = 0;
>
> If we create links before that, things may go bad.


It looks like there _is_ a guarantee of ordering actually. When the
ov8865's notifier is registered in v4l2_async_register_subdev_sensor(),
v4l2_async_nf_try_all_subdevs() is called against it, but at that point
v4l2_async_nf_find_v4l2_dev() won't find anything for the ov8865's
notifier even if the dw9719 has already probed and has it's async_subdev
waiting because the notifier has no parent and no directly assigned
v4l2_dev, so the function exits before trying to match anything (this
same logic guards all calls to v4l2_async_find_match()). Very shortly
after that v4l2_async_register_subdev() is called for the ov8865's
subdev which will match to ipu3-cio2's notifier. In
v4l2_async_match_notify() for that match the ipu3-cio2's notifier is
assigned as parent to the ov8865's notifier, but _after_
v4l2_device_register_subdev() is called for the ov8865. From that point
on v4l2_async_nf_find_v4l2_dev() will return a pointer and the matching
for the dw9719 will work correctly. So unless I've missed something, I
think it's ok.

This took me a long time to figure out, because I reset libcamera to
master for some reason and then totally forgot that I had done
that...which meant the auto-focus wasn't working when I tested it and I
convinced myself that my deliberate screwing of the probe ordering _did_
break it. After tearing my hair out for an embarrassing amount of time I
eventually figured out what I had done and got to the bottom of it -
sorry for the delay!

>
>>>>>> +					   MEDIA_LNK_FL_ENABLED |
>>>>>> +					   MEDIA_LNK_FL_IMMUTABLE);
>>>>>> +
>>>>>> +	return IS_ERR(link) ? PTR_ERR(link) : 0;
>>>>>> +}
>>>>>> +
>>>>>> +/*
>>>>>> + * Setup links on behalf of the notifier and subdev, where it's obvious what
>>>>> s/Setup/Create/ ("link setup" refers to another operation, enabling and
>>>>> disabling links at runtime)
>>>> Yes, good point; although that too is a piece of terminology I find a
>>>> bit jarring to be honest; I would have named that function
>>>> media_entity_configure_link()
>>>>
>>>>>> + * should be done. At the moment, we only support cases where the notifier
>>>>>> + * is a sensor and the subdev is a lens.
>>>>> s/sensor/camera sensor/
>>>>> s/lens/lens controller/
>>>>>
>>>>>> + *
>>>>>> + * TODO: Setup pad links if the notifier's function is MEDIA_ENT_F_VID_IF_BRIDGE
>>>>>> + * and the subdev's is MEDIA_ENT_F_CAM_SENSOR
>>>>>> + */
>>>>>> +static int v4l2_async_try_create_links(struct v4l2_async_notifier *notifier,
>>>>>> +				       struct v4l2_subdev *sd)
>>>>>> +{
>>>>>> +	if (!notifier->sd)
>>>>>> +		return 0;
>>>>>> +
>>>>>> +	switch (notifier->sd->entity.function) {
>>>>>> +	case MEDIA_ENT_F_CAM_SENSOR:
>>>>>> +		return __v4l2_async_create_ancillary_link(notifier, sd);
>>>>>> +	default:
>>>>>> +		return 0;
>>>>>> +	}
>>>>>> +}
>>>>>> +
>>>>>>  static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
>>>>>>  				   struct v4l2_device *v4l2_dev,
>>>>>>  				   struct v4l2_subdev *sd,
>>>>>> @@ -293,6 +332,18 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
>>>>>>  		return ret;
>>>>>>  	}
>>>>>>  
>>>>>> +	/*
>>>>>> +	 * Depending of the function of the entities involved, we may want to
>>>>>> +	 * create links between them (for example between a sensor and its lens
>>>>>> +	 * or between a sensor's source pad and the connected device's sink
>>>>>> +	 * pad)
>>>>> s/)/)./
>>>>>
>>>>>> +	 */
>>>>>> +	ret = v4l2_async_try_create_links(notifier, sd);
>>>>>> +	if (ret) {
>>>>>> +		v4l2_device_unregister_subdev(sd);
>>>>>> +		return ret;
>>>>>> +	}
>>>>>> +
>>>>>>  	/* Remove from the waiting list */
>>>>>>  	list_del(&asd->list);
>>>>>>  	sd->asd = asd;

Patch
diff mbox series

diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index 0404267f1ae4..6575b1cbe95f 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -275,6 +275,45 @@  v4l2_async_nf_try_complete(struct v4l2_async_notifier *notifier)
 static int
 v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier);
 
+static int
+__v4l2_async_create_ancillary_link(struct v4l2_async_notifier *notifier,
+				   struct v4l2_subdev *sd)
+{
+	struct media_link *link;
+
+	if (sd->entity.function != MEDIA_ENT_F_LENS &&
+	    sd->entity.function != MEDIA_ENT_F_FLASH)
+		return -EINVAL;
+
+	link = media_create_ancillary_link(&notifier->sd->entity, &sd->entity,
+					   MEDIA_LNK_FL_ENABLED |
+					   MEDIA_LNK_FL_IMMUTABLE);
+
+	return IS_ERR(link) ? PTR_ERR(link) : 0;
+}
+
+/*
+ * Setup links on behalf of the notifier and subdev, where it's obvious what
+ * should be done. At the moment, we only support cases where the notifier
+ * is a sensor and the subdev is a lens.
+ *
+ * TODO: Setup pad links if the notifier's function is MEDIA_ENT_F_VID_IF_BRIDGE
+ * and the subdev's is MEDIA_ENT_F_CAM_SENSOR
+ */
+static int v4l2_async_try_create_links(struct v4l2_async_notifier *notifier,
+				       struct v4l2_subdev *sd)
+{
+	if (!notifier->sd)
+		return 0;
+
+	switch (notifier->sd->entity.function) {
+	case MEDIA_ENT_F_CAM_SENSOR:
+		return __v4l2_async_create_ancillary_link(notifier, sd);
+	default:
+		return 0;
+	}
+}
+
 static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
 				   struct v4l2_device *v4l2_dev,
 				   struct v4l2_subdev *sd,
@@ -293,6 +332,18 @@  static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
 		return ret;
 	}
 
+	/*
+	 * Depending of the function of the entities involved, we may want to
+	 * create links between them (for example between a sensor and its lens
+	 * or between a sensor's source pad and the connected device's sink
+	 * pad)
+	 */
+	ret = v4l2_async_try_create_links(notifier, sd);
+	if (ret) {
+		v4l2_device_unregister_subdev(sd);
+		return ret;
+	}
+
 	/* Remove from the waiting list */
 	list_del(&asd->list);
 	sd->asd = asd;