diff mbox series

[net,v1,1/1] net: phy: micrel: ksz8081: disable broadcast only if PHY address is not 0

Message ID 20240627053353.1416261-1-o.rempel@pengutronix.de (mailing list archive)
State Changes Requested
Delegated to: Netdev Maintainers
Headers show
Series [net,v1,1/1] net: phy: micrel: ksz8081: disable broadcast only if PHY address is not 0 | 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: 859 this patch: 859
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers fail 2 blamed authors not CCed: cdleonard@gmail.com f.fainelli@gmail.com; 2 maintainers not CCed: cdleonard@gmail.com f.fainelli@gmail.com
netdev/build_clang success Errors and warnings before: 863 this patch: 863
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: 863 this patch: 863
netdev/checkpatch warning WARNING: Please use correct Fixes: style 'Fixes: <12 chars of sha1> ("<title line>")' - ie: 'Fixes: 79e498a9c7da ("net: phy: micrel: Restore led_mode and clk_sel on resume")'
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 success net-next-2024-06-28--06-00 (tests: 666)

Commit Message

Oleksij Rempel June 27, 2024, 5:33 a.m. UTC
Do not disable broadcast if we are using address 0 (broadcast) to
communicate with this device. Otherwise we will use proper driver but no
communication will be possible and no link changes will be detected.
There are two scenarios where we can run in to this situation:
- PHY is bootstrapped for address 0
- no PHY address is known and linux is scanning the MDIO bus, so first
  respond and attached device will be on address 0.

The fixes tag points to the latest refactoring, not to the initial point
where kszphy_broadcast_disable() was introduced.

Fixes: 79e498a9c7da0 ("net: phy: micrel: Restore led_mode and clk_sel on resume")
Cc: stable@vger.kernel.org
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 drivers/net/phy/micrel.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Andrew Lunn June 27, 2024, 1:56 p.m. UTC | #1
On Thu, Jun 27, 2024 at 07:33:53AM +0200, Oleksij Rempel wrote:
> Do not disable broadcast if we are using address 0 (broadcast) to
> communicate with this device. Otherwise we will use proper driver but no
> communication will be possible and no link changes will be detected.
> There are two scenarios where we can run in to this situation:
> - PHY is bootstrapped for address 0

What do you mean by bootstrapped to address 0? The strapping pins set
it to some other address, but the bootloader wrote to registers and
moved it to address 0? 

> - no PHY address is known and linux is scanning the MDIO bus, so first
>   respond and attached device will be on address 0.

So in this case, the PHY is really at address X, where X != 0. It
responds to all read requests, so the scanning finds it at all
addresses. It also stomps over other devices on the bus when scanning
for them, or probing them.

I'm not sure the current code is correct. But it is also going to be
messy to not break backwards compatibility for DT blobs say the device
is at address 0, when in fact it is not.

Is it possible to read the devices actual address from registers?

I'm wondering if probe should do something like:

int actual_address = phydev_read(phydev, 0x42);

if (actual_address == 0) {
	if (type->has_broadcast_disable) {
		phydev_dbg(phydev, "Disabling broadcast\n");
		kszphy_broadcast_disable(phydev);
	}

} else {
	if (actual_address != 0 &&
	 phydev->mdio.addr != actual_address &&
	 phydev->mdio.addr != 0) {
		if (type->has_broadcast_disable) {
			phydev_dbg(phydev, "Disabling broadcast\n");
			kszphy_broadcast_disable(phydev);
		}
        return -ENODEV;
	}
}

So if the devices really has an address is zero, turn off
broadcast. That will stop it stomping over other devices, but the
damage is probably already done in terms of scanning.

If the devices is really at some address other than 0, and we are
probing at a different address, and that address is not 0, turn off
broadcast and say the device does not exist. I think we need to
special case 0 because there are going to be some DT descriptions
which say the device is at 0, when in fact it is not. We might want to
add a phydev_warn() about this, to try to get the DT fixed.

> The fixes tag points to the latest refactoring, not to the initial point
> where kszphy_broadcast_disable() was introduced.
> 
> Fixes: 79e498a9c7da0 ("net: phy: micrel: Restore led_mode and clk_sel on resume")
> Cc: stable@vger.kernel.org
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>

Do you have a board which is going wrong because of this? Do you plan
to submit patches for earlier stable releases?

	Andrew
Oleksij Rempel June 27, 2024, 4:51 p.m. UTC | #2
Hi Andrew,

hm... looks like my previous answer is lost. I had here some hiccups on
my side. Sending new answer, do not wunder if there will be double
mail.

On Thu, Jun 27, 2024 at 03:56:42PM +0200, Andrew Lunn wrote:
> On Thu, Jun 27, 2024 at 07:33:53AM +0200, Oleksij Rempel wrote:
> > Do not disable broadcast if we are using address 0 (broadcast) to
> > communicate with this device. Otherwise we will use proper driver but no
> > communication will be possible and no link changes will be detected.
> > There are two scenarios where we can run in to this situation:
> > - PHY is bootstrapped for address 0
> 
> What do you mean by bootstrapped to address 0? The strapping pins set
> it to some other address, but the bootloader wrote to registers and
> moved it to address 0?

No no. Just strapping from HW perspective, no SW is involved.

> > - no PHY address is known and linux is scanning the MDIO bus, so first
> >   respond and attached device will be on address 0.
> 
> So in this case, the PHY is really at address X, where X != 0. It
> responds to all read requests, so the scanning finds it at all
> addresses. It also stomps over other devices on the bus when scanning
> for them, or probing them.
> 
> I'm not sure the current code is correct. But it is also going to be
> messy to not break backwards compatibility for DT blobs say the device
> is at address 0, when in fact it is not.

It looks like this is the actual case on my board.

> Is it possible to read the devices actual address from registers?

Yes.

> I'm wondering if probe should do something like:
> 
> int actual_address = phydev_read(phydev, 0x42);
> 
> if (actual_address == 0) {
> 	if (type->has_broadcast_disable) {
> 		phydev_dbg(phydev, "Disabling broadcast\n");
> 		kszphy_broadcast_disable(phydev);
> 	}
> 
> } else {
> 	if (actual_address != 0 &&
> 	 phydev->mdio.addr != actual_address &&
> 	 phydev->mdio.addr != 0) {
> 		if (type->has_broadcast_disable) {
> 			phydev_dbg(phydev, "Disabling broadcast\n");
> 			kszphy_broadcast_disable(phydev);
> 		}
>         return -ENODEV;
> 	}
> }
> 
> So if the devices really has an address is zero, turn off
> broadcast. That will stop it stomping over other devices, but the

If i understand the documentation correctly, disable broadcast bit is
designed to resolve conflict between two KSZ8081 PHYs on same bus
in one shot:
"For applications that require two KSZ8081RNA/RND PHYs to share the same
MDIO interface with one PHY set to address 0h and the other PHY set to
address 3h, use PHY address 0h (defaults to broadcast after power-up) to
set both PHYs’ Register 16h, Bit [9] to ‘1’ to assign PHY address 0h as
a unique (non-broadcast) PHY address."

For this scenario, we can't read configured address from the HW in the
first place, this can be done safely only if (phydev->mdio.addr != 0)

> damage is probably already done in terms of scanning.
> 
> If the devices is really at some address other than 0, and we are
> probing at a different address, and that address is not 0, turn off
> broadcast and say the device does not exist. I think we need to
> special case 0 because there are going to be some DT descriptions
> which say the device is at 0, when in fact it is not. We might want to
> add a phydev_warn() about this, to try to get the DT fixed.

Assuming there are no other devices on the bus listening for broadcast
too.

> > The fixes tag points to the latest refactoring, not to the initial point
> > where kszphy_broadcast_disable() was introduced.
> > 
> > Fixes: 79e498a9c7da0 ("net: phy: micrel: Restore led_mode and clk_sel on resume")
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> 
> Do you have a board which is going wrong because of this?

Yes, I can avoid this bug on the DT level. But the code side seems to be
broken too.

> Do you plan to submit patches for earlier stable releases?

Not so far. Should I?
Jakub Kicinski June 27, 2024, 9:57 p.m. UTC | #3
On Thu, 27 Jun 2024 07:33:53 +0200 Oleksij Rempel wrote:
> Do not disable broadcast if we are using address 0 (broadcast) to
> communicate with this device. Otherwise we will use proper driver but no
> communication will be possible and no link changes will be detected.
> There are two scenarios where we can run in to this situation:
> - PHY is bootstrapped for address 0
> - no PHY address is known and linux is scanning the MDIO bus, so first
>   respond and attached device will be on address 0.
> 
> The fixes tag points to the latest refactoring, not to the initial point
> where kszphy_broadcast_disable() was introduced.
> 
> Fixes: 79e498a9c7da0 ("net: phy: micrel: Restore led_mode and clk_sel on resume")

Is there a reason you're not CCing the author ?
diff mbox series

Patch

diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 81c20eb4b54b9..67c2e611150d2 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -590,7 +590,7 @@  static int kszphy_config_init(struct phy_device *phydev)
 
 	type = priv->type;
 
-	if (type && type->has_broadcast_disable)
+	if (type && type->has_broadcast_disable && phydev->mdio.addr != 0)
 		kszphy_broadcast_disable(phydev);
 
 	if (type && type->has_nand_tree_disable)