Commit 6710ab75 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'net-rework-sfp-capability-parsing-and-quirks'

Russell King says:

====================
net: rework SFP capability parsing and quirks

The original SPF module parsing was implemented prior to gaining any
quirks, and was designed such that the upstream calls the parsing
functions to get the translated capabilities of the module.

SFP quirks were then added to cope with modules that didn't correctly
fill out their ID EEPROM. The quirk function was called from
sfp_parse_support() to allow quirks to modify the ethtool link mode
masks.

Using just ethtool link mode masks eventually lead to difficulties
determining the correct phy_interface_t mode, so a bitmap of these
modes were added - needing both the upstream API and quirks to be
updated.

We have had significantly more SFP module quirks added since, some
which are modifying the ID EEPROM as a way of influencing the data
we provide to the upstream - for example, sfp_fixup_10gbaset_30m()
changes id.base.connector so we report PORT_TP. This could be done
more cleanly if the quirks had access to the parsed SFP port.

In order to improve flexibility, and to simplify some of the upstream
code, we group all module capabilities into a single structure that
the upstream can access via sfp_module_get_caps(). This will allow
the module capabilities to be expanded if required without reworking
all the infrastructure and upstreams again.

In this series, we rework the SFP code to use the capability structure
and then rework all the upstream implementations, finally removing the
old kernel internal APIs.
====================

Link: https://patch.msgid.link/aMnaoPjIuzEAsESZ@shell.armlinux.org.uk


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 9b277fca 9ce13873
Loading
Loading
Loading
Loading
+6 −7
Original line number Diff line number Diff line
@@ -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)
+3 −5
Original line number Diff line number Diff line
@@ -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));

+3 −4
Original line number Diff line number Diff line
@@ -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");
+6 −5
Original line number Diff line number Diff line
@@ -3750,17 +3750,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;

+4 −5
Original line number Diff line number Diff line
@@ -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");
Loading