2023-01-18 11:10:02

by Michael Walle

[permalink] [raw]
Subject: [PATCH net-next v2 0/6] net: phy: Remove probe_capabilities

With all the drivers which used .probe_capabilities converted to the
new c45 MDIO access methods, we can now decide based upon these whether
a bus driver supports c45 and we can get rid of the not widely used
probe_capabilites.

Unfortunately, due to a now broader support of c45 scans, this will
trigger a bug on some boards with a (c22-only) Micrel PHY. These PHYs
don't ignore c45 accesses correctly, thinking they are addressed
themselves and distrupt the MDIO access. To avoid this, a blacklist
for c45 scans is introduced.

To: Heiner Kallweit <[email protected]>
To: Russell King <[email protected]>
To: "David S. Miller" <[email protected]>
To: Eric Dumazet <[email protected]>
To: Jakub Kicinski <[email protected]>
To: Paolo Abeni <[email protected]>
To: Felix Fietkau <[email protected]>
To: John Crispin <[email protected]>
To: Sean Wang <[email protected]>
To: Mark Lee <[email protected]>
To: Lorenzo Bianconi <[email protected]>
To: Matthias Brugger <[email protected]>
To: Bryan Whitehead <[email protected]>
To: [email protected]
To: Giuseppe Cavallaro <[email protected]>
To: Alexandre Torgue <[email protected]>
To: Jose Abreu <[email protected]>
To: Maxime Coquelin <[email protected]>
To: Joel Stanley <[email protected]>
To: Andrew Jeffery <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: Andrew Lunn <[email protected]>
Signed-off-by: Michael Walle <[email protected]>

---
- Link to v1: https://lore.kernel.org/r/20230116-net-next-remove-probe-capabilities-v1-0-5aa29738a023@walle.cc

---
Andrew Lunn (6):
net: mdio: Move mdiobus_scan() within file
net: mdio: Rework scanning of bus ready for quirks
net: mdio: Add workaround for Micrel PHYs which are not C45 compatible
net: mdio: scan bus based on bus capabilities for C22 and C45
net: phy: Decide on C45 capabilities based on presence of method
net: phy: Remove probe_capabilities

drivers/net/ethernet/adi/adin1110.c | 1 -
drivers/net/ethernet/freescale/xgmac_mdio.c | 1 -
drivers/net/ethernet/marvell/pxa168_eth.c | 2 +-
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 -
drivers/net/ethernet/microchip/lan743x_main.c | 2 -
drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 3 -
drivers/net/mdio/mdio-aspeed.c | 1 -
drivers/net/phy/mdio_bus.c | 197 +++++++++++++++-------
drivers/net/phy/phy_device.c | 2 +-
include/linux/micrel_phy.h | 2 +
include/linux/phy.h | 10 +-
11 files changed, 140 insertions(+), 82 deletions(-)
---
base-commit: c12e2e5b76b2e739ccdf196bee960412b45d5f85
change-id: 20230116-net-next-remove-probe-capabilities-03d401439fc6

Best regards,
--
Michael Walle <[email protected]>


2023-01-18 11:10:10

by Michael Walle

[permalink] [raw]
Subject: [PATCH net-next v2 5/6] net: phy: Decide on C45 capabilities based on presence of method

From: Andrew Lunn <[email protected]>

Some PHYs provide invalid IDs in C22 space. If C45 is supported on the
bus an attempt can be made to get the IDs from the C45 space. Decide
on this based on the presence of the C45 read method in the bus
structure. This will allow the unreliable probe_capabilities to be
removed.

Signed-off-by: Andrew Lunn <[email protected]>
Signed-off-by: Michael Walle <[email protected]>
Reviewed-by: Jesse Brandeburg <[email protected]>
---
drivers/net/phy/phy_device.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 0d371a0a49f2..9ba8f973f26f 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -946,7 +946,7 @@ struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45)
* probe with C45 to see if we're able to get a valid PHY ID in the C45
* space, if successful, create the C45 PHY device.
*/
- if (!is_c45 && phy_id == 0 && bus->probe_capabilities >= MDIOBUS_C45) {
+ if (!is_c45 && phy_id == 0 && bus->read_c45) {
r = get_phy_c45_ids(bus, addr, &c45_ids);
if (!r)
return phy_device_create(bus, addr, phy_id,

--
2.30.2

2023-01-18 11:10:30

by Michael Walle

[permalink] [raw]
Subject: [PATCH net-next v2 6/6] net: phy: Remove probe_capabilities

From: Andrew Lunn <[email protected]>

Deciding if to probe of PHYs using C45 is now determine by if the bus
provides the C45 read method. This makes probe_capabilities redundant
so remove it.

Signed-off-by: Andrew Lunn <[email protected]>
Signed-off-by: Michael Walle <[email protected]>
Reviewed-by: Jesse Brandeburg <[email protected]>
---
drivers/net/ethernet/adi/adin1110.c | 1 -
drivers/net/ethernet/freescale/xgmac_mdio.c | 1 -
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 -
drivers/net/ethernet/microchip/lan743x_main.c | 2 --
drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 3 ---
drivers/net/mdio/mdio-aspeed.c | 1 -
include/linux/phy.h | 8 --------
7 files changed, 17 deletions(-)

diff --git a/drivers/net/ethernet/adi/adin1110.c b/drivers/net/ethernet/adi/adin1110.c
index 0805f249fff2..25f55756681d 100644
--- a/drivers/net/ethernet/adi/adin1110.c
+++ b/drivers/net/ethernet/adi/adin1110.c
@@ -523,7 +523,6 @@ static int adin1110_register_mdiobus(struct adin1110_priv *priv,
mii_bus->priv = priv;
mii_bus->parent = dev;
mii_bus->phy_mask = ~((u32)GENMASK(2, 0));
- mii_bus->probe_capabilities = MDIOBUS_C22;
snprintf(mii_bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));

ret = devm_mdiobus_register(dev, mii_bus);
diff --git a/drivers/net/ethernet/freescale/xgmac_mdio.c b/drivers/net/ethernet/freescale/xgmac_mdio.c
index 8b5a4cd8ff08..a13b4ba4d6e1 100644
--- a/drivers/net/ethernet/freescale/xgmac_mdio.c
+++ b/drivers/net/ethernet/freescale/xgmac_mdio.c
@@ -397,7 +397,6 @@ static int xgmac_mdio_probe(struct platform_device *pdev)
bus->read_c45 = xgmac_mdio_read_c45;
bus->write_c45 = xgmac_mdio_write_c45;
bus->parent = &pdev->dev;
- bus->probe_capabilities = MDIOBUS_C22_C45;
snprintf(bus->id, MII_BUS_ID_SIZE, "%pa", &res->start);

priv = bus->priv;
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index dc50e0b227a6..d67ec28b2ba3 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -808,7 +808,6 @@ static int mtk_mdio_init(struct mtk_eth *eth)
eth->mii_bus->write = mtk_mdio_write_c22;
eth->mii_bus->read_c45 = mtk_mdio_read_c45;
eth->mii_bus->write_c45 = mtk_mdio_write_c45;
- eth->mii_bus->probe_capabilities = MDIOBUS_C22_C45;
eth->mii_bus->priv = eth;
eth->mii_bus->parent = eth->dev;

diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
index e205edf477de..86b81df374da 100644
--- a/drivers/net/ethernet/microchip/lan743x_main.c
+++ b/drivers/net/ethernet/microchip/lan743x_main.c
@@ -3279,7 +3279,6 @@ static int lan743x_mdiobus_init(struct lan743x_adapter *adapter)
lan743x_csr_write(adapter, SGMII_CTL, sgmii_ctl);
netif_dbg(adapter, drv, adapter->netdev,
"SGMII operation\n");
- adapter->mdiobus->probe_capabilities = MDIOBUS_C22_C45;
adapter->mdiobus->read = lan743x_mdiobus_read_c22;
adapter->mdiobus->write = lan743x_mdiobus_write_c22;
adapter->mdiobus->read_c45 = lan743x_mdiobus_read_c45;
@@ -3295,7 +3294,6 @@ static int lan743x_mdiobus_init(struct lan743x_adapter *adapter)
netif_dbg(adapter, drv, adapter->netdev,
"RGMII operation\n");
// Only C22 support when RGMII I/F
- adapter->mdiobus->probe_capabilities = MDIOBUS_C22;
adapter->mdiobus->read = lan743x_mdiobus_read_c22;
adapter->mdiobus->write = lan743x_mdiobus_write_c22;
adapter->mdiobus->name = "lan743x-mdiobus";
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
index d2cb22f49ce5..21aaa2730ac8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -553,9 +553,6 @@ int stmmac_mdio_register(struct net_device *ndev)

new_bus->name = "stmmac";

- if (priv->plat->has_gmac4)
- new_bus->probe_capabilities = MDIOBUS_C22_C45;
-
if (priv->plat->has_xgmac) {
new_bus->read = &stmmac_xgmac2_mdio_read_c22;
new_bus->write = &stmmac_xgmac2_mdio_write_c22;
diff --git a/drivers/net/mdio/mdio-aspeed.c b/drivers/net/mdio/mdio-aspeed.c
index 2f4bbda5e56c..c727103c8b05 100644
--- a/drivers/net/mdio/mdio-aspeed.c
+++ b/drivers/net/mdio/mdio-aspeed.c
@@ -164,7 +164,6 @@ static int aspeed_mdio_probe(struct platform_device *pdev)
bus->write = aspeed_mdio_write_c22;
bus->read_c45 = aspeed_mdio_read_c45;
bus->write_c45 = aspeed_mdio_write_c45;
- bus->probe_capabilities = MDIOBUS_C22_C45;

rc = of_mdiobus_register(bus, pdev->dev.of_node);
if (rc) {
diff --git a/include/linux/phy.h b/include/linux/phy.h
index fceaac0fb319..fbeba4fee8d4 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -419,14 +419,6 @@ struct mii_bus {
/** @reset_gpiod: Reset GPIO descriptor pointer */
struct gpio_desc *reset_gpiod;

- /** @probe_capabilities: bus capabilities, used for probing */
- enum {
- MDIOBUS_NO_CAP = 0,
- MDIOBUS_C22,
- MDIOBUS_C45,
- MDIOBUS_C22_C45,
- } probe_capabilities;
-
/** @shared_lock: protect access to the shared element */
struct mutex shared_lock;


--
2.30.2

2023-01-18 11:10:36

by Michael Walle

[permalink] [raw]
Subject: [PATCH net-next v2 1/6] net: mdio: Move mdiobus_scan() within file

From: Andrew Lunn <[email protected]>

No functional change, just place it earlier in preparation for some
refactoring.

While at it, correct the comment format and one typo.

Signed-off-by: Andrew Lunn <[email protected]>
Signed-off-by: Michael Walle <[email protected]>
Reviewed-by: Jesse Brandeburg <[email protected]>
---
drivers/net/phy/mdio_bus.c | 101 ++++++++++++++++++++++-----------------------
1 file changed, 50 insertions(+), 51 deletions(-)

diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 902e1c88ef58..61c33c6098a1 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -506,6 +506,56 @@ static int mdiobus_create_device(struct mii_bus *bus,
return ret;
}

+/**
+ * mdiobus_scan - scan a bus for MDIO devices.
+ * @bus: mii_bus to scan
+ * @addr: address on bus to scan
+ *
+ * This function scans the MDIO bus, looking for devices which can be
+ * identified using a vendor/product ID in registers 2 and 3. Not all
+ * MDIO devices have such registers, but PHY devices typically
+ * do. Hence this function assumes anything found is a PHY, or can be
+ * treated as a PHY. Other MDIO devices, such as switches, will
+ * probably not be found during the scan.
+ */
+struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr)
+{
+ struct phy_device *phydev = ERR_PTR(-ENODEV);
+ int err;
+
+ switch (bus->probe_capabilities) {
+ case MDIOBUS_NO_CAP:
+ case MDIOBUS_C22:
+ phydev = get_phy_device(bus, addr, false);
+ break;
+ case MDIOBUS_C45:
+ phydev = get_phy_device(bus, addr, true);
+ break;
+ case MDIOBUS_C22_C45:
+ phydev = get_phy_device(bus, addr, false);
+ if (IS_ERR(phydev))
+ phydev = get_phy_device(bus, addr, true);
+ break;
+ }
+
+ if (IS_ERR(phydev))
+ return phydev;
+
+ /* For DT, see if the auto-probed phy has a corresponding child
+ * in the bus node, and set the of_node pointer in this case.
+ */
+ of_mdiobus_link_mdiodev(bus, &phydev->mdio);
+
+ err = phy_device_register(phydev);
+ if (err) {
+ phy_device_free(phydev);
+ return ERR_PTR(-ENODEV);
+ }
+
+ return phydev;
+}
+EXPORT_SYMBOL(mdiobus_scan);
+
/**
* __mdiobus_register - bring up all the PHYs on a given bus and attach them to bus
* @bus: target mii_bus
@@ -679,57 +729,6 @@ void mdiobus_free(struct mii_bus *bus)
}
EXPORT_SYMBOL(mdiobus_free);

-/**
- * mdiobus_scan - scan a bus for MDIO devices.
- * @bus: mii_bus to scan
- * @addr: address on bus to scan
- *
- * This function scans the MDIO bus, looking for devices which can be
- * identified using a vendor/product ID in registers 2 and 3. Not all
- * MDIO devices have such registers, but PHY devices typically
- * do. Hence this function assumes anything found is a PHY, or can be
- * treated as a PHY. Other MDIO devices, such as switches, will
- * probably not be found during the scan.
- */
-struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr)
-{
- struct phy_device *phydev = ERR_PTR(-ENODEV);
- int err;
-
- switch (bus->probe_capabilities) {
- case MDIOBUS_NO_CAP:
- case MDIOBUS_C22:
- phydev = get_phy_device(bus, addr, false);
- break;
- case MDIOBUS_C45:
- phydev = get_phy_device(bus, addr, true);
- break;
- case MDIOBUS_C22_C45:
- phydev = get_phy_device(bus, addr, false);
- if (IS_ERR(phydev))
- phydev = get_phy_device(bus, addr, true);
- break;
- }
-
- if (IS_ERR(phydev))
- return phydev;
-
- /*
- * For DT, see if the auto-probed phy has a correspoding child
- * in the bus node, and set the of_node pointer in this case.
- */
- of_mdiobus_link_mdiodev(bus, &phydev->mdio);
-
- err = phy_device_register(phydev);
- if (err) {
- phy_device_free(phydev);
- return ERR_PTR(-ENODEV);
- }
-
- return phydev;
-}
-EXPORT_SYMBOL(mdiobus_scan);
-
static void mdiobus_stats_acct(struct mdio_bus_stats *stats, bool op, int ret)
{
preempt_disable();

--
2.30.2

2023-01-18 11:13:24

by Michael Walle

[permalink] [raw]
Subject: [PATCH net-next v2 3/6] net: mdio: Add workaround for Micrel PHYs which are not C45 compatible

From: Andrew Lunn <[email protected]>

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 <[email protected]>
Signed-off-by: Michael Walle <[email protected]>
---
v2:
[mw] move variable declaration into the loop. Thanks, Jesse.
---
drivers/net/phy/mdio_bus.c | 37 ++++++++++++++++++++++++++++++++++---
include/linux/micrel_phy.h | 2 ++
2 files changed, 36 insertions(+), 3 deletions(-)

diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 667247f661c5..a664eeb1868d 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,32 @@ 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)
+{
+ int i;
+
+ for (i = 0; i < PHY_MAX_ADDR; i++) {
+ struct phy_device *phydev;
+ u32 oui;
+
+ 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 +644,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 +719,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

--
2.30.2

2023-01-18 11:36:44

by Michael Walle

[permalink] [raw]
Subject: [PATCH net-next v2 2/6] net: mdio: Rework scanning of bus ready for quirks

From: Andrew Lunn <[email protected]>

Some C22 PHYs do bad things when there are C45 transactions on the
bus. In order to handle this, the bus needs to be scanned first for
C22 at all addresses, and then C45 scanned for all addresses.

The Marvell pxa168 driver scans a specific address on the bus to find
its PHY. This is a C22 only device, so update it to use the c22
helper.

Signed-off-by: Andrew Lunn <[email protected]>
Signed-off-by: Michael Walle <[email protected]>
Reviewed-by: Jesse Brandeburg <[email protected]>
---
v2:
[mw] Avoid the use of unitialized variabe. Thanks Jakub.
Just iterate over all possible addresses in the error path.
---
drivers/net/ethernet/marvell/pxa168_eth.c | 2 +-
drivers/net/phy/mdio_bus.c | 125 ++++++++++++++++++++----------
include/linux/phy.h | 2 +-
3 files changed, 88 insertions(+), 41 deletions(-)

diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c
index cf456d62677f..87fff539d39d 100644
--- a/drivers/net/ethernet/marvell/pxa168_eth.c
+++ b/drivers/net/ethernet/marvell/pxa168_eth.c
@@ -965,7 +965,7 @@ static int pxa168_init_phy(struct net_device *dev)
if (dev->phydev)
return 0;

- phy = mdiobus_scan(pep->smi_bus, pep->phy_addr);
+ phy = mdiobus_scan_c22(pep->smi_bus, pep->phy_addr);
if (IS_ERR(phy))
return PTR_ERR(phy);

diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 61c33c6098a1..667247f661c5 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -506,38 +506,12 @@ static int mdiobus_create_device(struct mii_bus *bus,
return ret;
}

-/**
- * mdiobus_scan - scan a bus for MDIO devices.
- * @bus: mii_bus to scan
- * @addr: address on bus to scan
- *
- * This function scans the MDIO bus, looking for devices which can be
- * identified using a vendor/product ID in registers 2 and 3. Not all
- * MDIO devices have such registers, but PHY devices typically
- * do. Hence this function assumes anything found is a PHY, or can be
- * treated as a PHY. Other MDIO devices, such as switches, will
- * probably not be found during the scan.
- */
-struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr)
+static struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr, bool c45)
{
struct phy_device *phydev = ERR_PTR(-ENODEV);
int err;

- switch (bus->probe_capabilities) {
- case MDIOBUS_NO_CAP:
- case MDIOBUS_C22:
- phydev = get_phy_device(bus, addr, false);
- break;
- case MDIOBUS_C45:
- phydev = get_phy_device(bus, addr, true);
- break;
- case MDIOBUS_C22_C45:
- phydev = get_phy_device(bus, addr, false);
- if (IS_ERR(phydev))
- phydev = get_phy_device(bus, addr, true);
- break;
- }
-
+ phydev = get_phy_device(bus, addr, c45);
if (IS_ERR(phydev))
return phydev;

@@ -554,7 +528,77 @@ struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr)

return phydev;
}
-EXPORT_SYMBOL(mdiobus_scan);
+
+/**
+ * mdiobus_scan_c22 - scan one address on a bus for C22 MDIO devices.
+ * @bus: mii_bus to scan
+ * @addr: address on bus to scan
+ *
+ * This function scans one address on the MDIO bus, looking for
+ * devices which can be identified using a vendor/product ID in
+ * registers 2 and 3. Not all MDIO devices have such registers, but
+ * PHY devices typically do. Hence this function assumes anything
+ * found is a PHY, or can be treated as a PHY. Other MDIO devices,
+ * such as switches, will probably not be found during the scan.
+ */
+struct phy_device *mdiobus_scan_c22(struct mii_bus *bus, int addr)
+{
+ return mdiobus_scan(bus, addr, false);
+}
+EXPORT_SYMBOL(mdiobus_scan_c22);
+
+/**
+ * mdiobus_scan_c45 - scan one address on a bus for C45 MDIO devices.
+ * @bus: mii_bus to scan
+ * @addr: address on bus to scan
+ *
+ * This function scans one address on the MDIO bus, looking for
+ * devices which can be identified using a vendor/product ID in
+ * registers 2 and 3. Not all MDIO devices have such registers, but
+ * PHY devices typically do. Hence this function assumes anything
+ * found is a PHY, or can be treated as a PHY. Other MDIO devices,
+ * such as switches, will probably not be found during the scan.
+ */
+static struct phy_device *mdiobus_scan_c45(struct mii_bus *bus, int addr)
+{
+ return mdiobus_scan(bus, addr, true);
+}
+
+static int mdiobus_scan_bus_c22(struct mii_bus *bus)
+{
+ int i;
+
+ for (i = 0; i < PHY_MAX_ADDR; i++) {
+ if ((bus->phy_mask & BIT(i)) == 0) {
+ struct phy_device *phydev;
+
+ phydev = mdiobus_scan_c22(bus, i);
+ if (IS_ERR(phydev) && (PTR_ERR(phydev) != -ENODEV))
+ return PTR_ERR(phydev);
+ }
+ }
+ return 0;
+}
+
+static int mdiobus_scan_bus_c45(struct mii_bus *bus)
+{
+ int i;
+
+ for (i = 0; i < PHY_MAX_ADDR; i++) {
+ if ((bus->phy_mask & BIT(i)) == 0) {
+ struct phy_device *phydev;
+
+ /* Don't scan C45 if we already have a C22 device */
+ if (bus->mdio_map[i])
+ continue;
+
+ phydev = mdiobus_scan_c45(bus, i);
+ if (IS_ERR(phydev) && (PTR_ERR(phydev) != -ENODEV))
+ return PTR_ERR(phydev);
+ }
+ }
+ return 0;
+}

/**
* __mdiobus_register - bring up all the PHYs on a given bus and attach them to bus
@@ -639,16 +683,19 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
goto error_reset_gpiod;
}

- for (i = 0; i < PHY_MAX_ADDR; i++) {
- if ((bus->phy_mask & BIT(i)) == 0) {
- struct phy_device *phydev;
+ if (bus->probe_capabilities == MDIOBUS_NO_CAP ||
+ bus->probe_capabilities == MDIOBUS_C22 ||
+ bus->probe_capabilities == MDIOBUS_C22_C45) {
+ err = mdiobus_scan_bus_c22(bus);
+ if (err)
+ goto error;
+ }

- phydev = mdiobus_scan(bus, i);
- if (IS_ERR(phydev) && (PTR_ERR(phydev) != -ENODEV)) {
- err = PTR_ERR(phydev);
- goto error;
- }
- }
+ if (bus->probe_capabilities == MDIOBUS_C45 ||
+ bus->probe_capabilities == MDIOBUS_C22_C45) {
+ err = mdiobus_scan_bus_c45(bus);
+ if (err)
+ goto error;
}

mdiobus_setup_mdiodev_from_board_info(bus, mdiobus_create_device);
@@ -658,7 +705,7 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
return 0;

error:
- while (--i >= 0) {
+ for (i = 0; i < PHY_MAX_ADDR; i++) {
mdiodev = bus->mdio_map[i];
if (!mdiodev)
continue;
diff --git a/include/linux/phy.h b/include/linux/phy.h
index b3cf1e08e880..fceaac0fb319 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -464,7 +464,7 @@ static inline struct mii_bus *devm_mdiobus_alloc(struct device *dev)
}

struct mii_bus *mdio_find_bus(const char *mdio_name);
-struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr);
+struct phy_device *mdiobus_scan_c22(struct mii_bus *bus, int addr);

#define PHY_INTERRUPT_DISABLED false
#define PHY_INTERRUPT_ENABLED true

--
2.30.2

2023-01-19 06:44:30

by Andrew Jeffery

[permalink] [raw]
Subject: Re: [PATCH net-next v2 6/6] net: phy: Remove probe_capabilities



On Wed, 18 Jan 2023, at 20:31, Michael Walle wrote:
> From: Andrew Lunn <[email protected]>
>
> Deciding if to probe of PHYs using C45 is now determine by if the bus
> provides the C45 read method. This makes probe_capabilities redundant
> so remove it.
>
> Signed-off-by: Andrew Lunn <[email protected]>
> Signed-off-by: Michael Walle <[email protected]>
> Reviewed-by: Jesse Brandeburg <[email protected]>
> ---
> drivers/net/ethernet/adi/adin1110.c | 1 -
> drivers/net/ethernet/freescale/xgmac_mdio.c | 1 -
> drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 -
> drivers/net/ethernet/microchip/lan743x_main.c | 2 --
> drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 3 ---
> drivers/net/mdio/mdio-aspeed.c | 1 -

For the Aspeed change:

Acked-by: Andrew Jeffery <[email protected]>

2023-01-20 04:46:31

by patchwork-bot+netdevbpf

[permalink] [raw]
Subject: Re: [PATCH net-next v2 0/6] net: phy: Remove probe_capabilities

Hello:

This series was applied to netdev/net-next.git (master)
by Paolo Abeni <[email protected]>:

On Wed, 18 Jan 2023 11:01:35 +0100 you wrote:
> With all the drivers which used .probe_capabilities converted to the
> new c45 MDIO access methods, we can now decide based upon these whether
> a bus driver supports c45 and we can get rid of the not widely used
> probe_capabilites.
>
> Unfortunately, due to a now broader support of c45 scans, this will
> trigger a bug on some boards with a (c22-only) Micrel PHY. These PHYs
> don't ignore c45 accesses correctly, thinking they are addressed
> themselves and distrupt the MDIO access. To avoid this, a blacklist
> for c45 scans is introduced.
>
> [...]

Here is the summary with links:
- [net-next,v2,1/6] net: mdio: Move mdiobus_scan() within file
https://git.kernel.org/netdev/net-next/c/81d874e7c84e
- [net-next,v2,2/6] net: mdio: Rework scanning of bus ready for quirks
https://git.kernel.org/netdev/net-next/c/d41e127757f3
- [net-next,v2,3/6] net: mdio: Add workaround for Micrel PHYs which are not C45 compatible
https://git.kernel.org/netdev/net-next/c/348659337485
- [net-next,v2,4/6] net: mdio: scan bus based on bus capabilities for C22 and C45
https://git.kernel.org/netdev/net-next/c/1a136ca2e089
- [net-next,v2,5/6] net: phy: Decide on C45 capabilities based on presence of method
https://git.kernel.org/netdev/net-next/c/fbfe97597c77
- [net-next,v2,6/6] net: phy: Remove probe_capabilities
https://git.kernel.org/netdev/net-next/c/da099a7fb13d

You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html