From nobody Tue Dec 2 01:26:44 2025 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BD3612FE581; Sat, 22 Nov 2025 12:44:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763815444; cv=none; b=o/vuVBHrV+j4j0N14SR2hxBthAOScI13Lwl9l5uwvtl8mXk1bNn3O44p3yU/+DiocN5E1UHHEbf7DMQ4xnU+mBwWw0zRPGS0qFChcatPZQiMJQ3zJSQzFgtlHjyIwav4/DBk3PCBWPCFe2514tzlfLDbJrfD2pKlNKz23RSv3Ic= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763815444; c=relaxed/simple; bh=kt970PIrRbKVbKWCO7Ijcr1y2Psk1Vk4rbXY/51Trjc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ms1OpCOVMyfKKNcA3wP0MeYYWUam7Dury+0AKwtdSEXLHV1owEkcIbEttzzGI8kCzlQC48xCk+VACV9IViIdZvLpho3NlRoh8QUDQCa0wK0A6YerydtUnUrc+vEACejWrMbqOzdQW5HpW4Rv0W8LPQ45hO0PGy9BIjw9xQwPhEQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=zYUV8PZh; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="zYUV8PZh" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 4099D4E41851; Sat, 22 Nov 2025 12:44:01 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 13BFE606C5; Sat, 22 Nov 2025 12:44:01 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id B1A5410371E69; Sat, 22 Nov 2025 13:43:56 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1763815439; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=mXISH1m2FWOa1re4lRf2E8WpcS+3R+/gMgNN8FHfuxc=; b=zYUV8PZhh7Runip5pLfyfp5jguRY718C+vXe9VrjW61m3JZ6NeY2sLu3dRlcdJ4cKZXQRH Swrvo/M5p9Z0+lC5+GDTFWwObEvR89oD6crm40WIWD//RnbY1jE7//g0EwHQ5oKnJ2eMtH toavdmEm6d2QPnws1ZBu1EdwEn/T9yx/S9QfZTaBPCH4+bKpgDr4eBZQmDAH+X3JZJoDQj 0u1W4mGD8t0JDGa2NonlTxZEi+P7k40uWikBqFPI+j5DG7fwzFqfQDApXtnWylAw95j55T uZRwWTj7iL+8Xeh4efrqvw44binODwuuLJg3t5Fkpq8kpMD8qP3kobWy20iOxw== From: Maxime Chevallier To: davem@davemloft.net Cc: Maxime Chevallier , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, thomas.petazzoni@bootlin.com, Andrew Lunn , Jakub Kicinski , Eric Dumazet , Paolo Abeni , Russell King , linux-arm-kernel@lists.infradead.org, Christophe Leroy , Herve Codina , Florian Fainelli , Heiner Kallweit , Vladimir Oltean , =?UTF-8?q?K=C3=B6ry=20Maincent?= , =?UTF-8?q?Marek=20Beh=C3=BAn?= , Oleksij Rempel , =?UTF-8?q?Nicol=C3=B2=20Veronese?= , Simon Horman , mwojtas@chromium.org, Antoine Tenart , devicetree@vger.kernel.org, Conor Dooley , Krzysztof Kozlowski , Rob Herring , Romain Gantois , Daniel Golle , Dimitri Fedrau , Tariq Toukan Subject: [PATCH net-next v19 10/15] net: phy: marvell10g: Support SFP through phy_port Date: Sat, 22 Nov 2025 13:43:09 +0100 Message-ID: <20251122124317.92346-11-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20251122124317.92346-1-maxime.chevallier@bootlin.com> References: <20251122124317.92346-1-maxime.chevallier@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 X-Rspamd-Fuzzy: 3cb21b558de28fb2da6f0bd9e82e7e0b10c8d141dc54d9d6fbfd2e91509e71453fa3284c1bc137d8881b8fab86d8e63a2159b0df6846de9d71fb1087f1828b62 Content-Type: text/plain; charset="utf-8" Convert the Marvell10G driver to use the generic SFP handling, through a dedicated .attach_port() handler to populate the port's supported interfaces. As the 88x3310 supports multiple MDI, the .attach_port() logic handles both SFP attach with 10GBaseR support, and support for the "regular" port that usually is a BaseT port. Reviewed-by: Andrew Lunn Reviewed-by: Christophe Leroy Tested-by: Christophe Leroy Signed-off-by: Maxime Chevallier --- drivers/net/phy/marvell10g.c | 52 ++++++++++++++++++++++-------------- drivers/net/phy/phy_port.c | 44 ++++++++++++++++++++++++++++++ include/linux/phy_port.h | 1 + 3 files changed, 77 insertions(+), 20 deletions(-) diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 8fd42131cdbf..d4cace758fe8 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include =20 #define MV_PHY_ALASKA_NBT_QUIRK_MASK 0xfffffffe @@ -463,35 +463,35 @@ static int mv3310_set_edpd(struct phy_device *phydev,= u16 edpd) return err; } =20 -static int mv3310_sfp_insert(void *upstream, const struct sfp_eeprom_id *i= d) +static int mv3310_attach_mii_port(struct phy_device *phydev, + struct phy_port *port) { - struct phy_device *phydev =3D upstream; - const struct sfp_module_caps *caps; - phy_interface_t iface; + __set_bit(PHY_INTERFACE_MODE_10GBASER, port->interfaces); + return 0; +} =20 - caps =3D sfp_get_module_caps(phydev->sfp_bus); - iface =3D sfp_select_interface(phydev->sfp_bus, caps->link_modes); +static int mv3310_attach_mdi_port(struct phy_device *phydev, + struct phy_port *port) +{ + /* This PHY can do combo-ports, i.e. 2 MDI outputs, usually one + * of them going to an SFP and the other one to a RJ45 + * connector. If we don't have any representation for the port + * in DT, and we are dealing with a non-SFP port, then we + * mask the port's capabilities to report BaseT-only modes + */ + if (port->not_described) + return phy_port_restrict_mediums(port, + BIT(ETHTOOL_LINK_MEDIUM_BASET)); =20 - if (iface !=3D PHY_INTERFACE_MODE_10GBASER) { - dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n"); - return -EINVAL; - } return 0; } =20 -static const struct sfp_upstream_ops mv3310_sfp_ops =3D { - .attach =3D phy_sfp_attach, - .detach =3D phy_sfp_detach, - .connect_phy =3D phy_sfp_connect_phy, - .disconnect_phy =3D phy_sfp_disconnect_phy, - .module_insert =3D mv3310_sfp_insert, -}; - static int mv3310_probe(struct phy_device *phydev) { const struct mv3310_chip *chip =3D to_mv3310_chip(phydev); struct mv3310_priv *priv; u32 mmd_mask =3D MDIO_DEVS_PMAPMD | MDIO_DEVS_AN; + DECLARE_PHY_INTERFACE_MASK(interfaces); int ret; =20 if (!phydev->is_c45 || @@ -542,9 +542,13 @@ static int mv3310_probe(struct phy_device *phydev) if (ret) return ret; =20 + __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); + chip->init_supported_interfaces(priv->supported_interfaces); =20 - return phy_sfp_probe(phydev, &mv3310_sfp_ops); + phydev->max_n_ports =3D 2; + + return 0; } =20 static void mv3310_remove(struct phy_device *phydev) @@ -1405,6 +1409,8 @@ static struct phy_driver mv3310_drivers[] =3D { .set_loopback =3D genphy_c45_loopback, .get_wol =3D mv3110_get_wol, .set_wol =3D mv3110_set_wol, + .attach_mii_port =3D mv3310_attach_mii_port, + .attach_mdi_port =3D mv3310_attach_mdi_port, }, { .phy_id =3D MARVELL_PHY_ID_88X3310, @@ -1424,6 +1430,8 @@ static struct phy_driver mv3310_drivers[] =3D { .set_tunable =3D mv3310_set_tunable, .remove =3D mv3310_remove, .set_loopback =3D genphy_c45_loopback, + .attach_mii_port =3D mv3310_attach_mii_port, + .attach_mdi_port =3D mv3310_attach_mdi_port, }, { .phy_id =3D MARVELL_PHY_ID_88E2110, @@ -1444,6 +1452,8 @@ static struct phy_driver mv3310_drivers[] =3D { .set_loopback =3D genphy_c45_loopback, .get_wol =3D mv3110_get_wol, .set_wol =3D mv3110_set_wol, + .attach_mii_port =3D mv3310_attach_mii_port, + .attach_mdi_port =3D mv3310_attach_mdi_port, }, { .phy_id =3D MARVELL_PHY_ID_88E2110, @@ -1462,6 +1472,8 @@ static struct phy_driver mv3310_drivers[] =3D { .set_tunable =3D mv3310_set_tunable, .remove =3D mv3310_remove, .set_loopback =3D genphy_c45_loopback, + .attach_mii_port =3D mv3310_attach_mii_port, + .attach_mdi_port =3D mv3310_attach_mdi_port, }, }; =20 diff --git a/drivers/net/phy/phy_port.c b/drivers/net/phy/phy_port.c index f89f70f83593..d9099196f870 100644 --- a/drivers/net/phy/phy_port.c +++ b/drivers/net/phy/phy_port.c @@ -149,6 +149,50 @@ void phy_port_update_supported(struct phy_port *port) } EXPORT_SYMBOL_GPL(phy_port_update_supported); =20 +/** + * phy_port_filter_supported() - Make sure that port->supported match port= ->mediums + * @port: The port to filter + * + * After updating a port's mediums to a more restricted subset, this helpe= r will + * make sure that port->supported only contains linkmodes that are compati= ble + * with port->mediums. + */ +static void phy_port_filter_supported(struct phy_port *port) +{ + __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) =3D { 0 }; + int i; + + for_each_set_bit(i, &port->mediums, __ETHTOOL_LINK_MEDIUM_LAST) + phy_caps_medium_get_supported(supported, i, port->pairs); + + linkmode_and(port->supported, port->supported, supported); +} + +/** + * phy_port_restrict_mediums - Mask away some of the port's supported medi= ums + * @port: The port to act upon + * @mediums: A mask of mediums to support on the port + * + * This helper allows removing some mediums from a port's list of supported + * mediums, which occurs once we have enough information about the port to + * know its nature. + * + * Returns: 0 if the change was donne correctly, a negative value otherwis= e. + */ +int phy_port_restrict_mediums(struct phy_port *port, unsigned long mediums) +{ + /* We forbid ending-up with a port with empty mediums */ + if (!(port->mediums & mediums)) + return -EINVAL; + + port->mediums &=3D mediums; + + phy_port_filter_supported(port); + + return 0; +} +EXPORT_SYMBOL_GPL(phy_port_restrict_mediums); + /** * phy_port_get_type() - get the PORT_* attribute for that port. * @port: The port we want the information from diff --git a/include/linux/phy_port.h b/include/linux/phy_port.h index 550c3f4ab19f..0ef0f5ce4709 100644 --- a/include/linux/phy_port.h +++ b/include/linux/phy_port.h @@ -92,6 +92,7 @@ static inline bool phy_port_is_fiber(struct phy_port *por= t) } =20 void phy_port_update_supported(struct phy_port *port); +int phy_port_restrict_mediums(struct phy_port *port, unsigned long mediums= ); =20 int phy_port_get_type(struct phy_port *port); =20 --=20 2.49.0