Re: [PATCH] media: ipu3-cio2: Move functionality from .complete() to .bound()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello all

On 06/05/2022 22:15, Daniel Scally wrote:
> Creating links and registering subdev nodes during the .complete()
> callback has the unfortunate effect of preventing all cameras that
> connect to a notifier from working if any one of their drivers fails
> to probe. Moving the functionality from .complete() to .bound() allows
> those camera sensor drivers that did probe correctly to work regardless.
>
> Signed-off-by: Daniel Scally <djrscally@xxxxxxxxx>
> ---
>
> This results in v4l2_device_register_subdev_nodes() being called multiple times
> but since it's a no-op where the devnode exists already, I think that it's ok.


There ended up being a problem with this. If a camera sensor driver
registers a notifier via v4l2_async_register_subdev_sensor(), the
devnodes for any device that bound to that notifier (a lens controller
for example) would be created where v4l2_device_register_subdev_nodes()
is called by the ipu3-cio2 driver's .complete() callback. This is
because it won't be called until the lens controller's driver has
probed. On the other hand, if the lens controller's driver probes late
(after all the camera sensor drivers) then its devnodes _won't_ be
created because it'll miss the calls to
v4l2_device_register_subdev_nodes() when ipu3-cio2's .bound() is
triggered as their drivers probe. The effect of this is that we still
need a call to v4l2_device_register_subdev_nodes() in .complete() to
make sure we catch anything that's bound to a notifier registered by one
of the camera sensor drivers. This kinda defeats the purpose of the
patch as if an ISP has one sensor linked to a lens controller and one
one sensor without a lens controller, failure during probe of the driver
for the lens-less sensor will mean .complete() is never called, and so
the devnodes for the lens controller won't get created, and so the
sensor with a lens won't work properly anyway.


So - more thought needed on this I think. I still think it's the right
approach to refactor such that a failure in one sensor driver's probe
does not prevent any other sensors present from working provided _they_
probe correctly, but I'm not sure the best way to achieve it now.



>
>  drivers/media/pci/intel/ipu3/ipu3-cio2-main.c | 65 +++++++------------
>  1 file changed, 23 insertions(+), 42 deletions(-)
>
> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> index 93cc0577b6db..6a1bcb20725d 100644
> --- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> @@ -1387,7 +1387,10 @@ static int cio2_notifier_bound(struct v4l2_async_notifier *notifier,
>  {
>  	struct cio2_device *cio2 = to_cio2_device(notifier);
>  	struct sensor_async_subdev *s_asd = to_sensor_asd(asd);
> +	struct device *dev = &cio2->pci_dev->dev;
>  	struct cio2_queue *q;
> +	unsigned int pad;
> +	int ret;
>  
>  	if (cio2->queue[s_asd->csi2.port].sensor)
>  		return -EBUSY;
> @@ -1398,7 +1401,26 @@ static int cio2_notifier_bound(struct v4l2_async_notifier *notifier,
>  	q->sensor = sd;
>  	q->csi_rx_base = cio2->base + CIO2_REG_PIPE_BASE(q->csi2.port);
>  
> -	return 0;
> +	for (pad = 0; pad < q->sensor->entity.num_pads; pad++)
> +		if (q->sensor->entity.pads[pad].flags &
> +					MEDIA_PAD_FL_SOURCE)
> +			break;
> +
> +	if (pad == q->sensor->entity.num_pads) {
> +		dev_err(dev, "failed to find src pad for %s\n",
> +			q->sensor->name);
> +		return -ENXIO;
> +	}
> +
> +	ret = media_create_pad_link(&q->sensor->entity, pad, &q->subdev.entity,
> +				    CIO2_PAD_SINK, 0);
> +	if (ret) {
> +		dev_err(dev, "failed to create link for %s\n",
> +			q->sensor->name);
> +		return ret;
> +	}
> +
> +	return v4l2_device_register_subdev_nodes(&cio2->v4l2_dev);
>  }
>  
>  /* The .unbind callback */
> @@ -1412,50 +1434,9 @@ static void cio2_notifier_unbind(struct v4l2_async_notifier *notifier,
>  	cio2->queue[s_asd->csi2.port].sensor = NULL;
>  }
>  
> -/* .complete() is called after all subdevices have been located */
> -static int cio2_notifier_complete(struct v4l2_async_notifier *notifier)
> -{
> -	struct cio2_device *cio2 = to_cio2_device(notifier);
> -	struct device *dev = &cio2->pci_dev->dev;
> -	struct sensor_async_subdev *s_asd;
> -	struct v4l2_async_subdev *asd;
> -	struct cio2_queue *q;
> -	unsigned int pad;
> -	int ret;
> -
> -	list_for_each_entry(asd, &cio2->notifier.asd_list, asd_list) {
> -		s_asd = to_sensor_asd(asd);
> -		q = &cio2->queue[s_asd->csi2.port];
> -
> -		for (pad = 0; pad < q->sensor->entity.num_pads; pad++)
> -			if (q->sensor->entity.pads[pad].flags &
> -						MEDIA_PAD_FL_SOURCE)
> -				break;
> -
> -		if (pad == q->sensor->entity.num_pads) {
> -			dev_err(dev, "failed to find src pad for %s\n",
> -				q->sensor->name);
> -			return -ENXIO;
> -		}
> -
> -		ret = media_create_pad_link(
> -				&q->sensor->entity, pad,
> -				&q->subdev.entity, CIO2_PAD_SINK,
> -				0);
> -		if (ret) {
> -			dev_err(dev, "failed to create link for %s\n",
> -				q->sensor->name);
> -			return ret;
> -		}
> -	}
> -
> -	return v4l2_device_register_subdev_nodes(&cio2->v4l2_dev);
> -}
> -
>  static const struct v4l2_async_notifier_operations cio2_async_ops = {
>  	.bound = cio2_notifier_bound,
>  	.unbind = cio2_notifier_unbind,
> -	.complete = cio2_notifier_complete,
>  };
>  
>  static int cio2_parse_firmware(struct cio2_device *cio2)



[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux