Hi Jacopo,
On 2018-05-25 13:50:08 +0200, Jacopo Mondi wrote:
> Hi Niklas,
> I might have another question before sending v5.
>
> On Fri, May 25, 2018 at 12:29:44AM +0200, Niklas Söderlund wrote:
> > Hi Jacopo,
> >
> > Thanks for your work.
> >
> > I really like what you did with this patch in v4.
> >
> > On 2018-05-25 00:02:15 +0200, Jacopo Mondi wrote:
> > > The rcar-vin driver so far had a mutually exclusive code path for
> > > handling parallel and CSI-2 video input subdevices, with only the CSI-2
> > > use case supporting media-controller. As we add support for parallel
> > > inputs to Gen3 media-controller compliant code path now parse both port@0
> > > and port@1, handling the media-controller use case in the parallel
> > > bound/unbind notifier operations.
> > >
> > > Signed-off-by: Jacopo Mondi <[email protected]>
> > >
> > > ---
> > > v3 -> v4:
> > > - Change the mc/parallel initialization order. Initialize mc first, then
> > > parallel
> > > - As a consequence no need to delay parallel notifiers registration, the
> > > media controller is set up already when parallel input got parsed,
> > > this greatly simplify the group notifier complete callback.
> > > ---
> > > drivers/media/platform/rcar-vin/rcar-core.c | 56
> > > ++++++++++++++++++-----------
> > > 1 file changed, 35 insertions(+), 21 deletions(-)
> > >
> > > diff --git a/drivers/media/platform/rcar-vin/rcar-core.c
> > > b/drivers/media/platform/rcar-vin/rcar-core.c
> > > index a799684..29619c2 100644
> > > --- a/drivers/media/platform/rcar-vin/rcar-core.c
> > > +++ b/drivers/media/platform/rcar-vin/rcar-core.c
> > > @@ -399,6 +399,11 @@ static int rvin_parallel_subdevice_attach(struct
> > > rvin_dev *vin,
> > > ret = rvin_find_pad(subdev, MEDIA_PAD_FL_SINK);
> > > vin->parallel->sink_pad = ret < 0 ? 0 : ret;
> > >
> > > + if (vin->info->use_mc) {
> > > + vin->parallel->subdev = subdev;
> > > + return 0;
> > > + }
> > > +
> > > /* Find compatible subdevices mbus format */
> > > vin->mbus_code = 0;
> > > code.index = 0;
> > > @@ -460,10 +465,12 @@ static int rvin_parallel_subdevice_attach(struct
> > > rvin_dev *vin,
> > > static void rvin_parallel_subdevice_detach(struct rvin_dev *vin)
> > > {
> > > rvin_v4l2_unregister(vin);
> > > - v4l2_ctrl_handler_free(&vin->ctrl_handler);
> > > -
> > > - vin->vdev.ctrl_handler = NULL;
> > > vin->parallel->subdev = NULL;
> > > +
> > > + if (!vin->info->use_mc) {
> > > + v4l2_ctrl_handler_free(&vin->ctrl_handler);
> > > + vin->vdev.ctrl_handler = NULL;
> > > + }
> > > }
> > >
> > > static int rvin_parallel_notify_complete(struct v4l2_async_notifier
> > > *notifier)
> > > @@ -552,18 +559,18 @@ static int rvin_parallel_parse_v4l2(struct device
> > > *dev,
> > > return 0;
> > > }
> > >
> > > -static int rvin_parallel_graph_init(struct rvin_dev *vin)
> > > +static int rvin_parallel_init(struct rvin_dev *vin)
> > > {
> > > int ret;
> > >
> > > - ret = v4l2_async_notifier_parse_fwnode_endpoints(
> > > - vin->dev, &vin->notifier,
> > > - sizeof(struct rvin_parallel_entity), rvin_parallel_parse_v4l2);
> > > + ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
> > > + vin->dev, &vin->notifier, sizeof(struct rvin_parallel_entity),
> > > + 0, rvin_parallel_parse_v4l2);
> > > if (ret)
> > > return ret;
> > >
> > > if (!vin->parallel)
> > > - return -ENODEV;
> > > + return -ENOTCONN;
> >
> > I think you still should return -ENODEV here if !vin->info->use_mc to
> > preserve Gen2 which runs without media controller behavior. How about:
> >
> > return vin->info->use_mc ? -ENOTCONN : -ENODEV;
> >
> > >
> > > vin_dbg(vin, "Found parallel subdevice %pOF\n",
> > > to_of_node(vin->parallel->asd.match.fwnode));
> > > @@ -784,14 +791,8 @@ static int rvin_mc_init(struct rvin_dev *vin)
> > > {
> > > int ret;
> > >
> > > - vin->pad.flags = MEDIA_PAD_FL_SINK;
> > > - ret = media_entity_pads_init(&vin->vdev.entity, 1, &vin->pad);
> > > - if (ret)
> > > - return ret;
> > > -
> > > - ret = rvin_group_get(vin);
> > > - if (ret)
> > > - return ret;
> > > + if (!vin->info->use_mc)
> > > + return 0;
> > >
> > > ret = rvin_mc_parse_of_graph(vin);
> > > if (ret)
> > > @@ -1074,11 +1075,24 @@ static int rcar_vin_probe(struct platform_device
> > > *pdev)
> > > return ret;
> > >
> > > platform_set_drvdata(pdev, vin);
> > > - if (vin->info->use_mc)
> > > - ret = rvin_mc_init(vin);
> > > - else
> > > - ret = rvin_parallel_graph_init(vin);
> > > - if (ret < 0)
> > > +
> > > + if (vin->info->use_mc) {
> > > + vin->pad.flags = MEDIA_PAD_FL_SINK;
> > > + ret = media_entity_pads_init(&vin->vdev.entity, 1, &vin->pad);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + ret = rvin_group_get(vin);
> > > + if (ret)
> > > + return ret;
> > > + }
> >
> > I don't see why you need to move the media pad creation out of
> > rvin_mc_init(). With the reorder of the rvin_mc_init()
> > rvin_parallel_init() I would keep this in rvin_mc_init().
> >
> > > +
> > > + ret = rvin_mc_init(vin);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + ret = rvin_parallel_init(vin);
> > > + if (ret < 0 && ret != -ENOTCONN)
> > > goto error;
> > >
> > > pm_suspend_ignore_children(&pdev->dev, true);
>
> I've been looking at the error path handling now that the code looks
> like this in the forthcoming v5:
>
> if (vin->info->use_mc) {
> ret = rvin_mc_init(vin);
> if (ret)
> goto error_dma_unregister;
> }
>
> ret = rvin_parallel_init(vin);
> if (ret)
> goto error_group_unregister;
>
>
> ...
>
>
> error_group_unreg:
> if (vin->info->use_mc) {
> mutex_lock(&vin->group->lock);
> if (&vin->v4l2_dev == vin->group->notifier.v4l2_dev) {
> v4l2_async_notifier_unregister(&vin->group->notifier);
> v4l2_async_notifier_cleanup(&vin->group->notifier);
> }
> mutex_unlock(&vin->group->lock);
> rvin_group_put(vin);
> }
>
> error_dma_unreg:
> rvin_dma_unregister(vin);
>
> return ret;
>
> Question is, do you think the group notifier should be unregistered
> and cleaned up if the parallel input initialization of the VIN
> instance whose v4l2_dev is used to register the group notifier fails?
>
> I feel like it should, as the VIN instance whose v4l2_dev is used is
> always the last probing one, so there should be no issues with other
> VINs registering after it and finding themselves without a valid
> notifier.
I agree with you. If the parallel initialization fails everything done
by that particular VIN probe should be undone. So if it have registered
the group notifier it should unregister it.
>
> I felt like it was better anticipating this to you instead of adding
> this part out of the blue in v5.
>
> Also, I think in both parallel input and mc notifier registration, the
> notifier should be cleaned up to release the parsed async subdevices
> memory allocated by
> v4l2_async_notifier_parse_fwnode_endpoints_by_port() if the
> sub-sequent v4l2_async_notifier_register() fails.
I agree with you here as well. That this memory should be cleaned up,
nice catch.
>
> That would be:
>
> @@ -781,18 +782,29 @@ static int rvin_mc_parse_of_graph(struct rvin_dev *vin)
> &vin->group->notifier);
> if (ret < 0) {
> vin_err(vin, "Notifier registration failed\n");
> - return ret;
> + goto error_clean_up_notifier;
> }
>
> return 0;
> +
> +error_clean_up_notifier:
> + v4l2_async_notifier_cleanup(&vin->group->notifier);
> +
> + return ret;
> }
>
> in both mc and parallel initialization functions.
>
> With your ack I can send two patches on top of the currently merged VIN
> version, and rebase my series on top eventually.
>
> Sorry for the long email.
>
> Thanks
> j
>
>
> > > --
> > > 2.7.4
> > >
> >
> > --
> > Regards,
> > Niklas Söderlund
--
Regards,
Niklas Söderlund