Message ID | 20230116-net-next-remove-probe-capabilities-v1-3-5aa29738a023@walle.cc (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | net: phy: Remove probe_capabilities | expand |
On 1/16/2023 4:55 AM, Michael Walle wrote: > From: Andrew Lunn <andrew@lunn.ch> > > After scanning the bus for C22 devices, check if any Micrel PHYs have > been found. They are known to do bad things if there are C45 > transactions on the bus. Prevent the scanning of the bus using C45 if > such a PHY has been detected. > > Signed-off-by: Andrew Lunn <andrew@lunn.ch> > Signed-off-by: Michael Walle <michael@walle.cc> > --- ... > @@ -600,6 +601,31 @@ static int mdiobus_scan_bus_c45(struct mii_bus *bus) > return 0; > } > > +/* There are some C22 PHYs which do bad things when where is a C45 > + * transaction on the bus, like accepting a read themselves, and > + * stomping over the true devices reply, to performing a write to > + * themselves which was intended for another device. Now that C22 > + * devices have been found, see if any of them are bad for C45, and if we > + * should skip the C45 scan. > + */ > +static bool mdiobus_prevent_c45_scan(struct mii_bus *bus) > +{ > + struct phy_device *phydev; > + u32 oui; nit: phydev and oui declarations can move inside the loop > + int i; > + > + for (i = 0; i < PHY_MAX_ADDR; i++) { > + phydev = mdiobus_get_phy(bus, i); > + if (!phydev) > + continue; > + oui = phydev->phy_id >> 10; > + > + if (oui == MICREL_OUI) > + return true; > + } > + return false; > +} > + > /** > * __mdiobus_register - bring up all the PHYs on a given bus and attach them to bus > * @bus: target mii_bus
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 25a964b98bc6..f173c91842e0 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -19,6 +19,7 @@ #include <linux/interrupt.h> #include <linux/io.h> #include <linux/kernel.h> +#include <linux/micrel_phy.h> #include <linux/mii.h> #include <linux/mm.h> #include <linux/module.h> @@ -600,6 +601,31 @@ static int mdiobus_scan_bus_c45(struct mii_bus *bus) return 0; } +/* There are some C22 PHYs which do bad things when where is a C45 + * transaction on the bus, like accepting a read themselves, and + * stomping over the true devices reply, to performing a write to + * themselves which was intended for another device. Now that C22 + * devices have been found, see if any of them are bad for C45, and if we + * should skip the C45 scan. + */ +static bool mdiobus_prevent_c45_scan(struct mii_bus *bus) +{ + struct phy_device *phydev; + u32 oui; + int i; + + for (i = 0; i < PHY_MAX_ADDR; i++) { + phydev = mdiobus_get_phy(bus, i); + if (!phydev) + continue; + oui = phydev->phy_id >> 10; + + if (oui == MICREL_OUI) + return true; + } + return false; +} + /** * __mdiobus_register - bring up all the PHYs on a given bus and attach them to bus * @bus: target mii_bus @@ -617,8 +643,9 @@ static int mdiobus_scan_bus_c45(struct mii_bus *bus) int __mdiobus_register(struct mii_bus *bus, struct module *owner) { struct mdio_device *mdiodev; - int i, err; struct gpio_desc *gpiod; + bool prevent_c45_scan; + int i, err; if (!bus || !bus->name) return -EINVAL; @@ -691,8 +718,11 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner) goto error; } - if (bus->probe_capabilities == MDIOBUS_C45 || - bus->probe_capabilities == MDIOBUS_C22_C45) { + prevent_c45_scan = mdiobus_prevent_c45_scan(bus); + + if (!prevent_c45_scan && + (bus->probe_capabilities == MDIOBUS_C45 || + bus->probe_capabilities == MDIOBUS_C22_C45)) { err = mdiobus_scan_bus_c45(bus); if (err) goto error; diff --git a/include/linux/micrel_phy.h b/include/linux/micrel_phy.h index 1f7c33b2f5a3..771e050883db 100644 --- a/include/linux/micrel_phy.h +++ b/include/linux/micrel_phy.h @@ -8,6 +8,8 @@ #ifndef _MICREL_PHY_H #define _MICREL_PHY_H +#define MICREL_OUI 0x0885 + #define MICREL_PHY_ID_MASK 0x00fffff0 #define PHY_ID_KSZ8873MLL 0x000e7237