[PATCH net-next] net: sfp: add quirk for ZYXEL PMG3000-D20B
From: Martin Ostertag
Date: Mon Oct 26 2026 - 09:59:11 EST
The ZYXEL PMG3000-D20B GPON SFP module reports LOS and TX_FAULT in a
way that prevents the SFP state machine from initialising it. Its
EEPROM also advertises autonegotiation support although the module does
not implement it, and the module needs about 60 seconds before it is
ready.
Ignore LOS and TX_FAULT, disable the advertised autonegotiation and use
T_START_UP_BAD_GPON as the wait time before the module is assumed to be
initialised.
Tested with a ZYXEL PMG3000-D20B in an SFP cage.
Signed-off-by: Martin Ostertag <martin.ostertag@xxxxxx>
---
drivers/net/phy/sfp.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index 85e57a1..578d4d8 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -472,6 +472,18 @@ static void sfp_fixup_potron(struct sfp *sfp)
sfp_fixup_ignore_hw(sfp, SFP_F_TX_FAULT | SFP_F_LOS);
}
+static void sfp_fixup_zyxel(struct sfp *sfp)
+{
+ /*
+ * The LOS and TX_FAULT signals are not usable on this module, so
+ * ignore them. It also needs about 60s to become ready. Use
+ * module_t_wait, as module_t_start_up is not evaluated when
+ * TX_FAULT is ignored.
+ */
+ sfp_fixup_ignore_tx_fault_and_los(sfp);
+ sfp->module_t_wait = T_START_UP_BAD_GPON;
+}
+
static void sfp_fixup_rollball_cc(struct sfp *sfp)
{
sfp_fixup_rollball(sfp);
@@ -654,6 +666,10 @@ static const struct sfp_quirk sfp_quirks[] = {
SFP_QUIRK_F("XikeStor", "SKT-2.5G-100M", sfp_fixup_xikestor_2_5g),
SFP_QUIRK_S("ZOERAX", "SFP-2.5G-T", sfp_quirk_oem_2_5g),
+
+ /* The module advertises autonegotiation it does not support. */
+ SFP_QUIRK("ZYXEL", "PMG3000-D20B", sfp_quirk_disable_autoneg,
+ sfp_fixup_zyxel),
};
static size_t sfp_strlen(const char *str, size_t maxlen)
--
2.56.0