diff mbox series

[net] net: mdio-mux: fix C45 access returning -EIO after API change

Message ID 20231017113222.3135895-1-vladimir.oltean@nxp.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series [net] net: mdio-mux: fix C45 access returning -EIO after API change | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for net
netdev/fixes_present success Fixes tag present in non-next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 1362 this patch: 1362
netdev/cc_maintainers success CCed 10 of 10 maintainers
netdev/build_clang success Errors and warnings before: 1386 this patch: 1386
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 Fixes tag looks correct
netdev/build_allmodconfig_warn success Errors and warnings before: 1386 this patch: 1386
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 63 lines checked
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Vladimir Oltean Oct. 17, 2023, 11:32 a.m. UTC
The mii_bus API conversion to read_c45() and write_c45() did not cover
the mdio-mux driver before read() and write() were made C22-only.

This broke arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-13bb.dtso.
The -EOPNOTSUPP from mdiobus_c45_read() is transformed by
get_phy_c45_devs_in_pkg() into -EIO, is further propagated to
of_mdiobus_register() and this makes the mdio-mux driver fail to probe
the entire child buses, not just the PHYs that cause access errors.

Fix the regression by introducing special c45 read and write accessors
to mdio-mux which forward the operation to the parent MDIO bus.

Fixes: db1a63aed89c ("net: phy: Remove fallback to old C45 method")
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/mdio/mdio-mux.c | 45 +++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

Comments

Russell King (Oracle) Oct. 17, 2023, 1:31 p.m. UTC | #1
On Tue, Oct 17, 2023 at 02:32:22PM +0300, Vladimir Oltean wrote:
> The mii_bus API conversion to read_c45() and write_c45() did not cover
> the mdio-mux driver before read() and write() were made C22-only.
> 
> This broke arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-13bb.dtso.
> The -EOPNOTSUPP from mdiobus_c45_read() is transformed by
> get_phy_c45_devs_in_pkg() into -EIO, is further propagated to
> of_mdiobus_register() and this makes the mdio-mux driver fail to probe
> the entire child buses, not just the PHYs that cause access errors.
> 
> Fix the regression by introducing special c45 read and write accessors
> to mdio-mux which forward the operation to the parent MDIO bus.
> 
> Fixes: db1a63aed89c ("net: phy: Remove fallback to old C45 method")
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> ---
>  drivers/net/mdio/mdio-mux.c | 45 +++++++++++++++++++++++++++++++++++++
>  1 file changed, 45 insertions(+)
> 
> diff --git a/drivers/net/mdio/mdio-mux.c b/drivers/net/mdio/mdio-mux.c
> index a881e3523328..7d322c08c1e9 100644
> --- a/drivers/net/mdio/mdio-mux.c
> +++ b/drivers/net/mdio/mdio-mux.c
> @@ -55,6 +55,27 @@ static int mdio_mux_read(struct mii_bus *bus, int phy_id, int regnum)
>  	return r;
>  }
>  
> +static int mdio_mux_read_c45(struct mii_bus *bus, int phy_id, int dev_addr,
> +			     int regnum)
> +{
> +	struct mdio_mux_child_bus *cb = bus->priv;
> +	struct mdio_mux_parent_bus *pb = cb->parent;
> +	int r;
> +
> +	mutex_lock_nested(&pb->mii_bus->mdio_lock, MDIO_MUTEX_MUX);
> +	r = pb->switch_fn(pb->current_child, cb->bus_number, pb->switch_data);
> +	if (r)
> +		goto out;
> +
> +	pb->current_child = cb->bus_number;
> +
> +	r = pb->mii_bus->read_c45(pb->mii_bus, phy_id, dev_addr, regnum);

What if the parent bus doesn't have read_c45 or write_c45 ?

> @@ -173,6 +216,8 @@ int mdio_mux_init(struct device *dev,
>  		cb->mii_bus->parent = dev;
>  		cb->mii_bus->read = mdio_mux_read;
>  		cb->mii_bus->write = mdio_mux_write;
> +		cb->mii_bus->read_c45 = mdio_mux_read_c45;
> +		cb->mii_bus->write_c45 = mdio_mux_write_c45;

Maybe make these conditional on the parent bus implementing the c45
read/write ops?
Andrew Lunn Oct. 17, 2023, 1:44 p.m. UTC | #2
> Maybe make these conditional on the parent bus implementing the c45
> read/write ops?

And optionally, for net-next, make the c22 read/write ops conditional
on the parent bus having C22 as well. Its a bit of a corner case, but
there are a couple of MDIO bus masters which are C45 only.

Not having C45 is however very common, so we should make this
conditional as part of the fix.

      Andrew
Vladimir Oltean Oct. 17, 2023, 1:57 p.m. UTC | #3
On Tue, Oct 17, 2023 at 02:31:30PM +0100, Russell King (Oracle) wrote:
> What if the parent bus doesn't have read_c45 or write_c45 ?

Good question. Predictably, the kernel crashes.

> Maybe make these conditional on the parent bus implementing the c45
> read/write ops?

I can do that, and send a v2 right away. Thanks for the hint.
Vladimir Oltean Oct. 17, 2023, 2:01 p.m. UTC | #4
On Tue, Oct 17, 2023 at 03:44:58PM +0200, Andrew Lunn wrote:
> > Maybe make these conditional on the parent bus implementing the c45
> > read/write ops?
> 
> And optionally, for net-next, make the c22 read/write ops conditional
> on the parent bus having C22 as well. Its a bit of a corner case, but
> there are a couple of MDIO bus masters which are C45 only.
> 
> Not having C45 is however very common, so we should make this
> conditional as part of the fix.
> 
>       Andrew

Ok. I don't know if net-next will remain open after this patch gets
accepted and "net" gets merged back into it, so in order to not
completely forget, I'll add a patch with your suggestion to our
Layerscape SDK and that will serve as a reminder for the next
upstreaming session.

In the meantime, for this patch:

pw-bot: cr
diff mbox series

Patch

diff --git a/drivers/net/mdio/mdio-mux.c b/drivers/net/mdio/mdio-mux.c
index a881e3523328..7d322c08c1e9 100644
--- a/drivers/net/mdio/mdio-mux.c
+++ b/drivers/net/mdio/mdio-mux.c
@@ -55,6 +55,27 @@  static int mdio_mux_read(struct mii_bus *bus, int phy_id, int regnum)
 	return r;
 }
 
+static int mdio_mux_read_c45(struct mii_bus *bus, int phy_id, int dev_addr,
+			     int regnum)
+{
+	struct mdio_mux_child_bus *cb = bus->priv;
+	struct mdio_mux_parent_bus *pb = cb->parent;
+	int r;
+
+	mutex_lock_nested(&pb->mii_bus->mdio_lock, MDIO_MUTEX_MUX);
+	r = pb->switch_fn(pb->current_child, cb->bus_number, pb->switch_data);
+	if (r)
+		goto out;
+
+	pb->current_child = cb->bus_number;
+
+	r = pb->mii_bus->read_c45(pb->mii_bus, phy_id, dev_addr, regnum);
+out:
+	mutex_unlock(&pb->mii_bus->mdio_lock);
+
+	return r;
+}
+
 /*
  * The parent bus' lock is used to order access to the switch_fn.
  */
@@ -80,6 +101,28 @@  static int mdio_mux_write(struct mii_bus *bus, int phy_id,
 	return r;
 }
 
+static int mdio_mux_write_c45(struct mii_bus *bus, int phy_id, int dev_addr,
+			      int regnum, u16 val)
+{
+	struct mdio_mux_child_bus *cb = bus->priv;
+	struct mdio_mux_parent_bus *pb = cb->parent;
+
+	int r;
+
+	mutex_lock_nested(&pb->mii_bus->mdio_lock, MDIO_MUTEX_MUX);
+	r = pb->switch_fn(pb->current_child, cb->bus_number, pb->switch_data);
+	if (r)
+		goto out;
+
+	pb->current_child = cb->bus_number;
+
+	r = pb->mii_bus->write_c45(pb->mii_bus, phy_id, dev_addr, regnum, val);
+out:
+	mutex_unlock(&pb->mii_bus->mdio_lock);
+
+	return r;
+}
+
 static int parent_count;
 
 static void mdio_mux_uninit_children(struct mdio_mux_parent_bus *pb)
@@ -173,6 +216,8 @@  int mdio_mux_init(struct device *dev,
 		cb->mii_bus->parent = dev;
 		cb->mii_bus->read = mdio_mux_read;
 		cb->mii_bus->write = mdio_mux_write;
+		cb->mii_bus->read_c45 = mdio_mux_read_c45;
+		cb->mii_bus->write_c45 = mdio_mux_write_c45;
 		r = of_mdiobus_register(cb->mii_bus, child_bus_node);
 		if (r) {
 			mdiobus_free(cb->mii_bus);