net: phy: as21xxx: stop probing foreign PHYs (root cause of the MxL862xx relay error flood) - #207
Merged
Conversation
aeon_cl45_read() ends with aeon_mdio_patch(), which issues __mdiobus_c45_write(bus, 30, 0x1, 0x1, 0x1); a write to PHY address 30 on whatever bus the phydev happens to live on. Nothing is at address 30. phylib calls match_phy_device() for every registered driver entry against every phydev, so aeon_gen1_read_pid() runs against PHYs that are not Aeonsemi parts - including the four internal GPY cores of an MxL86252C DSA switch, whose bus is the switch firmware's MDIO relay. There the write becomes an INT_GPHY_WRITE mailbox command for PHY 30, which the firmware rejects: mxl862xx mdio-bus:10: CMD 1802 returned error -19 On a BPI-R4 Pro that is 4 GPY cores x 12 match entries x 2 PID reads = 96 rejected commands on every boot. A read needs no flush: __mdiobus_c45_read() has already completed and dropped the bus lock when the patch write is issued. The mainline as21xxx driver performs the same identification and firmware load with no such write at all. Drop it from the read path. aeon_mdio_patch() is kept in aeon_cl45_write(), where the original workaround was reported to matter. After this change every remaining caller is reached only once a device has been confirmed to be an AS21xxx, so no foreign bus is touched. Signed-off-by: Mihai Ordean <research@mihaiordean.com>
aeon_gen1_match_phy_device() and aeon_gen2_match_phy_device() read the PHY ID out of every phydev phylib offers them, with no check that the device is an Aeonsemi part at all. phylib calls match_phy_device() for every registered driver entry against every phydev on every bus, so the driver issues C45 vendor register accesses to foreign PHYs. On a BPI-R4 Pro the four internal GPY cores of the MxL86252C sit on the switch firmware's MDIO relay, where each of those reads is a full mailbox transaction: write LEN_RET, write CTRL, poll for BUSY to clear, read CTRL and LEN_RET back. With 12 match entries (11 gen1, 1 gen2) and two PID reads each, that is 96 pointless mailbox commands - several thousand SMDIO frames - during PHY probing, delaying the switch setup that follows. The mainline as21xxx driver guards its match function with a vendor comparison and returns genphy_match_phy_device() for everything else. Do the same here. PHY_VENDOR_AEONSEMI is already defined and was previously unused. Signed-off-by: Mihai Ordean <research@mihaiordean.com>
frank-w
reviewed
Aug 2, 2026
| @@ -1484,7 +1480,17 @@ | |||
| static int aeon_gen1_match_phy_device(struct phy_device *phydev, | |||
Owner
There was a problem hiding this comment.
Great, this seems the rootcause of these phyad 30 errors on mxl bus which looked really strange. Thanks for it
Owner
There was a problem hiding this comment.
Looks like i catched the wrong line...meant the line with the read_pid before checking for aeonsemi phy
u32 phy_id = aeon_gen1_read_pid(phydev);
| } | ||
| ret = __mdiobus_c45_read(bus, phy_addr, dev_addr, phy_reg); | ||
| __mdiobus_c45_write(bus, 30, 0x1, 0x1, 0x1); |
Author
There was a problem hiding this comment.
yes. this can be removed too. good find. i can submit a patch later. want me to do it to this PR?
Owner
There was a problem hiding this comment.
i can do it on my own, just wanted your feedback here
Author
There was a problem hiding this comment.
ok. i've tested and works fine for me:
diff --git a/drivers/net/phy/as21xx_1.9.2/as21xxx.c b/drivers/net/phy/as21xx_1.9.2/as21xxx.c
index ed001d3..e595e10 100644
--- a/drivers/net/phy/as21xx_1.9.2/as21xxx.c
+++ b/drivers/net/phy/as21xx_1.9.2/as21xxx.c
@@ -539,7 +539,6 @@ static int aeon_mdio_read(struct phy_device *phydev, int dev_addr,
}
ret = __mdiobus_c45_read(bus, phy_addr, dev_addr, phy_reg);
- __mdiobus_c45_write(bus, 30, 0x1, 0x1, 0x1);
return ret;
}
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #201, which just silenced the symptom.
aeon_gen1_match_phy_device()callsaeon_gen1_read_pid(), which usesaeon_cl45_read(). That accessor ends with:A write to PHY address 30 — nothing is there.
phylib calls
match_phy_device()for every registered driver entry againstevery phydev on every bus. That includes the four internal GPY cores of the
MxL86252C at
mdio-bus:10-mii:00..03, whose bus is the switch firmware's MDIOrelay. There the patch write becomes an
INT_GPHY_WRITEmailbox command forPHY 30, which the firmware rejects:
CMD 1802isINT_GPHY_WRITE. The error is the patch write itself.Arithmetic
Measured on a BPI-R4 Pro boot where three of the four cores were present:
3 × 12 × 2 = 72. Exactly 72 observed.Timing on my device confirms it is the match path
The errors start 46 ms after the switch reports ready and run interleaved
with PHY binding. They cannot come from
mxl-gpy'sconfig_init, which iswhat #201 claimed — that runs after a PHY has bound.
Comparison with mainline
drivers/net/phy/as21xxx.cin this same tree has no__mdiobus_*calls, nomdio_lockmanipulation and no flush of any kind — all 24 register accesses gothrough
phy_{read,write,modify}_mmd(). It loads the same firmware andidentifies the same silicon without a patch write anywhere, which is good
evidence the flush is not a hardware requirement of this PHY.
Mainline also gates its match function before touching the bus:
The 1.9.2 vendor driver has neither protection, though it already defines
PHY_VENDOR_AEONSEMI(unused).The patches
1/2 — don't write to a nonexistent PHY after C45 reads. A read needs no
flush:
__mdiobus_c45_read()has already completed and dropped the bus lockwhen the patch write is issued.
aeon_mdio_patch()is kept inaeon_cl45_write(), where the original workaround was reported to matter.After this change every remaining caller is reached only once a device is
confirmed to be an AS21xxx, so no foreign bus is touched.
2/2 — only probe Aeonsemi PHYs when matching. Brings the vendor driver in
line with mainline. This removes the PID reads themselves — each one a full
mailbox round-trip (write LEN_RET, write CTRL, poll BUSY, read back).