* [PATCH net-next 1/7] net: phy: add phy_interface_copy()
2025-09-15 13:16 [PATCH net-next 0/7] net: rework SFP capability parsing and quirks Russell King (Oracle)
@ 2025-09-15 13:31 ` Russell King (Oracle)
2025-09-15 15:05 ` Andrew Lunn
2025-09-15 13:31 ` [PATCH net-next 2/7] net: sfp: pre-parse the module support Russell King (Oracle)
` (5 subsequent siblings)
6 siblings, 1 reply; 12+ messages in thread
From: Russell King (Oracle) @ 2025-09-15 13:31 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, linux-arm-msm,
Marek Beh__n, netdev, Paolo Abeni
Add a helper for copying PHY interface bitmasks. This will be used by
the SFP bus code, which will then be moved to phylink in the subsequent
patches.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
include/linux/phy.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 04553419adc3..407dae517b2e 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -169,6 +169,11 @@ static inline bool phy_interface_empty(const unsigned long *intf)
return bitmap_empty(intf, PHY_INTERFACE_MODE_MAX);
}
+static inline void phy_interface_copy(unsigned long *d, const unsigned long *s)
+{
+ bitmap_copy(d, s, PHY_INTERFACE_MODE_MAX);
+}
+
static inline unsigned int phy_interface_weight(const unsigned long *intf)
{
return bitmap_weight(intf, PHY_INTERFACE_MODE_MAX);
--
2.47.3
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PATCH net-next 1/7] net: phy: add phy_interface_copy()
2025-09-15 13:31 ` [PATCH net-next 1/7] net: phy: add phy_interface_copy() Russell King (Oracle)
@ 2025-09-15 15:05 ` Andrew Lunn
0 siblings, 0 replies; 12+ messages in thread
From: Andrew Lunn @ 2025-09-15 15:05 UTC (permalink / raw)
To: Russell King (Oracle)
Cc: Heiner Kallweit, David S. Miller, Eric Dumazet, Jakub Kicinski,
linux-arm-msm, Marek Beh__n, netdev, Paolo Abeni
On Mon, Sep 15, 2025 at 02:31:45PM +0100, Russell King (Oracle) wrote:
> Add a helper for copying PHY interface bitmasks. This will be used by
> the SFP bus code, which will then be moved to phylink in the subsequent
> patches.
>
> Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH net-next 2/7] net: sfp: pre-parse the module support
2025-09-15 13:16 [PATCH net-next 0/7] net: rework SFP capability parsing and quirks Russell King (Oracle)
2025-09-15 13:31 ` [PATCH net-next 1/7] net: phy: add phy_interface_copy() Russell King (Oracle)
@ 2025-09-15 13:31 ` Russell King (Oracle)
2025-09-15 15:12 ` Andrew Lunn
2025-09-15 13:31 ` [PATCH net-next 3/7] net: sfp: convert sfp quirks to modify struct sfp_module_support Russell King (Oracle)
` (4 subsequent siblings)
6 siblings, 1 reply; 12+ messages in thread
From: Russell King (Oracle) @ 2025-09-15 13:31 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, linux-arm-msm,
Marek Beh__n, netdev, Paolo Abeni
Pre-parse the module support on insert rather than when the upstream
requests the data. This will allow more flexible and extensible
parsing.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/phy/sfp-bus.c | 80 +++++++++++++++++++++++++++------------
include/linux/sfp.h | 22 +++++++++++
2 files changed, 77 insertions(+), 25 deletions(-)
diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c
index f13c00b5b449..18e5d3de63a8 100644
--- a/drivers/net/phy/sfp-bus.c
+++ b/drivers/net/phy/sfp-bus.c
@@ -22,7 +22,6 @@ struct sfp_bus {
const struct sfp_socket_ops *socket_ops;
struct device *sfp_dev;
struct sfp *sfp;
- const struct sfp_quirk *sfp_quirk;
const struct sfp_upstream_ops *upstream_ops;
void *upstream;
@@ -30,6 +29,8 @@ struct sfp_bus {
bool registered;
bool started;
+
+ struct sfp_module_caps caps;
};
/**
@@ -48,6 +49,13 @@ struct sfp_bus {
*/
int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
unsigned long *support)
+{
+ return bus->caps.port;
+}
+EXPORT_SYMBOL_GPL(sfp_parse_port);
+
+static void sfp_module_parse_port(struct sfp_bus *bus,
+ const struct sfp_eeprom_id *id)
{
int port;
@@ -91,21 +99,18 @@ int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
break;
}
- if (support) {
- switch (port) {
- case PORT_FIBRE:
- phylink_set(support, FIBRE);
- break;
+ switch (port) {
+ case PORT_FIBRE:
+ phylink_set(bus->caps.link_modes, FIBRE);
+ break;
- case PORT_TP:
- phylink_set(support, TP);
- break;
- }
+ case PORT_TP:
+ phylink_set(bus->caps.link_modes, TP);
+ break;
}
- return port;
+ bus->caps.port = port;
}
-EXPORT_SYMBOL_GPL(sfp_parse_port);
/**
* sfp_may_have_phy() - indicate whether the module may have a PHY
@@ -117,8 +122,17 @@ EXPORT_SYMBOL_GPL(sfp_parse_port);
*/
bool sfp_may_have_phy(struct sfp_bus *bus, const struct sfp_eeprom_id *id)
{
- if (id->base.e1000_base_t)
- return true;
+ return bus->caps.may_have_phy;
+}
+EXPORT_SYMBOL_GPL(sfp_may_have_phy);
+
+static void sfp_module_may_have_phy(struct sfp_bus *bus,
+ const struct sfp_eeprom_id *id)
+{
+ if (id->base.e1000_base_t) {
+ bus->caps.may_have_phy = true;
+ return;
+ }
if (id->base.phys_id != SFF8024_ID_DWDM_SFP) {
switch (id->base.extended_cc) {
@@ -126,13 +140,13 @@ bool sfp_may_have_phy(struct sfp_bus *bus, const struct sfp_eeprom_id *id)
case SFF8024_ECC_10GBASE_T_SR:
case SFF8024_ECC_5GBASE_T:
case SFF8024_ECC_2_5GBASE_T:
- return true;
+ bus->caps.may_have_phy = true;
+ return;
}
}
- return false;
+ bus->caps.may_have_phy = false;
}
-EXPORT_SYMBOL_GPL(sfp_may_have_phy);
/**
* sfp_parse_support() - Parse the eeprom id for supported link modes
@@ -148,8 +162,17 @@ EXPORT_SYMBOL_GPL(sfp_may_have_phy);
void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
unsigned long *support, unsigned long *interfaces)
{
+ linkmode_or(support, support, bus->caps.link_modes);
+ phy_interface_copy(interfaces, bus->caps.interfaces);
+}
+EXPORT_SYMBOL_GPL(sfp_parse_support);
+
+static void sfp_module_parse_support(struct sfp_bus *bus,
+ const struct sfp_eeprom_id *id)
+{
+ unsigned long *interfaces = bus->caps.interfaces;
+ unsigned long *modes = bus->caps.link_modes;
unsigned int br_min, br_nom, br_max;
- __ETHTOOL_DECLARE_LINK_MODE_MASK(modes) = { 0, };
/* Decode the bitrate information to MBd */
br_min = br_nom = br_max = 0;
@@ -338,13 +361,22 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
phylink_set(modes, Autoneg);
phylink_set(modes, Pause);
phylink_set(modes, Asym_Pause);
+}
+
+static void sfp_init_module(struct sfp_bus *bus,
+ const struct sfp_eeprom_id *id,
+ const struct sfp_quirk *quirk)
+{
+ memset(&bus->caps, 0, sizeof(bus->caps));
- if (bus->sfp_quirk && bus->sfp_quirk->modes)
- bus->sfp_quirk->modes(id, modes, interfaces);
+ sfp_module_parse_support(bus, id);
+ sfp_module_parse_port(bus, id);
+ sfp_module_may_have_phy(bus, id);
- linkmode_or(support, support, modes);
+ if (quirk && quirk->modes)
+ quirk->modes(id, bus->caps.link_modes,
+ bus->caps.interfaces);
}
-EXPORT_SYMBOL_GPL(sfp_parse_support);
/**
* sfp_select_interface() - Select appropriate phy_interface_t mode
@@ -794,7 +826,7 @@ int sfp_module_insert(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
int ret = 0;
- bus->sfp_quirk = quirk;
+ sfp_init_module(bus, id, quirk);
if (ops && ops->module_insert)
ret = ops->module_insert(bus->upstream, id);
@@ -809,8 +841,6 @@ void sfp_module_remove(struct sfp_bus *bus)
if (ops && ops->module_remove)
ops->module_remove(bus->upstream);
-
- bus->sfp_quirk = NULL;
}
EXPORT_SYMBOL_GPL(sfp_module_remove);
diff --git a/include/linux/sfp.h b/include/linux/sfp.h
index 60c65cea74f6..5fb59cf49882 100644
--- a/include/linux/sfp.h
+++ b/include/linux/sfp.h
@@ -521,6 +521,28 @@ struct ethtool_eeprom;
struct ethtool_modinfo;
struct sfp_bus;
+/**
+ * struct sfp_module_caps - sfp module capabilities
+ * @interfaces: bitmap of interfaces that the module may support
+ * @link_modes: bitmap of ethtool link modes that the module may support
+ */
+struct sfp_module_caps {
+ DECLARE_PHY_INTERFACE_MASK(interfaces);
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(link_modes);
+ /**
+ * @may_have_phy: indicate whether the module may have an ethernet PHY
+ * There is no way to be sure that a module has a PHY as the EEPROM
+ * doesn't contain this information. When set, this does not mean that
+ * the module definitely has a PHY.
+ */
+ bool may_have_phy;
+ /**
+ * @port: one of ethtool %PORT_* definitions, parsed from the module
+ * EEPROM, or %PORT_OTHER if the port type is not known.
+ */
+ u8 port;
+};
+
/**
* struct sfp_upstream_ops - upstream operations structure
* @attach: called when the sfp socket driver is bound to the upstream
--
2.47.3
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PATCH net-next 2/7] net: sfp: pre-parse the module support
2025-09-15 13:31 ` [PATCH net-next 2/7] net: sfp: pre-parse the module support Russell King (Oracle)
@ 2025-09-15 15:12 ` Andrew Lunn
2025-09-16 21:42 ` Russell King (Oracle)
0 siblings, 1 reply; 12+ messages in thread
From: Andrew Lunn @ 2025-09-15 15:12 UTC (permalink / raw)
To: Russell King (Oracle)
Cc: Heiner Kallweit, David S. Miller, Eric Dumazet, Jakub Kicinski,
linux-arm-msm, Marek Beh__n, netdev, Paolo Abeni
> +static void sfp_module_may_have_phy(struct sfp_bus *bus,
> + const struct sfp_eeprom_id *id)
> +{
_may_have_phy() sounds like a question, and you would expect a return
value as the answer. But that is not what this does.
Maybe sfp_module_set_may_have_phy()?
Andrew
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [PATCH net-next 2/7] net: sfp: pre-parse the module support
2025-09-15 15:12 ` Andrew Lunn
@ 2025-09-16 21:42 ` Russell King (Oracle)
0 siblings, 0 replies; 12+ messages in thread
From: Russell King (Oracle) @ 2025-09-16 21:42 UTC (permalink / raw)
To: Andrew Lunn
Cc: Heiner Kallweit, David S. Miller, Eric Dumazet, Jakub Kicinski,
linux-arm-msm, Marek Beh__n, netdev, Paolo Abeni
On Mon, Sep 15, 2025 at 05:12:19PM +0200, Andrew Lunn wrote:
> > +static void sfp_module_may_have_phy(struct sfp_bus *bus,
> > + const struct sfp_eeprom_id *id)
> > +{
>
> _may_have_phy() sounds like a question, and you would expect a return
> value as the answer. But that is not what this does.
>
> Maybe sfp_module_set_may_have_phy()?
I'll stick a parse_ in there rather than set_ so it matches all the
others which are parsing the SFP ID to obtain something.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH net-next 3/7] net: sfp: convert sfp quirks to modify struct sfp_module_support
2025-09-15 13:16 [PATCH net-next 0/7] net: rework SFP capability parsing and quirks Russell King (Oracle)
2025-09-15 13:31 ` [PATCH net-next 1/7] net: phy: add phy_interface_copy() Russell King (Oracle)
2025-09-15 13:31 ` [PATCH net-next 2/7] net: sfp: pre-parse the module support Russell King (Oracle)
@ 2025-09-15 13:31 ` Russell King (Oracle)
2025-09-15 13:32 ` [PATCH net-next 4/7] net: sfp: provide sfp_get_module_caps() Russell King (Oracle)
` (3 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: Russell King (Oracle) @ 2025-09-15 13:31 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, linux-arm-msm,
Marek Beh__n, netdev, Paolo Abeni
In order to provide extensible module support properties, arrange for
the SFP quirks to modify any member of the sfp_module_support struct,
rather than just the ethtool link modes and interfaces.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/phy/sfp-bus.c | 5 ++--
drivers/net/phy/sfp.c | 49 +++++++++++++++++++--------------------
drivers/net/phy/sfp.h | 4 ++--
3 files changed, 28 insertions(+), 30 deletions(-)
diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c
index 18e5d3de63a8..b7275ecdf19b 100644
--- a/drivers/net/phy/sfp-bus.c
+++ b/drivers/net/phy/sfp-bus.c
@@ -373,9 +373,8 @@ static void sfp_init_module(struct sfp_bus *bus,
sfp_module_parse_port(bus, id);
sfp_module_may_have_phy(bus, id);
- if (quirk && quirk->modes)
- quirk->modes(id, bus->caps.link_modes,
- bus->caps.interfaces);
+ if (quirk && quirk->support)
+ quirk->support(id, &bus->caps);
}
/**
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index 4cd1d6c51dc2..d49f91ac2e50 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -440,45 +440,44 @@ static void sfp_fixup_rollball_cc(struct sfp *sfp)
}
static void sfp_quirk_2500basex(const struct sfp_eeprom_id *id,
- unsigned long *modes,
- unsigned long *interfaces)
+ struct sfp_module_caps *caps)
{
- linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, modes);
- __set_bit(PHY_INTERFACE_MODE_2500BASEX, interfaces);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
+ caps->link_modes);
+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, caps->interfaces);
}
static void sfp_quirk_disable_autoneg(const struct sfp_eeprom_id *id,
- unsigned long *modes,
- unsigned long *interfaces)
+ struct sfp_module_caps *caps)
{
- linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, modes);
+ linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, caps->link_modes);
}
static void sfp_quirk_oem_2_5g(const struct sfp_eeprom_id *id,
- unsigned long *modes,
- unsigned long *interfaces)
+ struct sfp_module_caps *caps)
{
/* Copper 2.5G SFP */
- linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, modes);
- __set_bit(PHY_INTERFACE_MODE_2500BASEX, interfaces);
- sfp_quirk_disable_autoneg(id, modes, interfaces);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
+ caps->link_modes);
+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, caps->interfaces);
+ sfp_quirk_disable_autoneg(id, caps);
}
static void sfp_quirk_ubnt_uf_instant(const struct sfp_eeprom_id *id,
- unsigned long *modes,
- unsigned long *interfaces)
+ struct sfp_module_caps *caps)
{
/* Ubiquiti U-Fiber Instant module claims that support all transceiver
* types including 10G Ethernet which is not truth. So clear all claimed
* modes and set only one mode which module supports: 1000baseX_Full.
*/
- linkmode_zero(modes);
- linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, modes);
+ linkmode_zero(caps->link_modes);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
+ caps->link_modes);
}
-#define SFP_QUIRK(_v, _p, _m, _f) \
- { .vendor = _v, .part = _p, .modes = _m, .fixup = _f, }
-#define SFP_QUIRK_M(_v, _p, _m) SFP_QUIRK(_v, _p, _m, NULL)
+#define SFP_QUIRK(_v, _p, _s, _f) \
+ { .vendor = _v, .part = _p, .support = _s, .fixup = _f, }
+#define SFP_QUIRK_S(_v, _p, _s) SFP_QUIRK(_v, _p, _s, NULL)
#define SFP_QUIRK_F(_v, _p, _f) SFP_QUIRK(_v, _p, NULL, _f)
static const struct sfp_quirk sfp_quirks[] = {
@@ -514,7 +513,7 @@ static const struct sfp_quirk sfp_quirks[] = {
// HG MXPD-483II-F 2.5G supports 2500Base-X, but incorrectly reports
// 2600MBd in their EERPOM
- SFP_QUIRK_M("HG GENUINE", "MXPD-483II", sfp_quirk_2500basex),
+ SFP_QUIRK_S("HG GENUINE", "MXPD-483II", sfp_quirk_2500basex),
// Huawei MA5671A can operate at 2500base-X, but report 1.2GBd NRZ in
// their EEPROM
@@ -523,9 +522,9 @@ static const struct sfp_quirk sfp_quirks[] = {
// Lantech 8330-262D-E can operate at 2500base-X, but incorrectly report
// 2500MBd NRZ in their EEPROM
- SFP_QUIRK_M("Lantech", "8330-262D-E", sfp_quirk_2500basex),
+ SFP_QUIRK_S("Lantech", "8330-262D-E", sfp_quirk_2500basex),
- SFP_QUIRK_M("UBNT", "UF-INSTANT", sfp_quirk_ubnt_uf_instant),
+ SFP_QUIRK_S("UBNT", "UF-INSTANT", sfp_quirk_ubnt_uf_instant),
// Walsun HXSX-ATR[CI]-1 don't identify as copper, and use the
// Rollball protocol to talk to the PHY.
@@ -538,9 +537,9 @@ static const struct sfp_quirk sfp_quirks[] = {
SFP_QUIRK_F("OEM", "SFP-GE-T", sfp_fixup_ignore_tx_fault),
SFP_QUIRK_F("OEM", "SFP-10G-T", sfp_fixup_rollball_cc),
- SFP_QUIRK_M("OEM", "SFP-2.5G-T", sfp_quirk_oem_2_5g),
- SFP_QUIRK_M("OEM", "SFP-2.5G-BX10-D", sfp_quirk_2500basex),
- SFP_QUIRK_M("OEM", "SFP-2.5G-BX10-U", sfp_quirk_2500basex),
+ SFP_QUIRK_S("OEM", "SFP-2.5G-T", sfp_quirk_oem_2_5g),
+ SFP_QUIRK_S("OEM", "SFP-2.5G-BX10-D", sfp_quirk_2500basex),
+ SFP_QUIRK_S("OEM", "SFP-2.5G-BX10-U", sfp_quirk_2500basex),
SFP_QUIRK_F("OEM", "RTSFP-10", sfp_fixup_rollball_cc),
SFP_QUIRK_F("OEM", "RTSFP-10G", sfp_fixup_rollball_cc),
SFP_QUIRK_F("Turris", "RTSFP-2.5G", sfp_fixup_rollball),
diff --git a/drivers/net/phy/sfp.h b/drivers/net/phy/sfp.h
index 1fd097dccb9f..879dff7afe6a 100644
--- a/drivers/net/phy/sfp.h
+++ b/drivers/net/phy/sfp.h
@@ -9,8 +9,8 @@ struct sfp;
struct sfp_quirk {
const char *vendor;
const char *part;
- void (*modes)(const struct sfp_eeprom_id *id, unsigned long *modes,
- unsigned long *interfaces);
+ void (*support)(const struct sfp_eeprom_id *id,
+ struct sfp_module_caps *caps);
void (*fixup)(struct sfp *sfp);
};
--
2.47.3
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH net-next 4/7] net: sfp: provide sfp_get_module_caps()
2025-09-15 13:16 [PATCH net-next 0/7] net: rework SFP capability parsing and quirks Russell King (Oracle)
` (2 preceding siblings ...)
2025-09-15 13:31 ` [PATCH net-next 3/7] net: sfp: convert sfp quirks to modify struct sfp_module_support Russell King (Oracle)
@ 2025-09-15 13:32 ` Russell King (Oracle)
2025-09-15 13:32 ` [PATCH net-next 5/7] net: phylink: use sfp_get_module_caps() Russell King (Oracle)
` (2 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: Russell King (Oracle) @ 2025-09-15 13:32 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, linux-arm-msm,
Marek Beh__n, netdev, Paolo Abeni
Provide a function to retrieve the current sfp_module_caps structure
so that upstreams can get the entire module support in one go.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/phy/sfp-bus.c | 6 ++++++
include/linux/sfp.h | 7 +++++++
2 files changed, 13 insertions(+)
diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c
index b7275ecdf19b..f409943f1952 100644
--- a/drivers/net/phy/sfp-bus.c
+++ b/drivers/net/phy/sfp-bus.c
@@ -33,6 +33,12 @@ struct sfp_bus {
struct sfp_module_caps caps;
};
+const struct sfp_module_caps *sfp_get_module_caps(struct sfp_bus *bus)
+{
+ return &bus->caps;
+}
+EXPORT_SYMBOL_GPL(sfp_get_module_caps);
+
/**
* sfp_parse_port() - Parse the EEPROM base ID, setting the port type
* @bus: a pointer to the &struct sfp_bus structure for the sfp module
diff --git a/include/linux/sfp.h b/include/linux/sfp.h
index 5fb59cf49882..9f29fcad52be 100644
--- a/include/linux/sfp.h
+++ b/include/linux/sfp.h
@@ -576,6 +576,7 @@ struct sfp_upstream_ops {
};
#if IS_ENABLED(CONFIG_SFP)
+const struct sfp_module_caps *sfp_get_module_caps(struct sfp_bus *bus);
int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
unsigned long *support);
bool sfp_may_have_phy(struct sfp_bus *bus, const struct sfp_eeprom_id *id);
@@ -600,6 +601,12 @@ int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream,
void sfp_bus_del_upstream(struct sfp_bus *bus);
const char *sfp_get_name(struct sfp_bus *bus);
#else
+static inline const struct sfp_module_caps *
+sfp_get_module_caps(struct sfp_bus *bus)
+{
+ return NULL;
+}
+
static inline int sfp_parse_port(struct sfp_bus *bus,
const struct sfp_eeprom_id *id,
unsigned long *support)
--
2.47.3
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH net-next 5/7] net: phylink: use sfp_get_module_caps()
2025-09-15 13:16 [PATCH net-next 0/7] net: rework SFP capability parsing and quirks Russell King (Oracle)
` (3 preceding siblings ...)
2025-09-15 13:32 ` [PATCH net-next 4/7] net: sfp: provide sfp_get_module_caps() Russell King (Oracle)
@ 2025-09-15 13:32 ` Russell King (Oracle)
2025-09-15 13:32 ` [PATCH net-next 6/7] net: phy: update all PHYs to " Russell King (Oracle)
2025-09-15 13:32 ` [PATCH net-next 7/7] net: sfp: remove old sfp_parse_* functions Russell King (Oracle)
6 siblings, 0 replies; 12+ messages in thread
From: Russell King (Oracle) @ 2025-09-15 13:32 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, linux-arm-msm,
Marek Beh__n, netdev, Paolo Abeni
Use sfp_get_module_caps() to get SFP module's capabilities.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/phy/phylink.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 1988b7d2089a..0c2b7538e492 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -3747,17 +3747,18 @@ static int phylink_sfp_config_optical(struct phylink *pl)
static int phylink_sfp_module_insert(void *upstream,
const struct sfp_eeprom_id *id)
{
+ const struct sfp_module_caps *caps;
struct phylink *pl = upstream;
ASSERT_RTNL();
- linkmode_zero(pl->sfp_support);
- phy_interface_zero(pl->sfp_interfaces);
- sfp_parse_support(pl->sfp_bus, id, pl->sfp_support, pl->sfp_interfaces);
- pl->sfp_port = sfp_parse_port(pl->sfp_bus, id, pl->sfp_support);
+ caps = sfp_get_module_caps(pl->sfp_bus);
+ phy_interface_copy(pl->sfp_interfaces, caps->interfaces);
+ linkmode_copy(pl->sfp_support, caps->link_modes);
+ pl->sfp_may_have_phy = caps->may_have_phy;
+ pl->sfp_port = caps->port;
/* If this module may have a PHY connecting later, defer until later */
- pl->sfp_may_have_phy = sfp_may_have_phy(pl->sfp_bus, id);
if (pl->sfp_may_have_phy)
return 0;
--
2.47.3
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH net-next 6/7] net: phy: update all PHYs to use sfp_get_module_caps()
2025-09-15 13:16 [PATCH net-next 0/7] net: rework SFP capability parsing and quirks Russell King (Oracle)
` (4 preceding siblings ...)
2025-09-15 13:32 ` [PATCH net-next 5/7] net: phylink: use sfp_get_module_caps() Russell King (Oracle)
@ 2025-09-15 13:32 ` Russell King (Oracle)
2025-09-15 13:32 ` [PATCH net-next 7/7] net: sfp: remove old sfp_parse_* functions Russell King (Oracle)
6 siblings, 0 replies; 12+ messages in thread
From: Russell King (Oracle) @ 2025-09-15 13:32 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, linux-arm-msm,
Marek Beh__n, netdev, Paolo Abeni
Update all PHYs to use sfp_get_module_caps() rather than the
sfp_parse_*() family of functions.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/phy/marvell-88x2222.c | 13 ++++++-------
drivers/net/phy/marvell.c | 8 +++-----
drivers/net/phy/marvell10g.c | 7 +++----
drivers/net/phy/qcom/at803x.c | 9 ++++-----
drivers/net/phy/qcom/qca807x.c | 7 +++----
5 files changed, 19 insertions(+), 25 deletions(-)
diff --git a/drivers/net/phy/marvell-88x2222.c b/drivers/net/phy/marvell-88x2222.c
index fad2f54c1eac..894bcee61e65 100644
--- a/drivers/net/phy/marvell-88x2222.c
+++ b/drivers/net/phy/marvell-88x2222.c
@@ -475,21 +475,20 @@ static int mv2222_config_init(struct phy_device *phydev)
static int mv2222_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
{
- DECLARE_PHY_INTERFACE_MASK(interfaces);
struct phy_device *phydev = upstream;
+ const struct sfp_module_caps *caps;
phy_interface_t sfp_interface;
struct mv2222_data *priv;
struct device *dev;
int ret;
- __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_supported) = { 0, };
-
priv = phydev->priv;
dev = &phydev->mdio.dev;
- sfp_parse_support(phydev->sfp_bus, id, sfp_supported, interfaces);
- phydev->port = sfp_parse_port(phydev->sfp_bus, id, sfp_supported);
- sfp_interface = sfp_select_interface(phydev->sfp_bus, sfp_supported);
+ caps = sfp_get_module_caps(phydev->sfp_bus);
+
+ phydev->port = caps->port;
+ sfp_interface = sfp_select_interface(phydev->sfp_bus, caps->link_modes);
dev_info(dev, "%s SFP module inserted\n", phy_modes(sfp_interface));
@@ -502,7 +501,7 @@ static int mv2222_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
}
priv->line_interface = sfp_interface;
- linkmode_and(priv->supported, phydev->supported, sfp_supported);
+ linkmode_and(priv->supported, phydev->supported, caps->link_modes);
ret = mv2222_config_line(phydev);
if (ret < 0)
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 0ea366c1217e..c248c90510ae 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -3600,20 +3600,18 @@ static int marvell_probe(struct phy_device *phydev)
static int m88e1510_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
{
- DECLARE_PHY_INTERFACE_MASK(interfaces);
struct phy_device *phydev = upstream;
+ const struct sfp_module_caps *caps;
phy_interface_t interface;
struct device *dev;
int oldpage;
int ret = 0;
u16 mode;
- __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, };
-
dev = &phydev->mdio.dev;
- sfp_parse_support(phydev->sfp_bus, id, supported, interfaces);
- interface = sfp_select_interface(phydev->sfp_bus, supported);
+ caps = sfp_get_module_caps(phydev->sfp_bus);
+ interface = sfp_select_interface(phydev->sfp_bus, caps->link_modes);
dev_info(dev, "%s SFP module inserted\n", phy_modes(interface));
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
index 13e81dff42c1..8fd42131cdbf 100644
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -466,12 +466,11 @@ static int mv3310_set_edpd(struct phy_device *phydev, u16 edpd)
static int mv3310_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
{
struct phy_device *phydev = upstream;
- __ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, };
- DECLARE_PHY_INTERFACE_MASK(interfaces);
+ const struct sfp_module_caps *caps;
phy_interface_t iface;
- sfp_parse_support(phydev->sfp_bus, id, support, interfaces);
- iface = sfp_select_interface(phydev->sfp_bus, support);
+ caps = sfp_get_module_caps(phydev->sfp_bus);
+ iface = sfp_select_interface(phydev->sfp_bus, caps->link_modes);
if (iface != PHY_INTERFACE_MODE_10GBASER) {
dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n");
diff --git a/drivers/net/phy/qcom/at803x.c b/drivers/net/phy/qcom/at803x.c
index 51a132242462..338acd11a9b6 100644
--- a/drivers/net/phy/qcom/at803x.c
+++ b/drivers/net/phy/qcom/at803x.c
@@ -771,10 +771,10 @@ static int at8031_register_regulators(struct phy_device *phydev)
static int at8031_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
{
- struct phy_device *phydev = upstream;
__ETHTOOL_DECLARE_LINK_MODE_MASK(phy_support);
__ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support);
- DECLARE_PHY_INTERFACE_MASK(interfaces);
+ struct phy_device *phydev = upstream;
+ const struct sfp_module_caps *caps;
phy_interface_t iface;
linkmode_zero(phy_support);
@@ -784,12 +784,11 @@ static int at8031_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
phylink_set(phy_support, Pause);
phylink_set(phy_support, Asym_Pause);
- linkmode_zero(sfp_support);
- sfp_parse_support(phydev->sfp_bus, id, sfp_support, interfaces);
+ caps = sfp_get_module_caps(phydev->sfp_bus);
/* Some modules support 10G modes as well as others we support.
* Mask out non-supported modes so the correct interface is picked.
*/
- linkmode_and(sfp_support, phy_support, sfp_support);
+ linkmode_and(sfp_support, phy_support, caps->link_modes);
if (linkmode_empty(sfp_support)) {
dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n");
diff --git a/drivers/net/phy/qcom/qca807x.c b/drivers/net/phy/qcom/qca807x.c
index 070dc8c00835..1be8295a95cb 100644
--- a/drivers/net/phy/qcom/qca807x.c
+++ b/drivers/net/phy/qcom/qca807x.c
@@ -646,13 +646,12 @@ static int qca807x_phy_package_config_init_once(struct phy_device *phydev)
static int qca807x_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
{
struct phy_device *phydev = upstream;
- __ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, };
+ const struct sfp_module_caps *caps;
phy_interface_t iface;
int ret;
- DECLARE_PHY_INTERFACE_MASK(interfaces);
- sfp_parse_support(phydev->sfp_bus, id, support, interfaces);
- iface = sfp_select_interface(phydev->sfp_bus, support);
+ caps = sfp_get_module_caps(phydev->sfp_bus);
+ iface = sfp_select_interface(phydev->sfp_bus, caps->link_modes);
dev_info(&phydev->mdio.dev, "%s SFP module inserted\n", phy_modes(iface));
--
2.47.3
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH net-next 7/7] net: sfp: remove old sfp_parse_* functions
2025-09-15 13:16 [PATCH net-next 0/7] net: rework SFP capability parsing and quirks Russell King (Oracle)
` (5 preceding siblings ...)
2025-09-15 13:32 ` [PATCH net-next 6/7] net: phy: update all PHYs to " Russell King (Oracle)
@ 2025-09-15 13:32 ` Russell King (Oracle)
6 siblings, 0 replies; 12+ messages in thread
From: Russell King (Oracle) @ 2025-09-15 13:32 UTC (permalink / raw)
To: Andrew Lunn, Heiner Kallweit
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, linux-arm-msm,
Marek Beh__n, netdev, Paolo Abeni
Remove the old sfp_parse_*() functions that are now no longer used.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/phy/sfp-bus.c | 54 ---------------------------------------
include/linux/sfp.h | 25 ------------------
2 files changed, 79 deletions(-)
diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c
index f409943f1952..4664df08e3a6 100644
--- a/drivers/net/phy/sfp-bus.c
+++ b/drivers/net/phy/sfp-bus.c
@@ -39,27 +39,6 @@ const struct sfp_module_caps *sfp_get_module_caps(struct sfp_bus *bus)
}
EXPORT_SYMBOL_GPL(sfp_get_module_caps);
-/**
- * sfp_parse_port() - Parse the EEPROM base ID, setting the port type
- * @bus: a pointer to the &struct sfp_bus structure for the sfp module
- * @id: a pointer to the module's &struct sfp_eeprom_id
- * @support: optional pointer to an array of unsigned long for the
- * ethtool support mask
- *
- * Parse the EEPROM identification given in @id, and return one of
- * %PORT_TP, %PORT_FIBRE or %PORT_OTHER. If @support is non-%NULL,
- * also set the ethtool %ETHTOOL_LINK_MODE_xxx_BIT corresponding with
- * the connector type.
- *
- * If the port type is not known, returns %PORT_OTHER.
- */
-int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
- unsigned long *support)
-{
- return bus->caps.port;
-}
-EXPORT_SYMBOL_GPL(sfp_parse_port);
-
static void sfp_module_parse_port(struct sfp_bus *bus,
const struct sfp_eeprom_id *id)
{
@@ -118,20 +97,6 @@ static void sfp_module_parse_port(struct sfp_bus *bus,
bus->caps.port = port;
}
-/**
- * sfp_may_have_phy() - indicate whether the module may have a PHY
- * @bus: a pointer to the &struct sfp_bus structure for the sfp module
- * @id: a pointer to the module's &struct sfp_eeprom_id
- *
- * Parse the EEPROM identification given in @id, and return whether
- * this module may have a PHY.
- */
-bool sfp_may_have_phy(struct sfp_bus *bus, const struct sfp_eeprom_id *id)
-{
- return bus->caps.may_have_phy;
-}
-EXPORT_SYMBOL_GPL(sfp_may_have_phy);
-
static void sfp_module_may_have_phy(struct sfp_bus *bus,
const struct sfp_eeprom_id *id)
{
@@ -154,25 +119,6 @@ static void sfp_module_may_have_phy(struct sfp_bus *bus,
bus->caps.may_have_phy = false;
}
-/**
- * sfp_parse_support() - Parse the eeprom id for supported link modes
- * @bus: a pointer to the &struct sfp_bus structure for the sfp module
- * @id: a pointer to the module's &struct sfp_eeprom_id
- * @support: pointer to an array of unsigned long for the ethtool support mask
- * @interfaces: pointer to an array of unsigned long for phy interface modes
- * mask
- *
- * Parse the EEPROM identification information and derive the supported
- * ethtool link modes for the module.
- */
-void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
- unsigned long *support, unsigned long *interfaces)
-{
- linkmode_or(support, support, bus->caps.link_modes);
- phy_interface_copy(interfaces, bus->caps.interfaces);
-}
-EXPORT_SYMBOL_GPL(sfp_parse_support);
-
static void sfp_module_parse_support(struct sfp_bus *bus,
const struct sfp_eeprom_id *id)
{
diff --git a/include/linux/sfp.h b/include/linux/sfp.h
index 9f29fcad52be..5c71945a5e4d 100644
--- a/include/linux/sfp.h
+++ b/include/linux/sfp.h
@@ -577,11 +577,6 @@ struct sfp_upstream_ops {
#if IS_ENABLED(CONFIG_SFP)
const struct sfp_module_caps *sfp_get_module_caps(struct sfp_bus *bus);
-int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
- unsigned long *support);
-bool sfp_may_have_phy(struct sfp_bus *bus, const struct sfp_eeprom_id *id);
-void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
- unsigned long *support, unsigned long *interfaces);
phy_interface_t sfp_select_interface(struct sfp_bus *bus,
const unsigned long *link_modes);
@@ -607,26 +602,6 @@ sfp_get_module_caps(struct sfp_bus *bus)
return NULL;
}
-static inline int sfp_parse_port(struct sfp_bus *bus,
- const struct sfp_eeprom_id *id,
- unsigned long *support)
-{
- return PORT_OTHER;
-}
-
-static inline bool sfp_may_have_phy(struct sfp_bus *bus,
- const struct sfp_eeprom_id *id)
-{
- return false;
-}
-
-static inline void sfp_parse_support(struct sfp_bus *bus,
- const struct sfp_eeprom_id *id,
- unsigned long *support,
- unsigned long *interfaces)
-{
-}
-
static inline phy_interface_t sfp_select_interface(struct sfp_bus *bus,
const unsigned long *link_modes)
{
--
2.47.3
^ permalink raw reply related [flat|nested] 12+ messages in thread