diff mbox series

[net,v2] net: dsa: mt7530: fix impossible MDIO address and issue warning

Message ID 11f5f127d0350e72569c36f9060b6e642dfaddbb.1714514208.git.daniel@makrotopia.org (mailing list archive)
State Changes Requested
Delegated to: Netdev Maintainers
Headers show
Series [net,v2] net: dsa: mt7530: fix impossible MDIO address and issue warning | 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/ynl success Generated files up to date; no warnings/errors; no diff in generated;
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: 926 this patch: 926
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 16 of 16 maintainers
netdev/build_clang success Errors and warnings before: 937 this patch: 937
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: 937 this patch: 937
netdev/checkpatch warning WARNING: Unknown commit id '868ff5f4944a', maybe rebased or not pulled? WARNING: line length of 86 exceeds 80 columns
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
netdev/contest fail net-next-2024-05-01--00-00 (tests: 999)

Commit Message

Daniel Golle April 30, 2024, 10:01 p.m. UTC
The MDIO address of the MT7530 and MT7531 switch ICs can be configured
using bootstrap pins. However, there are only 4 possible options for the
switch itself: 7, 15, 23 and 31. As in MediaTek's SDK the address of the
switch is wrongly stated in the device tree as 0 (while in reality it is
31), warn the user about such broken device tree and make a good guess
what was actually intended.

This is imporant also to not break compatibility with older device trees
as with commit 868ff5f4944a ("net: dsa: mt7530-mdio: read PHY address of
switch from device tree") the address in device tree will be taken into
account.

Fixes: b8f126a8d543 ("net-next: dsa: add dsa support for Mediatek MT7530 switch")
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
Changes since v1:
 - use FW_WARN as suggested.
 - fix build on net tree which doesn't have 'mdiodev' as member of the
   priv struct. Imho including this patch as fix makes sense to warn
   users about broken firmware, even if the change introducing the
   actual breakage is only present in net-next for now.

 drivers/net/dsa/mt7530-mdio.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

Comments

Florian Fainelli April 30, 2024, 10:08 p.m. UTC | #1
On 4/30/24 15:01, Daniel Golle wrote:
> The MDIO address of the MT7530 and MT7531 switch ICs can be configured
> using bootstrap pins. However, there are only 4 possible options for the
> switch itself: 7, 15, 23 and 31. As in MediaTek's SDK the address of the
> switch is wrongly stated in the device tree as 0 (while in reality it is
> 31), warn the user about such broken device tree and make a good guess
> what was actually intended.
> 
> This is imporant also to not break compatibility with older device trees
> as with commit 868ff5f4944a ("net: dsa: mt7530-mdio: read PHY address of
> switch from device tree") the address in device tree will be taken into
> account.
> 
> Fixes: b8f126a8d543 ("net-next: dsa: add dsa support for Mediatek MT7530 switch")
> Signed-off-by: Daniel Golle <daniel@makrotopia.org>
> ---
> Changes since v1:
>   - use FW_WARN as suggested.
>   - fix build on net tree which doesn't have 'mdiodev' as member of the
>     priv struct. Imho including this patch as fix makes sense to warn
>     users about broken firmware, even if the change introducing the
>     actual breakage is only present in net-next for now.
> 
>   drivers/net/dsa/mt7530-mdio.c | 13 +++++++++++++
>   1 file changed, 13 insertions(+)
> 
> diff --git a/drivers/net/dsa/mt7530-mdio.c b/drivers/net/dsa/mt7530-mdio.c
> index fa3ee85a99c1..3c21c8d074c7 100644
> --- a/drivers/net/dsa/mt7530-mdio.c
> +++ b/drivers/net/dsa/mt7530-mdio.c
> @@ -193,6 +193,19 @@ mt7530_probe(struct mdio_device *mdiodev)
>   			return PTR_ERR(priv->io_pwr);
>   	}
>   
> +	/* Only MDIO bus address 7, 15, 23 and 31 are valid options */
> +	if (~(mdiodev->addr & 0x7) & 0x7) {
> +		/* If the address in DT must be wrong, make a good guess about
> +		 * the most likely intention, and issue a warning.
> +		 */
> +		int correct_addr = ((((mdiodev->addr - 7) & ~0x7) % 0x20) + 7) & 0x1f;

0x20 -> PHY_MAX_ADDR
0x1F -> PHY_MAX_ADDR - 1

> +
> +		dev_warn(&mdiodev->dev, FW_WARN
> +			 "impossible switch MDIO address in device tree: %d, assuming %d\n",
> +			 mdiodev->addr, correct_addr);
> +		mdiodev->addr = correct_addr;

Sorry for not jumping on this earlier on, there is a mixture of 
hexadecimal and decimal numbers being used which IMHO just makes this 
more difficult to read than needed. It seems like the requirement is for 
the switch's MDIO device address to have the lower 3 bits set, so can we 
give it a name like MT7530_MDIO_ADDR_VALID_MASK?
Russell King (Oracle) April 30, 2024, 10:27 p.m. UTC | #2
On Tue, Apr 30, 2024 at 11:01:17PM +0100, Daniel Golle wrote:
> +	/* Only MDIO bus address 7, 15, 23 and 31 are valid options */
> +	if (~(mdiodev->addr & 0x7) & 0x7) {

So the common thing about the three addresses you mention are that they
all have the least significant three bits set. So I'd suggest to spell
that out in the comment:

	/* Only MDIO bus addresses 7, 15, 23, and 31 are valid options,
	 * which all have the least significant three bits set. Check
	 * for this.
	 */

The test here is also not obvious, so I would suggest:

	if ((mdiodev->addr & 7) != 7) {

which is much easier to read and ties up with the above comment.

> +		/* If the address in DT must be wrong, make a good guess about
> +		 * the most likely intention, and issue a warning.
> +		 */
> +		int correct_addr = ((((mdiodev->addr - 7) & ~0x7) % 0x20) + 7) & 0x1f;

Huh? Again, not obvious what this is doing. So, I threw this into a C
program that wraps the thing in a for() loop from 0..31 to see what it
produces.

addr range	result
0-6		31
7-14		7
15-22		15
23-30		23
31		31

Is it really sane to be suggesting "31" for values 0-6 ?

> +
> +		dev_warn(&mdiodev->dev, FW_WARN
> +			 "impossible switch MDIO address in device tree: %d, assuming %d\n",
> +			 mdiodev->addr, correct_addr);
> +		mdiodev->addr = correct_addr;

Sorry, but no. You must not change the mdiodev address. The address
member is used to index arrays in the MDIO bus, and changing it will
end up corrupting those arrays.

For example, when a MDIO device is registered:

	mdiodev->bus->mdio_map[mdiodev->addr] = mdiodev;

when it is unregistered:

        if (mdiodev->bus->mdio_map[mdiodev->addr] != mdiodev)
                return -EINVAL;

will fail, and a dangling pointer will be left at the original
address. Moreover, the reset control (if any) will not be put.

If the MDIO device address is wrong, then you can either fail or
maybe create a new mdio device with the correct address - but the
latter may get quite icky from a coding point of view. You would
have to tear down this other device when the original incorrect
one is unbound from the driver.
diff mbox series

Patch

diff --git a/drivers/net/dsa/mt7530-mdio.c b/drivers/net/dsa/mt7530-mdio.c
index fa3ee85a99c1..3c21c8d074c7 100644
--- a/drivers/net/dsa/mt7530-mdio.c
+++ b/drivers/net/dsa/mt7530-mdio.c
@@ -193,6 +193,19 @@  mt7530_probe(struct mdio_device *mdiodev)
 			return PTR_ERR(priv->io_pwr);
 	}
 
+	/* Only MDIO bus address 7, 15, 23 and 31 are valid options */
+	if (~(mdiodev->addr & 0x7) & 0x7) {
+		/* If the address in DT must be wrong, make a good guess about
+		 * the most likely intention, and issue a warning.
+		 */
+		int correct_addr = ((((mdiodev->addr - 7) & ~0x7) % 0x20) + 7) & 0x1f;
+
+		dev_warn(&mdiodev->dev, FW_WARN
+			 "impossible switch MDIO address in device tree: %d, assuming %d\n",
+			 mdiodev->addr, correct_addr);
+		mdiodev->addr = correct_addr;
+	}
+
 	regmap_config = devm_kzalloc(&mdiodev->dev, sizeof(*regmap_config),
 				     GFP_KERNEL);
 	if (!regmap_config)