[RFC net-next PATCH 16/16] net: sfp: Add quirk to ignore PHYs

From: Sean Anderson
Date: Mon Oct 04 2021 - 15:17:40 EST


Some modules have something at SFP_PHY_ADDR which isn't a PHY. If we try to
probe it, we might attach genphy anyway if addresses 2 and 3 return
something other than all 1s. To avoid this, add a quirk for these modules
so that we do not probe their PHY.

The particular module in this case is a Finisar SFP-GB-GE-T. This module is
also worked around in xgbe_phy_finisar_phy_quirks() by setting the support
manually. However, I do not believe that it has a PHY in the first place:

$ i2cdump -y -r 0-31 $BUS 0x56 w
0,8 1,9 2,a 3,b 4,c 5,d 6,e 7,f
00: ff01 ff01 ff01 c20c 010c 01c0 0f00 0120
08: fc48 000e ff78 0000 0000 0000 0000 00f0
10: 7800 00bc 0000 401c 680c 0300 0000 0000
18: ff41 0000 0a00 8890 0000 0000 0000 0000

The first several addresses contain the same value, which should almost
never be the case for a proper phy. In addition, the "OUI" 00-7F-C3 does
not match Finisar's OUI of 00-90-65 (or any other OUI for that matter).

Signed-off-by: Sean Anderson <sean.anderson@xxxxxxxx>
---

drivers/net/phy/sfp-bus.c | 12 +++++++++++-
drivers/net/phy/sfp.c | 3 +++
2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c
index 7362f8c3271c..0b79893a79ea 100644
--- a/drivers/net/phy/sfp-bus.c
+++ b/drivers/net/phy/sfp-bus.c
@@ -14,6 +14,7 @@ struct sfp_quirk {
const char *vendor;
const char *part;
void (*modes)(const struct sfp_eeprom_id *id, unsigned long *modes);
+ bool ignore_phy;
};

/**
@@ -68,6 +69,12 @@ static const struct sfp_quirk sfp_quirks[] = {
.vendor = "ALCATELLUCENT",
.part = "3FE46541AA",
.modes = sfp_quirk_2500basex,
+ }, {
+ // Finisar SFP-GB-GE-T has something on its I2C bus at
+ // SFP_PHY_ADDR, but it is not a (c22-compliant) phy
+ .vendor = "FS",
+ .part = "SFP-GB-GE-T",
+ .ignore_phy = true,
}, {
// Huawei MA5671A can operate at 2500base-X, but report 1.2GBd
// NRZ in their EEPROM
@@ -204,6 +211,9 @@ EXPORT_SYMBOL_GPL(sfp_parse_port);
*/
bool sfp_may_have_phy(struct sfp_bus *bus, const struct sfp_eeprom_id *id)
{
+ if (bus->sfp_quirk && bus->sfp_quirk->ignore_phy)
+ return false;
+
if (id->base.e1000_base_t)
return true;

@@ -370,7 +380,7 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
phylink_set(modes, 2500baseX_Full);
}

- if (bus->sfp_quirk)
+ if (bus->sfp_quirk && bus->sfp_quirk->modes)
bus->sfp_quirk->modes(id, modes);

bitmap_or(support, support, modes, __ETHTOOL_LINK_MODE_MASK_NBITS);
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index ab77a9f439ef..35c414eb1ecb 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -1512,6 +1512,9 @@ static int sfp_sm_probe_phy(struct sfp *sfp, bool is_c45)
struct phy_device *phy;
int err;

+ if (!sfp_may_have_phy(sfp->sfp_bus, &sfp->id))
+ return 0;
+
phy = get_phy_device(sfp->i2c_mii, SFP_PHY_ADDR, is_c45);
if (phy == ERR_PTR(-ENODEV))
return PTR_ERR(phy);
--
2.25.1