diff mbox series

of: of_mdio: count number of regitered phys

Message ID 1593415596-9487-1-git-send-email-claudiu.beznea@microchip.com
State Changes Requested
Headers show
Series of: of_mdio: count number of regitered phys | expand

Checks

Context Check Description
robh/checkpatch success

Commit Message

Claudiu Beznea June 29, 2020, 7:26 a.m. UTC
In case of_mdiobus_register_phy()/of_mdiobus_register_device()
returns -ENODEV for all PHYs in device tree or for all scanned
PHYs there is a chance that of_mdiobus_register() to
return success code although no PHY devices were registered.
Add a counter that increments every time a PHY was registered
to avoid the above scenario.

Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
---

Though I haven't encountered the scenario described in commit
message. Just went through this code and seemed to me that it
could be enhanved by checking the number of successfuly
registered devices.

Thank you,
Claudiu Beznea

 drivers/of/of_mdio.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

Comments

Andrew Lunn June 30, 2020, 12:45 a.m. UTC | #1
On Mon, Jun 29, 2020 at 10:26:36AM +0300, Claudiu Beznea wrote:
> In case of_mdiobus_register_phy()/of_mdiobus_register_device()
> returns -ENODEV for all PHYs in device tree or for all scanned
> PHYs there is a chance that of_mdiobus_register() to
> return success code although no PHY devices were registered.
> Add a counter that increments every time a PHY was registered
> to avoid the above scenario.

Hi Claudiu

There is a danger here this will break something. Without this patch,
an empty bus is O.K. But with this patch, a bus without a PHY is a
problem.

Take for example FEC. It often comes in pairs. Each has an MDIO
bus. But to save pins, there are some designs which place two PHYs on
one bus, leaving the other empty. The driver unconditionally calls
of_mdiobus_register() and if it returns an error, it will error out
the probe. So i would not be too surprised if you get reports of
missing interfaces with this patch.

	Andrew
Florian Fainelli June 30, 2020, 3:35 a.m. UTC | #2
On 6/29/2020 5:45 PM, Andrew Lunn wrote:
> On Mon, Jun 29, 2020 at 10:26:36AM +0300, Claudiu Beznea wrote:
>> In case of_mdiobus_register_phy()/of_mdiobus_register_device()
>> returns -ENODEV for all PHYs in device tree or for all scanned
>> PHYs there is a chance that of_mdiobus_register() to
>> return success code although no PHY devices were registered.
>> Add a counter that increments every time a PHY was registered
>> to avoid the above scenario.
> 
> Hi Claudiu
> 
> There is a danger here this will break something. Without this patch,
> an empty bus is O.K. But with this patch, a bus without a PHY is a
> problem.
> 
> Take for example FEC. It often comes in pairs. Each has an MDIO
> bus. But to save pins, there are some designs which place two PHYs on
> one bus, leaving the other empty. The driver unconditionally calls
> of_mdiobus_register() and if it returns an error, it will error out
> the probe. So i would not be too surprised if you get reports of
> missing interfaces with this patch.

Agreed, the potential for breakage here is too high especially given
this is fixing a hypothetical problem rather an an actual one. Even if
we were taking this from the angle of power management, runtime PM
should ensure that a MDIO bus with no slave, or no activity gets runtime
suspended.
Claudiu Beznea July 1, 2020, 8:47 a.m. UTC | #3
Hi Andrew, Florian,

On 30.06.2020 06:35, Florian Fainelli wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> On 6/29/2020 5:45 PM, Andrew Lunn wrote:
>> On Mon, Jun 29, 2020 at 10:26:36AM +0300, Claudiu Beznea wrote:
>>> In case of_mdiobus_register_phy()/of_mdiobus_register_device()
>>> returns -ENODEV for all PHYs in device tree or for all scanned
>>> PHYs there is a chance that of_mdiobus_register() to
>>> return success code although no PHY devices were registered.
>>> Add a counter that increments every time a PHY was registered
>>> to avoid the above scenario.
>>
>> Hi Claudiu
>>
>> There is a danger here this will break something. Without this patch,
>> an empty bus is O.K. But with this patch, a bus without a PHY is a
>> problem.
>>
>> Take for example FEC. It often comes in pairs. Each has an MDIO
>> bus. But to save pins, there are some designs which place two PHYs on
>> one bus, leaving the other empty. The driver unconditionally calls
>> of_mdiobus_register() and if it returns an error, it will error out
>> the probe. So i would not be too surprised if you get reports of
>> missing interfaces with this patch.
> 
> Agreed, the potential for breakage here is too high especially given
> this is fixing a hypothetical problem rather an an actual one. Even if
> we were taking this from the angle of power management, runtime PM
> should ensure that a MDIO bus with no slave, or no activity gets runtime
> suspended.

I understand your points. Thank you for taking time on reviewing this.

Claudiu Beznea

> --
> Florian
>
diff mbox series

Patch

diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
index eb84507de28a..bbf1d42d27f8 100644
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -249,7 +249,7 @@  int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
 {
 	struct device_node *child;
 	bool scanphys = false;
-	int addr, rc;
+	int addr, rc, devices = 0;
 
 	if (!np)
 		return mdiobus_register(mdio);
@@ -293,9 +293,11 @@  int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
 				addr);
 		else if (rc)
 			goto unregister;
+		else
+			devices++;
 	}
 
-	if (!scanphys)
+	if (!scanphys && devices)
 		return 0;
 
 	/* auto scan for PHYs with empty reg property */
@@ -319,14 +321,21 @@  int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
 				 * scanning should continue.
 				 */
 				rc = of_mdiobus_register_phy(mdio, child, addr);
-				if (!rc)
+				if (!rc) {
+					devices++;
 					break;
+				}
 				if (rc != -ENODEV)
 					goto unregister;
 			}
 		}
 	}
 
+	if (!devices) {
+		rc = -ENODEV;
+		goto unregister;
+	}
+
 	return 0;
 
 unregister: