diff mbox series

[net-next:,v3,6/8] net: core: switch to fwnode_find_net_device_by_node()

Message ID 20220727064321.2953971-7-mw@semihalf.com (mailing list archive)
State Changes Requested
Delegated to: Netdev Maintainers
Headers show
Series DSA: switch to fwnode_/device_ | expand

Checks

Context Check Description
netdev/tree_selection success Clearly marked for net-next, async
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix success Link
netdev/cover_letter success Series has a cover letter
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit fail Errors and warnings before: 3214 this patch: 3214
netdev/cc_maintainers warning 7 maintainers not CCed: frowand.list@gmail.com robh+dt@kernel.org linux-mediatek@lists.infradead.org devicetree@vger.kernel.org atenart@kernel.org linux-arm-kernel@lists.infradead.org matthias.bgg@gmail.com
netdev/build_clang fail Errors and warnings before: 709 this patch: 709
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn fail Errors and warnings before: 3312 this patch: 3312
netdev/checkpatch warning WARNING: line length of 88 exceeds 80 columns
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Marcin Wojtas July 27, 2022, 6:43 a.m. UTC
A helper function which allows getting the struct net_device pointer
associated with a given device tree node can be more generic and
also support alternative hardware description. Switch to fwnode_
and update the only existing caller in DSA subsystem.
For that purpose use newly added fwnode_dev_node_match helper routine.

Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
 include/linux/etherdevice.h |  1 +
 include/linux/of_net.h      |  6 -----
 net/core/net-sysfs.c        | 25 ++++++--------------
 net/dsa/dsa2.c              |  3 ++-
 4 files changed, 10 insertions(+), 25 deletions(-)

Comments

Vladimir Oltean July 27, 2022, 2:31 p.m. UTC | #1
On Wed, Jul 27, 2022 at 08:43:19AM +0200, Marcin Wojtas wrote:
> A helper function which allows getting the struct net_device pointer
> associated with a given device tree node can be more generic and
> also support alternative hardware description. Switch to fwnode_
> and update the only existing caller in DSA subsystem.
> For that purpose use newly added fwnode_dev_node_match helper routine.
> 
> Signed-off-by: Marcin Wojtas <mw@semihalf.com>
> ---
> -struct net_device *of_find_net_device_by_node(struct device_node *np)
> +struct net_device *fwnode_find_net_device_by_node(struct fwnode_handle *fwnode)
>  {
>  	struct device *dev;
>  
> -	dev = class_find_device(&net_class, NULL, np, of_dev_node_match);
> +	dev = class_find_device(&net_class, NULL, fwnode, fwnode_find_parent_dev_match);

This needs to maintain compatibility with DSA masters that have
dev->of_node but don't have dev->fwnode populated.

>  	if (!dev)
>  		return NULL;
>  
>  	return to_net_dev(dev);
>  }
> -EXPORT_SYMBOL(of_find_net_device_by_node);
> -#endif
> +EXPORT_SYMBOL(fwnode_find_net_device_by_node);
Marcin Wojtas July 27, 2022, 3:18 p.m. UTC | #2
śr., 27 lip 2022 o 16:31 Vladimir Oltean <olteanv@gmail.com> napisał(a):
>
> On Wed, Jul 27, 2022 at 08:43:19AM +0200, Marcin Wojtas wrote:
> > A helper function which allows getting the struct net_device pointer
> > associated with a given device tree node can be more generic and
> > also support alternative hardware description. Switch to fwnode_
> > and update the only existing caller in DSA subsystem.
> > For that purpose use newly added fwnode_dev_node_match helper routine.
> >
> > Signed-off-by: Marcin Wojtas <mw@semihalf.com>
> > ---
> > -struct net_device *of_find_net_device_by_node(struct device_node *np)
> > +struct net_device *fwnode_find_net_device_by_node(struct fwnode_handle *fwnode)
> >  {
> >       struct device *dev;
> >
> > -     dev = class_find_device(&net_class, NULL, np, of_dev_node_match);
> > +     dev = class_find_device(&net_class, NULL, fwnode, fwnode_find_parent_dev_match);
>
> This needs to maintain compatibility with DSA masters that have
> dev->of_node but don't have dev->fwnode populated.
>

Do you mean a situation analogous to what I addressed in:
[net-next: PATCH v3 4/8] net: mvpp2: initialize port fwnode pointer
?

I found indeed a couple of drivers that may require a similar change
(e.g. dpaa2).

IMO we have 2 options:
- update these drivers
- add some kind of fallback? If yes, I am wondering about an elegant
solution - maybe add an extra check inside
fwnode_find_parent_dev_match?

What would you suggest?

Best regards,
Marcin

> >       if (!dev)
> >               return NULL;
> >
> >       return to_net_dev(dev);
> >  }
> > -EXPORT_SYMBOL(of_find_net_device_by_node);
> > -#endif
> > +EXPORT_SYMBOL(fwnode_find_net_device_by_node);
Vladimir Oltean July 27, 2022, 4:38 p.m. UTC | #3
On Wed, Jul 27, 2022 at 05:18:16PM +0200, Marcin Wojtas wrote:
> Do you mean a situation analogous to what I addressed in:
> [net-next: PATCH v3 4/8] net: mvpp2: initialize port fwnode pointer
> ?

Not sure if "analogous" is the right word. My estimation is that the
overwhelmingly vast majority of DSA masters can be found by DSA simply
due to the SET_NETDEV_DEV() call that the Ethernet drivers need to make
anyway.  I see that mvpp2 also needed commit c4053ef32208 ("net: mvpp2:
initialize port of_node pointer"), but that isn't needed in general, and
I can't tell you exactly why it is needed there, I don't know enough
about the mvpp2 driver.

> I found indeed a couple of drivers that may require a similar change
> (e.g. dpaa2).

There I can tell you why the dpaa2-mac code mangles with net_dev->dev.of_node,
but I'd rather not go into an explanation that essentially doesn't matter.
The point is that you'd be mistaken to think that only the drivers which
touch the net device's ->dev->of_node are the ones that need updating
for your series to not cause regressions.

> IMO we have 2 options:
> - update these drivers
> - add some kind of fallback? If yes, I am wondering about an elegant
> solution - maybe add an extra check inside
> fwnode_find_parent_dev_match?
> 
> What would you suggest?

Fixing fwnode_find_parent_dev_match(), of course. This change broke DSA
on my LS1028A system (master in drivers/net/ethernet/freescale/enetc/)
and LS1021A (master in drivers/net/ethernet/freescale/gianfar.c).
Andy Shevchenko July 27, 2022, 5 p.m. UTC | #4
On Wed, Jul 27, 2022 at 5:24 PM Marcin Wojtas <mw@semihalf.com> wrote:
> śr., 27 lip 2022 o 16:31 Vladimir Oltean <olteanv@gmail.com> napisał(a):
> > On Wed, Jul 27, 2022 at 08:43:19AM +0200, Marcin Wojtas wrote:

...

> > > +     dev = class_find_device(&net_class, NULL, fwnode, fwnode_find_parent_dev_match);
> >
> > This needs to maintain compatibility with DSA masters that have
> > dev->of_node but don't have dev->fwnode populated.
>
> Do you mean a situation analogous to what I addressed in:
> [net-next: PATCH v3 4/8] net: mvpp2: initialize port fwnode pointer
> ?
>
> I found indeed a couple of drivers that may require a similar change
> (e.g. dpaa2).
>
> IMO we have 2 options:
> - update these drivers

Not Vladimir here, but my 2cents that update is best and elegant, it
can be done even before this series.
Marcin Wojtas July 27, 2022, 5:40 p.m. UTC | #5
śr., 27 lip 2022 o 18:38 Vladimir Oltean <olteanv@gmail.com> napisał(a):
>
> On Wed, Jul 27, 2022 at 05:18:16PM +0200, Marcin Wojtas wrote:
> > Do you mean a situation analogous to what I addressed in:
> > [net-next: PATCH v3 4/8] net: mvpp2: initialize port fwnode pointer
> > ?
>
> Not sure if "analogous" is the right word. My estimation is that the
> overwhelmingly vast majority of DSA masters can be found by DSA simply
> due to the SET_NETDEV_DEV() call that the Ethernet drivers need to make
> anyway.  I see that mvpp2 also needed commit c4053ef32208 ("net: mvpp2:
> initialize port of_node pointer"), but that isn't needed in general, and
> I can't tell you exactly why it is needed there, I don't know enough
> about the mvpp2 driver.

SET_NETDEV_DEV() fills net_device->dev.parent with &pdev->dev
and in most cases it is sufficient apparently it is sufficient for
fwnode_find_parent_dev_match (at least tests with mvneta case proves
it's fine).

We have some corner cases though:
* mvpp2 -> single controller can handle up to 3 net_devices and
therefore we need device_set_node() to make this work. I think dpaa2
is a similar case
* PCIE drivers with extra DT description (I think that's the case of enetc).

>
> > I found indeed a couple of drivers that may require a similar change
> > (e.g. dpaa2).
>
> There I can tell you why the dpaa2-mac code mangles with net_dev->dev.of_node,
> but I'd rather not go into an explanation that essentially doesn't matter.
> The point is that you'd be mistaken to think that only the drivers which
> touch the net device's ->dev->of_node are the ones that need updating
> for your series to not cause regressions.

As above - SET_NETDEV_DEV() should be fine in most cases, but we can
never be 100% sure untils it's verified.

>
> > IMO we have 2 options:
> > - update these drivers
> > - add some kind of fallback? If yes, I am wondering about an elegant
> > solution - maybe add an extra check inside
> > fwnode_find_parent_dev_match?
> >
> > What would you suggest?
>
> Fixing fwnode_find_parent_dev_match(), of course. This change broke DSA
> on my LS1028A system (master in drivers/net/ethernet/freescale/enetc/)
> and LS1021A (master in drivers/net/ethernet/freescale/gianfar.c).

Can you please check applying following diff:

--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -695,20 +695,22 @@ EXPORT_SYMBOL_GPL(fwnode_get_nth_parent);
  * The routine can be used e.g. as a callback for class_find_device().
  *
  * Returns: %1 - match is found
  *          %0 - match not found
  */
 int fwnode_find_parent_dev_match(struct device *dev, const void *data)
 {
        for (; dev; dev = dev->parent) {
                if (device_match_fwnode(dev, data))
                        return 1;
+               else if (device_match_of_node(dev, to_of_node(data))
+                       return 1;
        }

        return 0;
 }
 EXPORT_SYMBOL_GPL(fwnode_find_parent_dev_match);

Thanks for the review and test.
Marcin
Marcin Wojtas July 27, 2022, 5:41 p.m. UTC | #6
śr., 27 lip 2022 o 19:00 Andy Shevchenko <andy.shevchenko@gmail.com> napisał(a):
>
> On Wed, Jul 27, 2022 at 5:24 PM Marcin Wojtas <mw@semihalf.com> wrote:
> > śr., 27 lip 2022 o 16:31 Vladimir Oltean <olteanv@gmail.com> napisał(a):
> > > On Wed, Jul 27, 2022 at 08:43:19AM +0200, Marcin Wojtas wrote:
>
> ...
>
> > > > +     dev = class_find_device(&net_class, NULL, fwnode, fwnode_find_parent_dev_match);
> > >
> > > This needs to maintain compatibility with DSA masters that have
> > > dev->of_node but don't have dev->fwnode populated.
> >
> > Do you mean a situation analogous to what I addressed in:
> > [net-next: PATCH v3 4/8] net: mvpp2: initialize port fwnode pointer
> > ?
> >
> > I found indeed a couple of drivers that may require a similar change
> > (e.g. dpaa2).
> >
> > IMO we have 2 options:
> > - update these drivers
>
> Not Vladimir here, but my 2cents that update is best and elegant, it
> can be done even before this series.
>

In general I agree it's desired, but I'm not sure if we can catch all
cases just by reading code or rather base on regression reports
later...

Best regards,
Marcin
Vladimir Oltean July 27, 2022, 9:11 p.m. UTC | #7
On Wed, Jul 27, 2022 at 07:40:00PM +0200, Marcin Wojtas wrote:
> SET_NETDEV_DEV() fills net_device->dev.parent with &pdev->dev
> and in most cases it is sufficient apparently it is sufficient for
> fwnode_find_parent_dev_match (at least tests with mvneta case proves
> it's fine).

Indeed, mvneta works, which is a plain old platform device that hasn't
even been converted to fwnode, so why don't the others?

Well, as it turns out, it's one of the cases where I spoke to soon,
thinking I knew what was the problem why probing failed, before actually
debugging.

I thought there was no dmesg output from DSA at all, which would have
indicated an eternal -EPROBE_DEFER situation. But there's one tiny line
I had overlooked:

[    5.094013] mscc_felix 0000:00:00.5: error -EINVAL: Failed to register DSA switch

This comes from here:

static int dsa_port_parse_fw(struct dsa_port *dp, struct fwnode_handle *fwnode)
{
	struct fwnode_handle *ethernet = fwnode_find_reference(fwnode, "ethernet", 0);
	bool link = fwnode_property_present(fwnode, "link");
	const char *name = NULL;
	int ret;

	ret = fwnode_property_read_string(fwnode, "label", &name);
//	if (ret)
//		return ret;

	dp->fwnode = fwnode;

The 'label' property of a port was optional, you've made it mandatory by accident.
It is used only by DSA drivers that register using platform data.

(side note, I can't believe you actually have a 'label' property for the
CPU port and how many people are in the same situation as you; you know
it isn't used for anything, right? how do we stop the cargo cult?)

> Can you please check applying following diff:
> 
> --- a/drivers/base/property.c
> +++ b/drivers/base/property.c
> @@ -695,20 +695,22 @@ EXPORT_SYMBOL_GPL(fwnode_get_nth_parent);
>   * The routine can be used e.g. as a callback for class_find_device().
>   *
>   * Returns: %1 - match is found
>   *          %0 - match not found
>   */
>  int fwnode_find_parent_dev_match(struct device *dev, const void *data)
>  {
>         for (; dev; dev = dev->parent) {
>                 if (device_match_fwnode(dev, data))
>                         return 1;
> +               else if (device_match_of_node(dev, to_of_node(data))
> +                       return 1;
>         }
> 
>         return 0;
>  }
>  EXPORT_SYMBOL_GPL(fwnode_find_parent_dev_match);

So, nothing to do with device_match_fwnode() failing, that would have
been strange, come to think about it. Sorry for the noise here.

But looking at the deeper implementation of dev_fwnode() as:

struct fwnode_handle *dev_fwnode(struct device *dev)
{
	return IS_ENABLED(CONFIG_OF) && dev->of_node ?
		of_fwnode_handle(dev->of_node) : dev->fwnode;
}

I wonder, why did you have to modify mvpp2? It looks at dev->of_node
prior to returning dev->fwnode. It should work.
Vladimir Oltean July 27, 2022, 9:27 p.m. UTC | #8
On Thu, Jul 28, 2022 at 12:11:12AM +0300, Vladimir Oltean wrote:
> The 'label' property of a port was optional, you've made it mandatory by accident.
> It is used only by DSA drivers that register using platform data.

I didn't mean to say exactly this, the second phrase was an addition
through which I tried to make it clear that the "cpu" label *is* used,
but only by the drivers using platform data. With OF it's not, neither
that nor label = "dsa". We have other means of recognizing a CPU or DSA
port, by the 'ethernet' and/or 'dsa' phandles.

Additionally, the label is optional even for user port. One can have
udev rules that assign names to Ethernet ports. I think that is even
encouraged; some of the things in DSA predate the establishment of some
best practices.
Marcin Wojtas July 28, 2022, 6:47 a.m. UTC | #9
śr., 27 lip 2022 o 23:11 Vladimir Oltean <olteanv@gmail.com> napisał(a):
>
> On Wed, Jul 27, 2022 at 07:40:00PM +0200, Marcin Wojtas wrote:
> > SET_NETDEV_DEV() fills net_device->dev.parent with &pdev->dev
> > and in most cases it is sufficient apparently it is sufficient for
> > fwnode_find_parent_dev_match (at least tests with mvneta case proves
> > it's fine).
>
> Indeed, mvneta works, which is a plain old platform device that hasn't
> even been converted to fwnode, so why don't the others?
>
> Well, as it turns out, it's one of the cases where I spoke to soon,
> thinking I knew what was the problem why probing failed, before actually
> debugging.
>
> I thought there was no dmesg output from DSA at all, which would have
> indicated an eternal -EPROBE_DEFER situation. But there's one tiny line
> I had overlooked:
>
> [    5.094013] mscc_felix 0000:00:00.5: error -EINVAL: Failed to register DSA switch
>
> This comes from here:
>
> static int dsa_port_parse_fw(struct dsa_port *dp, struct fwnode_handle *fwnode)
> {
>         struct fwnode_handle *ethernet = fwnode_find_reference(fwnode, "ethernet", 0);
>         bool link = fwnode_property_present(fwnode, "link");
>         const char *name = NULL;
>         int ret;
>
>         ret = fwnode_property_read_string(fwnode, "label", &name);
> //      if (ret)
> //              return ret;
>
>         dp->fwnode = fwnode;
>
> The 'label' property of a port was optional, you've made it mandatory by accident.
> It is used only by DSA drivers that register using platform data.

Thanks for spotting that, I will make it optional again.

>
> (side note, I can't believe you actually have a 'label' property for the
> CPU port and how many people are in the same situation as you; you know
> it isn't used for anything, right? how do we stop the cargo cult?)
>

Well, given these results:
~/git/linux : git grep 'label = \"cpu\"' arch/arm/boot/dts/ | wc -l
79
~/git/linux : git grep 'label = \"cpu\"' arch/arm64/boot/dts/ | wc -l
14

It's not a surprise I also have it defined in the platforms I test. I
agree it doesn't serve any purpose in terms of creating the devices in
DSA with DT, but it IMO increases readability of the description at
least.

> > Can you please check applying following diff:
> >
> > --- a/drivers/base/property.c
> > +++ b/drivers/base/property.c
> > @@ -695,20 +695,22 @@ EXPORT_SYMBOL_GPL(fwnode_get_nth_parent);
> >   * The routine can be used e.g. as a callback for class_find_device().
> >   *
> >   * Returns: %1 - match is found
> >   *          %0 - match not found
> >   */
> >  int fwnode_find_parent_dev_match(struct device *dev, const void *data)
> >  {
> >         for (; dev; dev = dev->parent) {
> >                 if (device_match_fwnode(dev, data))
> >                         return 1;
> > +               else if (device_match_of_node(dev, to_of_node(data))
> > +                       return 1;
> >         }
> >
> >         return 0;
> >  }
> >  EXPORT_SYMBOL_GPL(fwnode_find_parent_dev_match);
>
> So, nothing to do with device_match_fwnode() failing, that would have
> been strange, come to think about it. Sorry for the noise here.
>

Great, thank you for confirmation.

> But looking at the deeper implementation of dev_fwnode() as:
>
> struct fwnode_handle *dev_fwnode(struct device *dev)
> {
>         return IS_ENABLED(CONFIG_OF) && dev->of_node ?
>                 of_fwnode_handle(dev->of_node) : dev->fwnode;
> }
>
> I wonder, why did you have to modify mvpp2? It looks at dev->of_node
> prior to returning dev->fwnode. It should work.

When I boot with ACPI, the dev->of_node becomes NULL. With DT it's fine as-is.

Best regards,
Marcin
Marcin Wojtas July 28, 2022, 6:52 a.m. UTC | #10
śr., 27 lip 2022 o 23:15 Andy Shevchenko <andy.shevchenko@gmail.com> napisał(a):
>
>
>
> On Wednesday, July 27, 2022, Marcin Wojtas <mw@semihalf.com> wrote:
>>
>> śr., 27 lip 2022 o 18:38 Vladimir Oltean <olteanv@gmail.com> napisał(a):
>> >
>> > On Wed, Jul 27, 2022 at 05:18:16PM +0200, Marcin Wojtas wrote:
>> > > Do you mean a situation analogous to what I addressed in:
>> > > [net-next: PATCH v3 4/8] net: mvpp2: initialize port fwnode pointer
>> > > ?
>> >
>> > Not sure if "analogous" is the right word. My estimation is that the
>> > overwhelmingly vast majority of DSA masters can be found by DSA simply
>> > due to the SET_NETDEV_DEV() call that the Ethernet drivers need to make
>> > anyway.  I see that mvpp2 also needed commit c4053ef32208 ("net: mvpp2:
>> > initialize port of_node pointer"), but that isn't needed in general, and
>> > I can't tell you exactly why it is needed there, I don't know enough
>> > about the mvpp2 driver.
>>
>> SET_NETDEV_DEV() fills net_device->dev.parent with &pdev->dev
>> and in most cases it is sufficient apparently it is sufficient for
>> fwnode_find_parent_dev_match (at least tests with mvneta case proves
>> it's fine).
>>
>> We have some corner cases though:
>> * mvpp2 -> single controller can handle up to 3 net_devices and
>> therefore we need device_set_node() to make this work. I think dpaa2
>> is a similar case
>> * PCIE drivers with extra DT description (I think that's the case of enetc).
>>
>> >
>> > > I found indeed a couple of drivers that may require a similar change
>> > > (e.g. dpaa2).
>> >
>> > There I can tell you why the dpaa2-mac code mangles with net_dev->dev.of_node,
>> > but I'd rather not go into an explanation that essentially doesn't matter.
>> > The point is that you'd be mistaken to think that only the drivers which
>> > touch the net device's ->dev->of_node are the ones that need updating
>> > for your series to not cause regressions.
>>
>> As above - SET_NETDEV_DEV() should be fine in most cases, but we can
>> never be 100% sure untils it's verified.
>>
>> >
>> > > IMO we have 2 options:
>> > > - update these drivers
>> > > - add some kind of fallback? If yes, I am wondering about an elegant
>> > > solution - maybe add an extra check inside
>> > > fwnode_find_parent_dev_match?
>> > >
>> > > What would you suggest?
>> >
>> > Fixing fwnode_find_parent_dev_match(), of course.
>
>
>
> Fixing how?!
>
>
>>
>>
>> This change broke DSA
>> > on my LS1028A system (master in drivers/net/ethernet/freescale/enetc/)
>> > and LS1021A (master in drivers/net/ethernet/freescale/gianfar.c).
>>
>> Can you please check applying following diff:
>>
>> --- a/drivers/base/property.c
>> +++ b/drivers/base/property.c
>> @@ -695,20 +695,22 @@ EXPORT_SYMBOL_GPL(fwnode_get_nth_parent);
>>   * The routine can be used e.g. as a callback for class_find_device().
>>   *
>>   * Returns: %1 - match is found
>>   *          %0 - match not found
>>   */
>>  int fwnode_find_parent_dev_match(struct device *dev, const void *data)
>>  {
>>         for (; dev; dev = dev->parent) {
>>                 if (device_match_fwnode(dev, data))
>>                         return 1;
>> +               else if (device_match_of_node(dev, to_of_node(data))
>> +                       return 1;
>>         }
>>
>
> This adds a piece of dead code. device_match_fwnode() covers this already.
>

Yes, indeed. After recent update, I think we can assume the current
implementation of fwnode_find_parent_dev_match should work fine with
all existing cases.

Thank you for all remarks and comments, I'll address them in v4 later today.

Best regards,
Marcin
Vladimir Oltean July 28, 2022, 9:16 a.m. UTC | #11
On Thu, Jul 28, 2022 at 08:52:04AM +0200, Marcin Wojtas wrote:
> Yes, indeed. After recent update, I think we can assume the current
> implementation of fwnode_find_parent_dev_match should work fine with
> all existing cases.

What you should really be fixing is the commit message of patch 4,
that's what threw me off:

| As a preparation to switch the DSA subsystem from using
| of_find_net_device_by_node() to its more generic fwnode_
| equivalent, the port's device structure should be updated
| with its fwnode pointer, similarly to of_node - see analogous
| commit c4053ef32208 ("net: mvpp2: initialize port of_node pointer").
| 
| This patch is required to prevent a regression before updating
| the DSA API on boards that connect the mvpp2 port to switch,
| such as Clearfog GT-8K or CN913x CEx7 Evaluation Board.

There's no regression to speak of. DSA didn't work with ACPI before, and
fwnode_find_net_device_by_node() still works with the plain dev->of_node
assignment.
Marcin Wojtas July 28, 2022, 4:56 p.m. UTC | #12
czw., 28 lip 2022 o 11:16 Vladimir Oltean <olteanv@gmail.com> napisał(a):
>
> On Thu, Jul 28, 2022 at 08:52:04AM +0200, Marcin Wojtas wrote:
> > Yes, indeed. After recent update, I think we can assume the current
> > implementation of fwnode_find_parent_dev_match should work fine with
> > all existing cases.
>
> What you should really be fixing is the commit message of patch 4,
> that's what threw me off:
>
> | As a preparation to switch the DSA subsystem from using
> | of_find_net_device_by_node() to its more generic fwnode_
> | equivalent, the port's device structure should be updated
> | with its fwnode pointer, similarly to of_node - see analogous
> | commit c4053ef32208 ("net: mvpp2: initialize port of_node pointer").
> |
> | This patch is required to prevent a regression before updating
> | the DSA API on boards that connect the mvpp2 port to switch,
> | such as Clearfog GT-8K or CN913x CEx7 Evaluation Board.
>
> There's no regression to speak of. DSA didn't work with ACPI before, and
> fwnode_find_net_device_by_node() still works with the plain dev->of_node
> assignment.

There was a regression even for OF in v1, but after switching to
device_match_fwnode() it works indeed. Anyway patch v4 is imo useful,
I'll only reword the commit message.

Thanks,
Marcin
Vladimir Oltean July 28, 2022, 7:16 p.m. UTC | #13
On Thu, Jul 28, 2022 at 06:56:48PM +0200, Marcin Wojtas wrote:
> There was a regression even for OF in v1, but after switching to
> device_match_fwnode() it works indeed. Anyway patch v4 is imo useful,
> I'll only reword the commit message.

Do you mean patch 4 or patch v4? If patch 4, of course it's useful, but
not for avoiding a regression with OF (case in which I drop all my claims
made earlier about fw_find_net_device_by_node), but rather to actually
get something working with actual ACPI (although perhaps not in this
series, you'll need to add ACPI IDs in the mv88e6xxx driver some time
later as well, maybe you could focus this series just on converting DSA
to play nice with fwnodes). If you're already thinking about the v4 of
this patch set, I'll respond to that in a separate email shortly.
Marcin Wojtas July 28, 2022, 7:49 p.m. UTC | #14
czw., 28 lip 2022 o 21:16 Vladimir Oltean <olteanv@gmail.com> napisał(a):
>
> On Thu, Jul 28, 2022 at 06:56:48PM +0200, Marcin Wojtas wrote:
> > There was a regression even for OF in v1, but after switching to
> > device_match_fwnode() it works indeed. Anyway patch v4 is imo useful,
> > I'll only reword the commit message.
>
> Do you mean patch 4 or patch v4? If patch 4, of course it's useful, but

Patch 4/8 in v4 :) I'm working on it right now to submit asap.

> not for avoiding a regression with OF (case in which I drop all my claims
> made earlier about fw_find_net_device_by_node), but rather to actually

Change in the mvpp2 driver:
-       dev->dev.of_node = port_node;
+       device_set_node(&dev->dev, port_fwnode);
is desired and correct anyway, so as a low-cost change I think it can
be included in this series (which is in fact preparation-to-ACPI
support). I will update the commit message. accordingly.

> get something working with actual ACPI (although perhaps not in this
> series, you'll need to add ACPI IDs in the mv88e6xxx driver some time

v1 added all of this, but we agreed that ACPI-specific bits should be
sent separately later, after extending the ACPI Specification.

> later as well, maybe you could focus this series just on converting DSA
> to play nice with fwnodes). If you're already thinking about the v4 of
> this patch set, I'll respond to that in a separate email shortly.
Vladimir Oltean July 28, 2022, 7:56 p.m. UTC | #15
On Thu, Jul 28, 2022 at 08:47:58AM +0200, Marcin Wojtas wrote:
> > The 'label' property of a port was optional, you've made it mandatory by accident.
> > It is used only by DSA drivers that register using platform data.
> 
> Thanks for spotting that, I will make it optional again.
> 
> > (side note, I can't believe you actually have a 'label' property for the
> > CPU port and how many people are in the same situation as you; you know
> > it isn't used for anything, right? how do we stop the cargo cult?)
> 
> Well, given these results:
> ~/git/linux : git grep 'label = \"cpu\"' arch/arm/boot/dts/ | wc -l
> 79
> ~/git/linux : git grep 'label = \"cpu\"' arch/arm64/boot/dts/ | wc -l
> 14
> 
> It's not a surprise I also have it defined in the platforms I test. I
> agree it doesn't serve any purpose in terms of creating the devices in
> DSA with DT, but it IMO increases readability of the description at
> least.

We've glided over this way too easily, so I'll repeat this thing I've said:

| One can have udev rules that assign names to Ethernet ports. I think
| that is even encouraged; some of the things in DSA predate the
| establishment of some best practices.

I know I'm not exactly "upfront" by saying this at v3 rather than earlier,
but I haven't had the time and I still don't have as much as I'd like.
Sorry for that.

Please don't jump to sending v4 just yet, and please don't expect that
this patch set will make it for the upcoming 5.20 release candidates.

ACPI is a whole new world and I don't think we want to mass-migrate each
and every OF binding that DSA has to the generic fwnode form, at least
not without having a serious discussion about it.

The 'label' thing is actually one of the things that I'm seriously
considering skipping parsing if this is an ACPI system, simply because
best practices are different today than they were when the OF bindings
were created.

There's also the change that validates that phylink has the fwnode
properties it needs to work properly:
https://patchwork.kernel.org/project/netdevbpf/patch/20220723164635.1621911-1-vladimir.oltean@nxp.com/

Please don't even think that the DSA fwnode conversion will be merged
before the validation patch (sorry, I'm not saying this to block you,
I'm saying this because I don't want DSA to start with zero-day baggage
on ACPI).

And even when the validation patch gets merged, you'll need to adapt it
to fwnode because that's what will be required syntactically, but we'll
only go through the motions of calling of_device_compatible_match() for
the OF case. With ACPI, every driver will opt into strict validation,
that's non negotiable.

And then there are some other issues we've learned about, with the DT
bindings that specific drivers such as mv88e6xxx and realtek-smi have.
I'll give you more details once we get to the actual mv88e6xxx
conversion to ACPI; currently my memory lacks some of the precise
details of how come mv88e6xxx came to not observe the issue but
realtek-smi did. Anyway, the issue was that fw_devlink causes the
internal PHYs to probe with the generic rather than the specific PHY
driver, if interrupts are being used (and provided by the switch as
'interrupt-controller').

It can be debated what exactly is at fault there, although one
interpretation can be that the DT bindings themselves are to blame,
for describing a circular dependency between a parent and a child.
I've been suggesting the authors of new drivers to take an alternative
approach and describe the switch chip as a MFD, with only the actual
switching component being probed by DSA and the rest being separate
drivers:
https://lore.kernel.org/all/20211204022037.dkipkk42qet4u7go@skbuf/T/

You'll say, ok but don't we have to keep maintaining mv8e6xxx OF bindings
functional with fw_devlink too anyway, so what benefit would there be if
for ACPI we'd split the exact same monolithic driver into a MFD?
And maybe you have a point, I don't know, I haven't actually tried to
look at the code and see if it could be restructured cleanly to probe
and work in both cases.

The bottom line is that if you haven't received too much review for your
series until now, I suspect it's because none of the DSA maintainers
cropped a large enough chunk of time yet to actually clarify things for
themselves. I don't consider the things I've pointed out here to be a
'review' in the proper sense, they're just cases I'm thinking about in
the back of my mind where we should learn from past mistakes.
I'll revisit when I will have come to some conclusions.
Andrew Lunn July 28, 2022, 8:18 p.m. UTC | #16
> The 'label' thing is actually one of the things that I'm seriously
> considering skipping parsing if this is an ACPI system, simply because
> best practices are different today than they were when the OF bindings
> were created.

Agreed. We want the ACPI binding to learn from what has worked and not
worked in DT. We should clean up some of the historical mess. And
enforce things we don't in DT simply because there is too much
history.

So a straight one to one conversion is not going to happen.

> It can be debated what exactly is at fault there, although one
> interpretation can be that the DT bindings themselves are to blame,
> for describing a circular dependency between a parent and a child.

DT describes hardware. I'm not sure hardware can have a circular
dependency. It is more about how software make use of that hardware
description that ends up in circular dependencies.

	    Andrew
Marcin Wojtas July 28, 2022, 9:23 p.m. UTC | #17
czw., 28 lip 2022 o 22:18 Andrew Lunn <andrew@lunn.ch> napisał(a):
>
> > The 'label' thing is actually one of the things that I'm seriously
> > considering skipping parsing if this is an ACPI system, simply because
> > best practices are different today than they were when the OF bindings
> > were created.
>
> Agreed. We want the ACPI binding to learn from what has worked and not
> worked in DT. We should clean up some of the historical mess. And
> enforce things we don't in DT simply because there is too much
> history.
>
> So a straight one to one conversion is not going to happen.

I understand your standpoint - there is a long history, possible
clean-ups, backward compatibility considerations, etc. that should not
be zero-day baggage of ACPI. Otoh, we don't need to be worried about
the ACPI binding too much now - as agreed it was removed from this
series, beginning from v2. IMO it may be better to return to that once
the ACPI Spec is updated with the MDIOSerialBus and the patches are
resubmitted on whatever shape of the DSA subsystem is established
within the next weeks/months from now.

In v1 we discussed also the resubmission of the non-ACPI-related
patches, which would pave the way to dropping the explicit OF_
dependency in the DSA and moving to a generic hardware description
kernel API - without any functional change. Modifying DT bindings and
clean-ups could be done on top this patchset as well. Of course, it is
the subsystems' Maintainers call and I'll adjust accordingly - if you
wish me to wait and rebase after the 'validation patch' lands in
net-next, I'll do that.

A side note: I was of course aware that making it for the v5.20 would
be extremely hard, but I decided to give it a try anyway - I had to
wait for some time, as this series was gated by fate of the eventually
abandoned phylink-related changes.

Thanks,
Marcin
Andrew Lunn July 28, 2022, 10:20 p.m. UTC | #18
On Thu, Jul 28, 2022 at 11:23:31PM +0200, Marcin Wojtas wrote:
> czw., 28 lip 2022 o 22:18 Andrew Lunn <andrew@lunn.ch> napisał(a):
> >
> > > The 'label' thing is actually one of the things that I'm seriously
> > > considering skipping parsing if this is an ACPI system, simply because
> > > best practices are different today than they were when the OF bindings
> > > were created.
> >
> > Agreed. We want the ACPI binding to learn from what has worked and not
> > worked in DT. We should clean up some of the historical mess. And
> > enforce things we don't in DT simply because there is too much
> > history.
> >
> > So a straight one to one conversion is not going to happen.
> 
> I understand your standpoint - there is a long history, possible
> clean-ups, backward compatibility considerations, etc. that should not
> be zero-day baggage of ACPI. Otoh, we don't need to be worried about
> the ACPI binding too much now - as agreed it was removed from this
> series, beginning from v2. IMO it may be better to return to that once
> the ACPI Spec is updated with the MDIOSerialBus and the patches are
> resubmitted on whatever shape of the DSA subsystem is established
> within the next weeks/months from now.
> 
> In v1 we discussed also the resubmission of the non-ACPI-related
> patches, which would pave the way to dropping the explicit OF_
> dependency in the DSA and moving to a generic hardware description
> kernel API - without any functional change.

Ideally, we want to keep all the ugly DT stuff in DT. We want to
ensure that any "generic hardware description kernel API" does not
inherit all the ugly DT stuff.

ACPI and DT are different things, so i don't see why they need to
share code.

      Andrew
Andy Shevchenko July 29, 2022, 9:59 a.m. UTC | #19
On Fri, Jul 29, 2022 at 12:29 AM Andrew Lunn <andrew@lunn.ch> wrote:
> On Thu, Jul 28, 2022 at 11:23:31PM +0200, Marcin Wojtas wrote:

...

> ACPI and DT are different things, so i don't see why they need to
> share code.

Yes and no.

ACPI _DSD extension allows us to share a lot of code when it comes to
specific device properties (that are not standardized anyhow by ACPI
specification, and for the record many of them even may not, but some
are, like MIPI camera). Maybe you want to have something like a
property standard for DSA that can be published as MIPI or so and then
that part of the code of course may very well be shared. Discussed
MDIOSerialBus() resource type is pure ACPI thingy if going to be
standardized and indeed, that part can't be shared.

Entire exercise with fwnodes allows to make drivers (most of or most
of the parts of) to be shared between different resource providers.
And this is a cool part about it.
diff mbox series

Patch

diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index 92b10e67d5f8..a335775af244 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -35,6 +35,7 @@  int nvmem_get_mac_address(struct device *dev, void *addrbuf);
 int device_get_mac_address(struct device *dev, char *addr);
 int device_get_ethdev_address(struct device *dev, struct net_device *netdev);
 int fwnode_get_mac_address(struct fwnode_handle *fwnode, char *addr);
+struct net_device *fwnode_find_net_device_by_node(struct fwnode_handle *fwnode);
 
 u32 eth_get_headlen(const struct net_device *dev, const void *data, u32 len);
 __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev);
diff --git a/include/linux/of_net.h b/include/linux/of_net.h
index 0484b613ca64..f672f831292d 100644
--- a/include/linux/of_net.h
+++ b/include/linux/of_net.h
@@ -15,7 +15,6 @@  struct net_device;
 extern int of_get_phy_mode(struct device_node *np, phy_interface_t *interface);
 extern int of_get_mac_address(struct device_node *np, u8 *mac);
 int of_get_ethdev_address(struct device_node *np, struct net_device *dev);
-extern struct net_device *of_find_net_device_by_node(struct device_node *np);
 #else
 static inline int of_get_phy_mode(struct device_node *np,
 				  phy_interface_t *interface)
@@ -32,11 +31,6 @@  static inline int of_get_ethdev_address(struct device_node *np, struct net_devic
 {
 	return -ENODEV;
 }
-
-static inline struct net_device *of_find_net_device_by_node(struct device_node *np)
-{
-	return NULL;
-}
 #endif
 
 #endif /* __LINUX_OF_NET_H */
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index d61afd21aab5..fc972545aaea 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -6,6 +6,7 @@ 
  */
 
 #include <linux/capability.h>
+#include <linux/etherdevice.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
 #include <linux/if_arp.h>
@@ -1935,38 +1936,26 @@  static struct class net_class __ro_after_init = {
 	.get_ownership = net_get_ownership,
 };
 
-#ifdef CONFIG_OF
-static int of_dev_node_match(struct device *dev, const void *data)
-{
-	for (; dev; dev = dev->parent) {
-		if (dev->of_node == data)
-			return 1;
-	}
-
-	return 0;
-}
-
 /*
- * of_find_net_device_by_node - lookup the net device for the device node
- * @np: OF device node
+ * fwnode_find_net_device_by_node - lookup the net device for the device fwnode
+ * @fwnode: firmware node
  *
- * Looks up the net_device structure corresponding with the device node.
+ * Looks up the net_device structure corresponding with the fwnode.
  * If successful, returns a pointer to the net_device with the embedded
  * struct device refcount incremented by one, or NULL on failure. The
  * refcount must be dropped when done with the net_device.
  */
-struct net_device *of_find_net_device_by_node(struct device_node *np)
+struct net_device *fwnode_find_net_device_by_node(struct fwnode_handle *fwnode)
 {
 	struct device *dev;
 
-	dev = class_find_device(&net_class, NULL, np, of_dev_node_match);
+	dev = class_find_device(&net_class, NULL, fwnode, fwnode_find_parent_dev_match);
 	if (!dev)
 		return NULL;
 
 	return to_net_dev(dev);
 }
-EXPORT_SYMBOL(of_find_net_device_by_node);
-#endif
+EXPORT_SYMBOL(fwnode_find_net_device_by_node);
 
 /* Delete sysfs entries but hold kobject reference until after all
  * netdev references are gone.
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 82fb3b009fb4..bba416eba9c2 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -7,6 +7,7 @@ 
  */
 
 #include <linux/device.h>
+#include <linux/etherdevice.h>
 #include <linux/err.h>
 #include <linux/list.h>
 #include <linux/netdevice.h>
@@ -1498,7 +1499,7 @@  static int dsa_port_parse_fw(struct dsa_port *dp, struct fwnode_handle *fwnode)
 		struct net_device *master;
 		const char *user_protocol;
 
-		master = of_find_net_device_by_node(to_of_node(ethernet));
+		master = fwnode_find_net_device_by_node(ethernet);
 		fwnode_handle_put(ethernet);
 		if (!master)
 			return -EPROBE_DEFER;