diff mbox series

[net-next,05/10] net: dsa: qca8k: skip MDIO bus creation if its OF node has status = "disabled"

Message ID 20240104140037.374166-6-vladimir.oltean@nxp.com (mailing list archive)
State Accepted
Commit e66bf63a7f670a600338faf889bed71f90c183bf
Delegated to: Netdev Maintainers
Headers show
Series ds->user_mii_bus cleanup (part 1) | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 1113 this patch: 1113
netdev/cc_maintainers success CCed 8 of 8 maintainers
netdev/build_clang success Errors and warnings before: 1140 this patch: 1140
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 1140 this patch: 1140
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 28 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Vladimir Oltean Jan. 4, 2024, 2 p.m. UTC
Currently the driver calls the non-OF devm_mdiobus_register() rather
than devm_of_mdiobus_register() for this case, but it seems to rather
be a confusing coincidence, and not a real use case that needs to be
supported.

If the device tree says status = "disabled" for the MDIO bus, we
shouldn't need an MDIO bus at all. Instead, just exit as early as
possible and do not call any MDIO API.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/dsa/qca/qca8k-8xxx.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

Comments

Alvin Šipraga Jan. 4, 2024, 3:44 p.m. UTC | #1
On Thu, Jan 04, 2024 at 04:00:32PM +0200, Vladimir Oltean wrote:
> Currently the driver calls the non-OF devm_mdiobus_register() rather
> than devm_of_mdiobus_register() for this case, but it seems to rather
> be a confusing coincidence, and not a real use case that needs to be
> supported.

I am not really sure about the use case, but I always thought that
status = "disabled" sort of functions the same as if the node were
simply never specified. But with your change, there is a behavioural
difference between these two cases:

  (a) mdio unspecified => register "qca8k-legacy user mii"
  (b) mdio specified, but status = "disabled" => don't register anything

Was this your intention?

> 
> If the device tree says status = "disabled" for the MDIO bus, we
> shouldn't need an MDIO bus at all. Instead, just exit as early as
> possible and do not call any MDIO API.
> 
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> ---
>  drivers/net/dsa/qca/qca8k-8xxx.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c
> index 5f47a290bd6e..21e36bc3c015 100644
> --- a/drivers/net/dsa/qca/qca8k-8xxx.c
> +++ b/drivers/net/dsa/qca/qca8k-8xxx.c
> @@ -949,9 +949,11 @@ qca8k_mdio_register(struct qca8k_priv *priv)
>  	struct dsa_switch *ds = priv->ds;
>  	struct device_node *mdio;
>  	struct mii_bus *bus;
> -	int err;
> +	int err = 0;
>  
>  	mdio = of_get_child_by_name(priv->dev->of_node, "mdio");
> +	if (mdio && !of_device_is_available(mdio))
> +		goto out;
>  
>  	bus = devm_mdiobus_alloc(ds->dev);
>  	if (!bus) {
> @@ -967,7 +969,7 @@ qca8k_mdio_register(struct qca8k_priv *priv)
>  	ds->user_mii_bus = bus;
>  
>  	/* Check if the devicetree declare the port:phy mapping */
> -	if (of_device_is_available(mdio)) {
> +	if (mdio) {
>  		bus->name = "qca8k user mii";
>  		bus->read = qca8k_internal_mdio_read;
>  		bus->write = qca8k_internal_mdio_write;
> @@ -986,7 +988,7 @@ qca8k_mdio_register(struct qca8k_priv *priv)
>  
>  out_put_node:
>  	of_node_put(mdio);
> -
> +out:
>  	return err;
>  }
>  
> -- 
> 2.34.1
>
Vladimir Oltean Jan. 4, 2024, 3:49 p.m. UTC | #2
On Thu, Jan 04, 2024 at 03:44:48PM +0000, Alvin Šipraga wrote:
> On Thu, Jan 04, 2024 at 04:00:32PM +0200, Vladimir Oltean wrote:
> > Currently the driver calls the non-OF devm_mdiobus_register() rather
> > than devm_of_mdiobus_register() for this case, but it seems to rather
> > be a confusing coincidence, and not a real use case that needs to be
> > supported.
> 
> I am not really sure about the use case, but I always thought that
> status = "disabled" sort of functions the same as if the node were
> simply never specified. But with your change, there is a behavioural
> difference between these two cases:
> 
>   (a) mdio unspecified => register "qca8k-legacy user mii"
>   (b) mdio specified, but status = "disabled" => don't register anything
> 
> Was this your intention?

Yeah, it was my intention. I'm not sure if I agree with your equivalence.
For example, PCI devices probe through enumeration. Their OF node is
optional, aka when absent, they still probe. But when an associated OF
node exists and has status = "disabled", they don't probe.
Alvin Šipraga Jan. 4, 2024, 4:04 p.m. UTC | #3
On Thu, Jan 04, 2024 at 05:49:27PM +0200, Vladimir Oltean wrote:
> On Thu, Jan 04, 2024 at 03:44:48PM +0000, Alvin Šipraga wrote:
> > On Thu, Jan 04, 2024 at 04:00:32PM +0200, Vladimir Oltean wrote:
> > > Currently the driver calls the non-OF devm_mdiobus_register() rather
> > > than devm_of_mdiobus_register() for this case, but it seems to rather
> > > be a confusing coincidence, and not a real use case that needs to be
> > > supported.
> > 
> > I am not really sure about the use case, but I always thought that
> > status = "disabled" sort of functions the same as if the node were
> > simply never specified. But with your change, there is a behavioural
> > difference between these two cases:
> > 
> >   (a) mdio unspecified => register "qca8k-legacy user mii"
> >   (b) mdio specified, but status = "disabled" => don't register anything
> > 
> > Was this your intention?
> 
> Yeah, it was my intention. I'm not sure if I agree with your equivalence.
> For example, PCI devices probe through enumeration. Their OF node is
> optional, aka when absent, they still probe. But when an associated OF
> node exists and has status = "disabled", they don't probe.

Yes, good example with PCIe. The change makes sense then. Thanks for clarifying.
Alvin Šipraga Jan. 4, 2024, 4:05 p.m. UTC | #4
On Thu, Jan 04, 2024 at 04:00:32PM +0200, Vladimir Oltean wrote:
> Currently the driver calls the non-OF devm_mdiobus_register() rather
> than devm_of_mdiobus_register() for this case, but it seems to rather
> be a confusing coincidence, and not a real use case that needs to be
> supported.
> 
> If the device tree says status = "disabled" for the MDIO bus, we
> shouldn't need an MDIO bus at all. Instead, just exit as early as
> possible and do not call any MDIO API.
> 
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>

Reviewed-by: Alvin Šipraga <alsi@bang-olufsen.dk>

> ---
>  drivers/net/dsa/qca/qca8k-8xxx.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
Florian Fainelli Jan. 4, 2024, 5:38 p.m. UTC | #5
On 1/4/24 06:00, Vladimir Oltean wrote:
> Currently the driver calls the non-OF devm_mdiobus_register() rather
> than devm_of_mdiobus_register() for this case, but it seems to rather
> be a confusing coincidence, and not a real use case that needs to be
> supported.
> 
> If the device tree says status = "disabled" for the MDIO bus, we
> shouldn't need an MDIO bus at all. Instead, just exit as early as
> possible and do not call any MDIO API.
> 
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>

Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Luiz Angelo Daros de Luca Jan. 5, 2024, 2:19 a.m. UTC | #6
Em qui., 4 de jan. de 2024 às 11:01, Vladimir Oltean
<vladimir.oltean@nxp.com> escreveu:
>
> Currently the driver calls the non-OF devm_mdiobus_register() rather
> than devm_of_mdiobus_register() for this case, but it seems to rather
> be a confusing coincidence, and not a real use case that needs to be
> supported.
>
> If the device tree says status = "disabled" for the MDIO bus, we
> shouldn't need an MDIO bus at all. Instead, just exit as early as
> possible and do not call any MDIO API.
>
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> ---
>  drivers/net/dsa/qca/qca8k-8xxx.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c
> index 5f47a290bd6e..21e36bc3c015 100644
> --- a/drivers/net/dsa/qca/qca8k-8xxx.c
> +++ b/drivers/net/dsa/qca/qca8k-8xxx.c
> @@ -949,9 +949,11 @@ qca8k_mdio_register(struct qca8k_priv *priv)
>         struct dsa_switch *ds = priv->ds;
>         struct device_node *mdio;
>         struct mii_bus *bus;
> -       int err;
> +       int err = 0;
>
>         mdio = of_get_child_by_name(priv->dev->of_node, "mdio");
> +       if (mdio && !of_device_is_available(mdio))
> +               goto out;

Hum.. that's why you moved this call here in the previous patch.

Don't you still need to put the node that is not available? Just put
it unconditionally whenever you exit this function after you get it.
of_node_put() can handle even NULL.

I'm not sure if this and other simple switches can be useful without a
valid MDIO. Anyway, wouldn't it be equivalent to having an empty mdio
node? It looks like it would work as well but without a specific code
path.

>         bus = devm_mdiobus_alloc(ds->dev);
>         if (!bus) {
> @@ -967,7 +969,7 @@ qca8k_mdio_register(struct qca8k_priv *priv)
>         ds->user_mii_bus = bus;
>
>         /* Check if the devicetree declare the port:phy mapping */
> -       if (of_device_is_available(mdio)) {
> +       if (mdio) {
>                 bus->name = "qca8k user mii";
>                 bus->read = qca8k_internal_mdio_read;
>                 bus->write = qca8k_internal_mdio_write;
> @@ -986,7 +988,7 @@ qca8k_mdio_register(struct qca8k_priv *priv)
>
>  out_put_node:
>         of_node_put(mdio);
> -
> +out:
>         return err;
>  }
>
> --
> 2.34.1
>
Vladimir Oltean Jan. 10, 2024, 4:35 p.m. UTC | #7
On Thu, Jan 04, 2024 at 11:19:20PM -0300, Luiz Angelo Daros de Luca wrote:
> Don't you still need to put the node that is not available? Just put
> it unconditionally whenever you exit this function after you get it.
> of_node_put() can handle even NULL.

You're right. I've prepared a patch to handle this case correctly.
I don't think it's worth sending to 'net' now that 'net-next' has
closed, because as you say below, it's quite possible that the
!of_device_is_available() code path is never exercised by existing
device trees. So the bug is like the tree that falls in the forest but
nobody hears it. I will submit the correction when net-next reopens,
together with Alvin's suggested "err" -> "ret" renaming.

> I'm not sure if this and other simple switches can be useful without a
> valid MDIO.

Will that always be the case? As implausible as this may sound, I've
received DSA questions from people using the sja1105 as a two-port
adapter between MII on the CPU side and RMII on the PHY side. It was the
cheapest way of adapting their SoC to RMII, using a switch as not even a
port multiplier. I see that AR8237 has 1x RGMII and 1x SerDes, so maybe
somebody would want to use it that way, and sidestep the internal PHYs?
I don't know.

> Anyway, wouldn't it be equivalent to having an empty mdio
> node? It looks like it would work as well but without a specific code
> path.

I guess you could also express this that way too. Although, in case it
matters, an 'empty node' has to pass schema validation (has to have all
required properties), and a disabled one doesn't.

The idea with this patch was to deliberately change the status = "disabled"
handling that the driver already had, to make things more consistent
across the board. Each driver binding has its own unique interpretation
of an absent MDIO OF node already. Some consider the OF node optional
and thus register it anyway, some say that absent means it's not needed.
But I think status = "disabled" should be an unambiguous way to specify
through DT that the hardware component is disabled. This is not how
qca8k was interpreting it prior to this change.
diff mbox series

Patch

diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c
index 5f47a290bd6e..21e36bc3c015 100644
--- a/drivers/net/dsa/qca/qca8k-8xxx.c
+++ b/drivers/net/dsa/qca/qca8k-8xxx.c
@@ -949,9 +949,11 @@  qca8k_mdio_register(struct qca8k_priv *priv)
 	struct dsa_switch *ds = priv->ds;
 	struct device_node *mdio;
 	struct mii_bus *bus;
-	int err;
+	int err = 0;
 
 	mdio = of_get_child_by_name(priv->dev->of_node, "mdio");
+	if (mdio && !of_device_is_available(mdio))
+		goto out;
 
 	bus = devm_mdiobus_alloc(ds->dev);
 	if (!bus) {
@@ -967,7 +969,7 @@  qca8k_mdio_register(struct qca8k_priv *priv)
 	ds->user_mii_bus = bus;
 
 	/* Check if the devicetree declare the port:phy mapping */
-	if (of_device_is_available(mdio)) {
+	if (mdio) {
 		bus->name = "qca8k user mii";
 		bus->read = qca8k_internal_mdio_read;
 		bus->write = qca8k_internal_mdio_write;
@@ -986,7 +988,7 @@  qca8k_mdio_register(struct qca8k_priv *priv)
 
 out_put_node:
 	of_node_put(mdio);
-
+out:
 	return err;
 }