From nobody Thu Oct 2 22:52:49 2025 Received: from smtpout-04.galae.net (smtpout-04.galae.net [185.171.202.116]) (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 92278350D52; Tue, 9 Sep 2025 15:27:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.171.202.116 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431637; cv=none; b=RHgHuBRSkyAKNvMXcMhHngcOZ/ps6cL6ojyIPKTrE1B6Oo85j5VKlqzPksUnaaQfU2gIGO9BPwzH3kthCxy/+xI4dm9ksmoBsBVuNpzFPwfzChTnstWDBtsSpDWcS1fs/gt1VC944XR12shNuBx+bZEtAQnG78dgk6BQvwdv6VM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431637; c=relaxed/simple; bh=gUJjaE0duj/kLnV7Lay1y+0wtUe1ZimWzrjINkTOSzo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KOETC83PIYyE8vSo+xTpLisNEHFGjTshczztp6DkAuf6sCLAw4HvvpmaD6fGDmmi0vOxXI9Jzxl/wN+RynCwRS8YbSlTFaCS0rTs5dK691pLMiVpcsBp+5AdNk/kcPR/gxXJolUh22N35VVdy2SglESmBFvo8qLwDM+upfANWxg= 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=QmDzuOrI; arc=none smtp.client-ip=185.171.202.116 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="QmDzuOrI" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-04.galae.net (Postfix) with ESMTPS id 0D12CC6B39E; Tue, 9 Sep 2025 15:26:58 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id B4CCC60630; Tue, 9 Sep 2025 15:27:13 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id D89E4102F28B2; Tue, 9 Sep 2025 17:27:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1757431631; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=/RuEgx5LojknB04vuOgySkXKclrKNkwFIX9m0dpLDeU=; b=QmDzuOrIRlNbLGmuK7KHTGoQeW5EsekuyOoPnllUIzKk/PsCYBasZDm7gtcnVsOAC+0/9X 8QPZ9VQPJ0lInliKoQSyvekAwQ/KAkBdSKckZ2kv1INIX2ICxHV4BDj/QGFbWMCK+ugK9M KTPboMzBXUfPNtsxtUmIaARFleNnZPhAL64RBwFuONbF66W8IxOWGDjvhZJMPKl0c4IbvW brDavuPS8QFzNJYqFzWSgYcGfCjGBh67AZP4ADYO54Hbsf+pNyxr79ozbUhvwXr58vVSiJ oo9L6t/9Eko4Sk/VEwT9uD8a38JHujvXHJ5+T4kVdkpWEDz5H6eyLvjSI5EwhA== 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 Subject: [PATCH net-next v12 01/18] dt-bindings: net: Introduce the ethernet-connector description Date: Tue, 9 Sep 2025 17:25:57 +0200 Message-ID: <20250909152617.119554-2-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250909152617.119554-1-maxime.chevallier@bootlin.com> References: <20250909152617.119554-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 Content-Type: text/plain; charset="utf-8" The ability to describe the physical ports of Ethernet devices is useful to describe multi-port devices, as well as to remove any ambiguity with regard to the nature of the port. Moreover, describing ports allows for a better description of features that are tied to connectors, such as PoE through the PSE-PD devices. Introduce a binding to allow describing the ports, for now with 2 attributes : - The number of lanes, which is a quite generic property that allows differentating between multiple similar technologies such as BaseT1 and "regular" BaseT (which usually means BaseT4). - The media that can be used on that port, such as BaseT for Twisted Copper, BaseC for coax copper, BaseS/L for Fiber, BaseK for backplane ethernet, etc. This allows defining the nature of the port, and therefore avoids the need for vendor-specific properties such as "micrel,fiber-mode" or "ti,fiber-mode". The port description lives in its own file, as it is intended in the future to allow describing the ports for phy-less devices. Reviewed-by: Rob Herring (Arm) Reviewed-by: Kory Maincent Reviewed-by: Christophe Leroy Signed-off-by: Maxime Chevallier Tested-by: Christophe Leroy Tested-by: Florian Fainelli Tested-by: Oleksij Rempel --- .../bindings/net/ethernet-connector.yaml | 45 +++++++++++++++++++ .../devicetree/bindings/net/ethernet-phy.yaml | 18 ++++++++ MAINTAINERS | 1 + 3 files changed, 64 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/ethernet-connecto= r.yaml diff --git a/Documentation/devicetree/bindings/net/ethernet-connector.yaml = b/Documentation/devicetree/bindings/net/ethernet-connector.yaml new file mode 100644 index 000000000000..32ae9f45b0e4 --- /dev/null +++ b/Documentation/devicetree/bindings/net/ethernet-connector.yaml @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/ethernet-connector.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Generic Ethernet Connector + +maintainers: + - Maxime Chevallier + +description: + An Ethernet Connector represents the output of a network component such = as + a PHY, an Ethernet controller with no PHY, or an SFP module. + +properties: + + lanes: + description: + Defines the number of lanes on the port, that is the number of physi= cal + channels used to convey the data with the link partner. + $ref: /schemas/types.yaml#/definitions/uint32 + + media: + description: + The mediums, as defined in 802.3, that can be used on the port. + enum: + - BaseT + - BaseK + - BaseS + - BaseC + - BaseL + - BaseD + - BaseE + - BaseF + - BaseV + - BaseMLD + +required: + - lanes + - media + +additionalProperties: true + +... diff --git a/Documentation/devicetree/bindings/net/ethernet-phy.yaml b/Docu= mentation/devicetree/bindings/net/ethernet-phy.yaml index 71e2cd32580f..64bd23b7073d 100644 --- a/Documentation/devicetree/bindings/net/ethernet-phy.yaml +++ b/Documentation/devicetree/bindings/net/ethernet-phy.yaml @@ -277,6 +277,17 @@ properties: =20 additionalProperties: false =20 + mdi: + type: object + + patternProperties: + '^connector-[a-f0-9]+$': + $ref: /schemas/net/ethernet-connector.yaml# + + unevaluatedProperties: false + + additionalProperties: false + required: - reg =20 @@ -313,5 +324,12 @@ examples: default-state =3D "keep"; }; }; + /* Fast Ethernet port, with only 2 pairs wired */ + mdi { + connector-0 { + lanes =3D <2>; + media =3D "BaseT"; + }; + }; }; }; diff --git a/MAINTAINERS b/MAINTAINERS index b81595e9ea95..384bb1dc8424 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9107,6 +9107,7 @@ R: Russell King L: netdev@vger.kernel.org S: Maintained F: Documentation/ABI/testing/sysfs-class-net-phydev +F: Documentation/devicetree/bindings/net/ethernet-connector.yaml F: Documentation/devicetree/bindings/net/ethernet-phy.yaml F: Documentation/devicetree/bindings/net/mdio* F: Documentation/devicetree/bindings/net/qca,ar803x.yaml --=20 2.49.0 From nobody Thu Oct 2 22:52:49 2025 Received: from smtpout-04.galae.net (smtpout-04.galae.net [185.171.202.116]) (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 AF9ED352FF0; Tue, 9 Sep 2025 15:27:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.171.202.116 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431640; cv=none; b=gPqzs/bw4z8B0IRUC9a+vpyik5e4YJMJd88a5PwZ3dXQa2TFMDhDSrMVkBM1UyGrZz6qhg35TezlEH7+zla5Zpvq1Apiysuw2efvUXVlSjt/P99fRevXS1N3MFUuB0I557LZ4XDRGwGmF/Bfn5czXyYJN/KvwuLIxBwv2/8cqkg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431640; c=relaxed/simple; bh=8GIISQ747xStpcrAmgsrEm3PUzf7LjS8WrP3DawpFlk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=oPW7QkUuKCOEHfOIVgD2pMRH6liVVi7OMVuYMK4pF1y2v/fuofYURgF9zqSRvYqcz1VDUd8RPnZr/9HAcjcE00yikWzZuDwciC0O+tz2b65npfiHT0TCUbo3/p+z5lFpxntnonZKHBwEilSdyMjnUoTzhqJNywwMHSaZQhBX018= 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=fB+eiZKH; arc=none smtp.client-ip=185.171.202.116 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="fB+eiZKH" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-04.galae.net (Postfix) with ESMTPS id 7979DC6B394; Tue, 9 Sep 2025 15:27:01 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 2F01D60630; Tue, 9 Sep 2025 15:27:17 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id F185A102F29EC; Tue, 9 Sep 2025 17:27:12 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1757431636; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=X1SG6EZwUeidKkcS9Cw+ueu25J90gmUPbo4DL8leCwY=; b=fB+eiZKHPolvzi13mJFfOgpFgeFd1Yny8ECJuMOjtqkABHsw3dkvmuDnPIa3OXUhq1xb/l xSS50T4rfyFiFInmOyCOwM3VSaXEQehjEeiqIZfKONZx6NcUlY9iGNScpRtji9BlPYWoBG cPNmQ/BfeyiDc0Gin3PejqBiWBZ1tkedx8K2qkrNqHPppXyOGDgOMPh6xV+bW8qlCLuzZX xKZKbNnj7csGWH6mBYujlt3j/bRZbS2qkTdnvEQjTQnpla7E6aWqxTmKsY8sucsRJocwlV zamRsrDvNhVT/Qa5zd4Iu3F+DGFC7o7xmVKWFbXNEQd5g/997iLc/dmFJhOyIg== 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 Subject: [PATCH net-next v12 02/18] net: ethtool: common: Indicate that BaseT works on up to 4 lanes Date: Tue, 9 Sep 2025 17:25:58 +0200 Message-ID: <20250909152617.119554-3-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250909152617.119554-1-maxime.chevallier@bootlin.com> References: <20250909152617.119554-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 Content-Type: text/plain; charset="utf-8" The way BaseT modes (Ethernet over twisted copper pairs) are represented in the kernel are through the following modes : ETHTOOL_LINK_MODE_10baseT_Half ETHTOOL_LINK_MODE_10baseT_Full ETHTOOL_LINK_MODE_100baseT_Half ETHTOOL_LINK_MODE_100baseT_Full ETHTOOL_LINK_MODE_1000baseT_Half ETHTOOL_LINK_MODE_1000baseT_Full ETHTOOL_LINK_MODE_2500baseT_Full ETHTOOL_LINK_MODE_5000baseT_Full ETHTOOL_LINK_MODE_10000baseT_Full ETHTOOL_LINK_MODE_100baseT1_Full ETHTOOL_LINK_MODE_1000baseT1_Full ETHTOOL_LINK_MODE_10baseT1L_Full ETHTOOL_LINK_MODE_10baseT1S_Full ETHTOOL_LINK_MODE_10baseT1S_Half ETHTOOL_LINK_MODE_10baseT1S_P2MP_Half ETHTOOL_LINK_MODE_10baseT1BRR_Full The baseT1* modes explicitly specify that they work on a single, unshielded twister copper pair. However, the other modes do not state the number of pairs that are used to carry the link. 10 and 100BaseT use 2 twisted copper pairs, while 1GBaseT and higher use 4 pairs. although 10 and 100BaseT use 2 pairs, they can work on a Cat3/4/5+ cables that contain 4 pairs. Change the number of pairs associated to BaseT modes to indicate the allowable number of pairs for BaseT. Further commits will then refine the minimum number of pairs required for the linkmode to work. BaseT1 modes aren't affected by this commit. Reviewed-by: Kory Maincent Reviewed-by: Christophe Leroy Signed-off-by: Maxime Chevallier Tested-by: Christophe Leroy Tested-by: Florian Fainelli Tested-by: Oleksij Rempel --- net/ethtool/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ethtool/common.c b/net/ethtool/common.c index 4f58648a27ad..57290fdb7193 100644 --- a/net/ethtool/common.c +++ b/net/ethtool/common.c @@ -267,7 +267,7 @@ static_assert(ARRAY_SIZE(link_mode_names) =3D=3D __ETHT= OOL_LINK_MODE_MASK_NBITS); #define __LINK_MODE_LANES_LR8_ER8_FR8 8 #define __LINK_MODE_LANES_LRM 1 #define __LINK_MODE_LANES_MLD2 2 -#define __LINK_MODE_LANES_T 1 +#define __LINK_MODE_LANES_T 4 #define __LINK_MODE_LANES_T1 1 #define __LINK_MODE_LANES_X 1 #define __LINK_MODE_LANES_FX 1 --=20 2.49.0 From nobody Thu Oct 2 22:52:49 2025 Received: from smtpout-04.galae.net (smtpout-04.galae.net [185.171.202.116]) (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 DDEF935336E for ; Tue, 9 Sep 2025 15:27:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.171.202.116 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431644; cv=none; b=bxbRdnOIIU491JZiW1L/YkN9f/THlrJfoHtOjMT/oB5cx1VZo6KJCC5Y1+Cl81kISNNZ/i3rTZIMIyNWun/y6dea4XOB2hGpspm1xLMUS9wiqgVn81dA8N7dZbMsk5zja9K5C1CEfXNSggtLBBsirnQnRDGKUFLhMOE9RNEYLAU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431644; c=relaxed/simple; bh=jJ6eAoS4S9qMqv0Q+KveUP/4ha7/0g4ywvSE1j78Wkw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NTLJwfe0nFgRJnGVS1AQhxrJyc5UIES5Txk2OIuRuXsuYTF9Z7Vjm2J5Lvd10dwOgzxkD1LFmuQe/YvnGH21+IYg8E6csJ6y1xjwsW4wr2YAsMDvsbQyySJPJdYxDLSU25WIDzwBRM9qwAOk/TBhZx3EKxgtHMZX0l9hubYHG2k= 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=C8zn1bCb; arc=none smtp.client-ip=185.171.202.116 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="C8zn1bCb" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-04.galae.net (Postfix) with ESMTPS id 74817C6B39E; Tue, 9 Sep 2025 15:27:04 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 2963460630; Tue, 9 Sep 2025 15:27:20 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 5AF17102F08F6; Tue, 9 Sep 2025 17:27:16 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1757431638; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=w/yqSwRvXqVvYfzjZo7nUqBHSWqW6ckF9rNnJTRjDn0=; b=C8zn1bCbf0F5vXmzX/TjMNs00K231YZazxMvrg6VYhjnfbK526G0FH+RWjkE8Z5MEuZ8lD eWy6gaUxyLtOrEKMgVtfKBfEw9G5h3YjaaXpLzYdcEnSTj92Y5kZxy/EG62wMiSfjluc/K QB1G0rmBx49G+RpPPD2foCDuID6ginxPHNndZ4K87fpO4DuQQKiSoc3g86g6Tdb3iPMlY+ 6htiVGmn0NnpEv7HRTXPn2i3hPZK3tZeDvZen3j1hCTfI6o/LsZcw4s3b424I4uzY6iOGH KYp/23YzLdfVEiPL9xXD5p6E/SlcVfOUP/9JMliBUojKdneUliPqvc9POcNmEw== 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 Subject: [PATCH net-next v12 03/18] net: ethtool: Introduce ETHTOOL_LINK_MEDIUM_* values Date: Tue, 9 Sep 2025 17:25:59 +0200 Message-ID: <20250909152617.119554-4-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250909152617.119554-1-maxime.chevallier@bootlin.com> References: <20250909152617.119554-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 Content-Type: text/plain; charset="utf-8" In an effort to have a better representation of Ethernet ports, introduce enumeration values representing the various ethernet Mediums. This is part of the 802.3 naming convention, for example : 1000 Base T 4 | | | | | | | \_ lanes (4) | | \___ Medium (T =3D=3D Twisted Copper Pairs) | \_______ Baseband transmission \____________ Speed Other example : 10000 Base K X 4 | | \_ lanes (4) | \___ encoding (BaseX is 8b/10b while BaseR is 66b/64b) \_____ Medium (K is backplane ethernet) In the case of representing a physical port, only the medium and number of lanes should be relevant. One exception would be 1000BaseX, which is currently also used as a medium in what appears to be any of 1000BaseSX, 1000BaseCX and 1000BaseLX. This was reflected in the mediums associated with the 1000BaseX linkmode. These mediums are set in the net/ethtool/common.c lookup table that maintains a list of all linkmodes with their number of lanes, medium, encoding, speed and duplex. One notable exception to this is 100M BaseT Ethernet. 100BaseTX is a 2-lanes protocol but it will also work on 4-lanes cables, so the lookup table contains 2 sets of lane numbers, indicating the min number of lanes for a protocol to work and the "nominal" number of lanes as well. Another set of exceptions are linkmodes such 100000baseLR4_ER4, where the same link mode seems to represent 100GBaseLR4 and 100GBaseER4. The macro __DEFINE_LINK_MODE_PARAMS_MEDIUMS is here used to populate the .mediums bitfield with all appropriate mediums. Reviewed-by: Christophe Leroy Signed-off-by: Maxime Chevallier Tested-by: Christophe Leroy Tested-by: Florian Fainelli Tested-by: Oleksij Rempel --- drivers/net/phy/phy_caps.c | 8 ++ include/linux/ethtool.h | 18 ++- include/uapi/linux/ethtool.h | 20 +++ net/ethtool/common.c | 265 +++++++++++++++++++++-------------- 4 files changed, 199 insertions(+), 112 deletions(-) diff --git a/drivers/net/phy/phy_caps.c b/drivers/net/phy/phy_caps.c index 2cc9ee97e867..990c36ccd9e7 100644 --- a/drivers/net/phy/phy_caps.c +++ b/drivers/net/phy/phy_caps.c @@ -78,6 +78,14 @@ int phy_caps_init(void) /* Fill the caps array from net/ethtool/common.c */ for (i =3D 0; i < __ETHTOOL_LINK_MODE_MASK_NBITS; i++) { linkmode =3D &link_mode_params[i]; + + /* Sanity check the linkmodes array for number of lanes */ + if (linkmode->lanes < linkmode->min_lanes) { + pr_err("Lanes count must not be under min_lanes for linkmode %d\n", + i); + return -EINVAL; + } + capa =3D speed_duplex_to_capa(linkmode->speed, linkmode->duplex); =20 if (capa < 0) { diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index de5bd76a400c..a0696cb840f7 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -216,13 +216,25 @@ static inline u8 *ethtool_rxfh_context_key(struct eth= tool_rxfh_context *ctx) void ethtool_rxfh_context_lost(struct net_device *dev, u32 context_id); =20 struct link_mode_info { - int speed; - u8 lanes; - u8 duplex; + int speed; + u8 min_lanes; + u8 lanes; + u8 duplex; + u16 mediums; }; =20 extern const struct link_mode_info link_mode_params[]; =20 +extern const char ethtool_link_medium_names[][ETH_GSTRING_LEN]; + +static inline const char *phy_mediums(enum ethtool_link_medium medium) +{ + if (medium >=3D __ETHTOOL_LINK_MEDIUM_LAST) + return "unknown"; + + return ethtool_link_medium_names[medium]; +} + /* declare a link mode bitmap */ #define __ETHTOOL_DECLARE_LINK_MODE_MASK(name) \ DECLARE_BITMAP(name, __ETHTOOL_LINK_MODE_MASK_NBITS) diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index 8bd5ea5469d9..6ed235053aed 100644 --- a/include/uapi/linux/ethtool.h +++ b/include/uapi/linux/ethtool.h @@ -2587,4 +2587,24 @@ enum phy_upstream { PHY_UPSTREAM_PHY, }; =20 +enum ethtool_link_medium { + ETHTOOL_LINK_MEDIUM_BASET =3D 0, + ETHTOOL_LINK_MEDIUM_BASEK, + ETHTOOL_LINK_MEDIUM_BASES, + ETHTOOL_LINK_MEDIUM_BASEC, + ETHTOOL_LINK_MEDIUM_BASEL, + ETHTOOL_LINK_MEDIUM_BASED, + ETHTOOL_LINK_MEDIUM_BASEE, + ETHTOOL_LINK_MEDIUM_BASEF, + ETHTOOL_LINK_MEDIUM_BASEV, + ETHTOOL_LINK_MEDIUM_BASEMLD, + ETHTOOL_LINK_MEDIUM_NONE, + + __ETHTOOL_LINK_MEDIUM_LAST, +}; + +#define ETHTOOL_MEDIUM_FIBER_BITS (BIT(ETHTOOL_LINK_MEDIUM_BASES) | \ + BIT(ETHTOOL_LINK_MEDIUM_BASEL) | \ + BIT(ETHTOOL_LINK_MEDIUM_BASEF)) + #endif /* _UAPI_LINUX_ETHTOOL_H */ diff --git a/net/ethtool/common.c b/net/ethtool/common.c index 57290fdb7193..163b76629b27 100644 --- a/net/ethtool/common.c +++ b/net/ethtool/common.c @@ -281,12 +281,32 @@ static_assert(ARRAY_SIZE(link_mode_names) =3D=3D __ET= HTOOL_LINK_MODE_MASK_NBITS); #define __LINK_MODE_LANES_DR8_2 8 #define __LINK_MODE_LANES_T1BRR 1 =20 -#define __DEFINE_LINK_MODE_PARAMS(_speed, _type, _duplex) \ +#define __DEFINE_LINK_MODE_PARAMS_LANES(_speed, _type, _min_lanes, _lanes,= _duplex, _medium) \ [ETHTOOL_LINK_MODE(_speed, _type, _duplex)] =3D { \ .speed =3D SPEED_ ## _speed, \ + .min_lanes =3D _min_lanes, \ + .lanes =3D _lanes, \ + .duplex =3D __DUPLEX_ ## _duplex, \ + .mediums =3D BIT(ETHTOOL_LINK_MEDIUM_BASE ## _medium) \ + } + +#define __DEFINE_LINK_MODE_PARAMS(_speed, _type, _duplex, _medium) \ + [ETHTOOL_LINK_MODE(_speed, _type, _duplex)] =3D { \ + .speed =3D SPEED_ ## _speed, \ + .min_lanes =3D __LINK_MODE_LANES_ ## _type, \ + .lanes =3D __LINK_MODE_LANES_ ## _type, \ + .duplex =3D __DUPLEX_ ## _duplex, \ + .mediums =3D BIT(ETHTOOL_LINK_MEDIUM_BASE ## _medium) \ + } +#define __DEFINE_LINK_MODE_PARAMS_MEDIUMS(_speed, _type, _duplex, _mediums= ) \ + [ETHTOOL_LINK_MODE(_speed, _type, _duplex)] =3D { \ + .speed =3D SPEED_ ## _speed, \ + .min_lanes =3D __LINK_MODE_LANES_ ## _type, \ .lanes =3D __LINK_MODE_LANES_ ## _type, \ - .duplex =3D __DUPLEX_ ## _duplex \ + .duplex =3D __DUPLEX_ ## _duplex, \ + .mediums =3D (_mediums) \ } +#define __MED(_medium) (BIT(ETHTOOL_LINK_MEDIUM_BASE ## _medium)) #define __DUPLEX_Half DUPLEX_HALF #define __DUPLEX_Full DUPLEX_FULL #define __DEFINE_SPECIAL_MODE_PARAMS(_mode) \ @@ -294,138 +314,165 @@ static_assert(ARRAY_SIZE(link_mode_names) =3D=3D __= ETHTOOL_LINK_MODE_MASK_NBITS); .speed =3D SPEED_UNKNOWN, \ .lanes =3D 0, \ .duplex =3D DUPLEX_UNKNOWN, \ + .mediums =3D BIT(ETHTOOL_LINK_MEDIUM_NONE), \ } =20 const struct link_mode_info link_mode_params[] =3D { - __DEFINE_LINK_MODE_PARAMS(10, T, Half), - __DEFINE_LINK_MODE_PARAMS(10, T, Full), - __DEFINE_LINK_MODE_PARAMS(100, T, Half), - __DEFINE_LINK_MODE_PARAMS(100, T, Full), - __DEFINE_LINK_MODE_PARAMS(1000, T, Half), - __DEFINE_LINK_MODE_PARAMS(1000, T, Full), + __DEFINE_LINK_MODE_PARAMS_LANES(10, T, 2, 4, Half, T), + __DEFINE_LINK_MODE_PARAMS_LANES(10, T, 2, 4, Full, T), + __DEFINE_LINK_MODE_PARAMS_LANES(100, T, 2, 4, Half, T), + __DEFINE_LINK_MODE_PARAMS_LANES(100, T, 2, 4, Full, T), + __DEFINE_LINK_MODE_PARAMS(1000, T, Half, T), + __DEFINE_LINK_MODE_PARAMS(1000, T, Full, T), __DEFINE_SPECIAL_MODE_PARAMS(Autoneg), __DEFINE_SPECIAL_MODE_PARAMS(TP), __DEFINE_SPECIAL_MODE_PARAMS(AUI), __DEFINE_SPECIAL_MODE_PARAMS(MII), __DEFINE_SPECIAL_MODE_PARAMS(FIBRE), __DEFINE_SPECIAL_MODE_PARAMS(BNC), - __DEFINE_LINK_MODE_PARAMS(10000, T, Full), + __DEFINE_LINK_MODE_PARAMS(10000, T, Full, T), __DEFINE_SPECIAL_MODE_PARAMS(Pause), __DEFINE_SPECIAL_MODE_PARAMS(Asym_Pause), - __DEFINE_LINK_MODE_PARAMS(2500, X, Full), + __DEFINE_LINK_MODE_PARAMS_MEDIUMS(2500, X, Full, + __MED(C) | __MED(S) | __MED(L)), __DEFINE_SPECIAL_MODE_PARAMS(Backplane), - __DEFINE_LINK_MODE_PARAMS(1000, KX, Full), - __DEFINE_LINK_MODE_PARAMS(10000, KX4, Full), - __DEFINE_LINK_MODE_PARAMS(10000, KR, Full), + __DEFINE_LINK_MODE_PARAMS(1000, KX, Full, K), + __DEFINE_LINK_MODE_PARAMS(10000, KX4, Full, K), + __DEFINE_LINK_MODE_PARAMS(10000, KR, Full, K), [ETHTOOL_LINK_MODE_10000baseR_FEC_BIT] =3D { .speed =3D SPEED_10000, .lanes =3D 1, .duplex =3D DUPLEX_FULL, }, - __DEFINE_LINK_MODE_PARAMS(20000, MLD2, Full), - __DEFINE_LINK_MODE_PARAMS(20000, KR2, Full), - __DEFINE_LINK_MODE_PARAMS(40000, KR4, Full), - __DEFINE_LINK_MODE_PARAMS(40000, CR4, Full), - __DEFINE_LINK_MODE_PARAMS(40000, SR4, Full), - __DEFINE_LINK_MODE_PARAMS(40000, LR4, Full), - __DEFINE_LINK_MODE_PARAMS(56000, KR4, Full), - __DEFINE_LINK_MODE_PARAMS(56000, CR4, Full), - __DEFINE_LINK_MODE_PARAMS(56000, SR4, Full), - __DEFINE_LINK_MODE_PARAMS(56000, LR4, Full), - __DEFINE_LINK_MODE_PARAMS(25000, CR, Full), - __DEFINE_LINK_MODE_PARAMS(25000, KR, Full), - __DEFINE_LINK_MODE_PARAMS(25000, SR, Full), - __DEFINE_LINK_MODE_PARAMS(50000, CR2, Full), - __DEFINE_LINK_MODE_PARAMS(50000, KR2, Full), - __DEFINE_LINK_MODE_PARAMS(100000, KR4, Full), - __DEFINE_LINK_MODE_PARAMS(100000, SR4, Full), - __DEFINE_LINK_MODE_PARAMS(100000, CR4, Full), - __DEFINE_LINK_MODE_PARAMS(100000, LR4_ER4, Full), - __DEFINE_LINK_MODE_PARAMS(50000, SR2, Full), - __DEFINE_LINK_MODE_PARAMS(1000, X, Full), - __DEFINE_LINK_MODE_PARAMS(10000, CR, Full), - __DEFINE_LINK_MODE_PARAMS(10000, SR, Full), - __DEFINE_LINK_MODE_PARAMS(10000, LR, Full), - __DEFINE_LINK_MODE_PARAMS(10000, LRM, Full), - __DEFINE_LINK_MODE_PARAMS(10000, ER, Full), - __DEFINE_LINK_MODE_PARAMS(2500, T, Full), - __DEFINE_LINK_MODE_PARAMS(5000, T, Full), + __DEFINE_LINK_MODE_PARAMS(20000, MLD2, Full, MLD), + __DEFINE_LINK_MODE_PARAMS(20000, KR2, Full, K), + __DEFINE_LINK_MODE_PARAMS(40000, KR4, Full, K), + __DEFINE_LINK_MODE_PARAMS(40000, CR4, Full, C), + __DEFINE_LINK_MODE_PARAMS(40000, SR4, Full, S), + __DEFINE_LINK_MODE_PARAMS(40000, LR4, Full, L), + __DEFINE_LINK_MODE_PARAMS(56000, KR4, Full, K), + __DEFINE_LINK_MODE_PARAMS(56000, CR4, Full, C), + __DEFINE_LINK_MODE_PARAMS(56000, SR4, Full, S), + __DEFINE_LINK_MODE_PARAMS(56000, LR4, Full, L), + __DEFINE_LINK_MODE_PARAMS(25000, CR, Full, C), + __DEFINE_LINK_MODE_PARAMS(25000, KR, Full, K), + __DEFINE_LINK_MODE_PARAMS(25000, SR, Full, S), + __DEFINE_LINK_MODE_PARAMS(50000, CR2, Full, C), + __DEFINE_LINK_MODE_PARAMS(50000, KR2, Full, K), + __DEFINE_LINK_MODE_PARAMS(100000, KR4, Full, K), + __DEFINE_LINK_MODE_PARAMS(100000, SR4, Full, S), + __DEFINE_LINK_MODE_PARAMS(100000, CR4, Full, C), + __DEFINE_LINK_MODE_PARAMS_MEDIUMS(100000, LR4_ER4, Full, + __MED(L) | __MED(E)), + __DEFINE_LINK_MODE_PARAMS(50000, SR2, Full, S), + __DEFINE_LINK_MODE_PARAMS_MEDIUMS(1000, X, Full, + __MED(C) | __MED(S) | __MED(L)), + __DEFINE_LINK_MODE_PARAMS(10000, CR, Full, C), + __DEFINE_LINK_MODE_PARAMS(10000, SR, Full, S), + __DEFINE_LINK_MODE_PARAMS(10000, LR, Full, L), + __DEFINE_LINK_MODE_PARAMS(10000, LRM, Full, L), + __DEFINE_LINK_MODE_PARAMS(10000, ER, Full, E), + __DEFINE_LINK_MODE_PARAMS(2500, T, Full, T), + __DEFINE_LINK_MODE_PARAMS(5000, T, Full, T), __DEFINE_SPECIAL_MODE_PARAMS(FEC_NONE), __DEFINE_SPECIAL_MODE_PARAMS(FEC_RS), __DEFINE_SPECIAL_MODE_PARAMS(FEC_BASER), - __DEFINE_LINK_MODE_PARAMS(50000, KR, Full), - __DEFINE_LINK_MODE_PARAMS(50000, SR, Full), - __DEFINE_LINK_MODE_PARAMS(50000, CR, Full), - __DEFINE_LINK_MODE_PARAMS(50000, LR_ER_FR, Full), - __DEFINE_LINK_MODE_PARAMS(50000, DR, Full), - __DEFINE_LINK_MODE_PARAMS(100000, KR2, Full), - __DEFINE_LINK_MODE_PARAMS(100000, SR2, Full), - __DEFINE_LINK_MODE_PARAMS(100000, CR2, Full), - __DEFINE_LINK_MODE_PARAMS(100000, LR2_ER2_FR2, Full), - __DEFINE_LINK_MODE_PARAMS(100000, DR2, Full), - __DEFINE_LINK_MODE_PARAMS(200000, KR4, Full), - __DEFINE_LINK_MODE_PARAMS(200000, SR4, Full), - __DEFINE_LINK_MODE_PARAMS(200000, LR4_ER4_FR4, Full), - __DEFINE_LINK_MODE_PARAMS(200000, DR4, Full), - __DEFINE_LINK_MODE_PARAMS(200000, CR4, Full), - __DEFINE_LINK_MODE_PARAMS(100, T1, Full), - __DEFINE_LINK_MODE_PARAMS(1000, T1, Full), - __DEFINE_LINK_MODE_PARAMS(400000, KR8, Full), - __DEFINE_LINK_MODE_PARAMS(400000, SR8, Full), - __DEFINE_LINK_MODE_PARAMS(400000, LR8_ER8_FR8, Full), - __DEFINE_LINK_MODE_PARAMS(400000, DR8, Full), - __DEFINE_LINK_MODE_PARAMS(400000, CR8, Full), + __DEFINE_LINK_MODE_PARAMS(50000, KR, Full, K), + __DEFINE_LINK_MODE_PARAMS(50000, SR, Full, S), + __DEFINE_LINK_MODE_PARAMS(50000, CR, Full, C), + __DEFINE_LINK_MODE_PARAMS_MEDIUMS(50000, LR_ER_FR, Full, + __MED(L) | __MED(E) | __MED(F)), + __DEFINE_LINK_MODE_PARAMS(50000, DR, Full, D), + __DEFINE_LINK_MODE_PARAMS(100000, KR2, Full, K), + __DEFINE_LINK_MODE_PARAMS(100000, SR2, Full, S), + __DEFINE_LINK_MODE_PARAMS(100000, CR2, Full, C), + __DEFINE_LINK_MODE_PARAMS_MEDIUMS(100000, LR2_ER2_FR2, Full, + __MED(L) | __MED(E) | __MED(F)), + __DEFINE_LINK_MODE_PARAMS(100000, DR2, Full, D), + __DEFINE_LINK_MODE_PARAMS(200000, KR4, Full, K), + __DEFINE_LINK_MODE_PARAMS(200000, SR4, Full, S), + __DEFINE_LINK_MODE_PARAMS_MEDIUMS(200000, LR4_ER4_FR4, Full, + __MED(L) | __MED(E) | __MED(F)), + __DEFINE_LINK_MODE_PARAMS(200000, DR4, Full, D), + __DEFINE_LINK_MODE_PARAMS(200000, CR4, Full, C), + __DEFINE_LINK_MODE_PARAMS(100, T1, Full, T), + __DEFINE_LINK_MODE_PARAMS(1000, T1, Full, T), + __DEFINE_LINK_MODE_PARAMS(400000, KR8, Full, K), + __DEFINE_LINK_MODE_PARAMS(400000, SR8, Full, S), + __DEFINE_LINK_MODE_PARAMS_MEDIUMS(400000, LR8_ER8_FR8, Full, + __MED(L) | __MED(E) | __MED(F)), + __DEFINE_LINK_MODE_PARAMS(400000, DR8, Full, D), + __DEFINE_LINK_MODE_PARAMS(400000, CR8, Full, C), __DEFINE_SPECIAL_MODE_PARAMS(FEC_LLRS), - __DEFINE_LINK_MODE_PARAMS(100000, KR, Full), - __DEFINE_LINK_MODE_PARAMS(100000, SR, Full), - __DEFINE_LINK_MODE_PARAMS(100000, LR_ER_FR, Full), - __DEFINE_LINK_MODE_PARAMS(100000, DR, Full), - __DEFINE_LINK_MODE_PARAMS(100000, CR, Full), - __DEFINE_LINK_MODE_PARAMS(200000, KR2, Full), - __DEFINE_LINK_MODE_PARAMS(200000, SR2, Full), - __DEFINE_LINK_MODE_PARAMS(200000, LR2_ER2_FR2, Full), - __DEFINE_LINK_MODE_PARAMS(200000, DR2, Full), - __DEFINE_LINK_MODE_PARAMS(200000, CR2, Full), - __DEFINE_LINK_MODE_PARAMS(400000, KR4, Full), - __DEFINE_LINK_MODE_PARAMS(400000, SR4, Full), - __DEFINE_LINK_MODE_PARAMS(400000, LR4_ER4_FR4, Full), - __DEFINE_LINK_MODE_PARAMS(400000, DR4, Full), - __DEFINE_LINK_MODE_PARAMS(400000, CR4, Full), - __DEFINE_LINK_MODE_PARAMS(100, FX, Half), - __DEFINE_LINK_MODE_PARAMS(100, FX, Full), - __DEFINE_LINK_MODE_PARAMS(10, T1L, Full), - __DEFINE_LINK_MODE_PARAMS(800000, CR8, Full), - __DEFINE_LINK_MODE_PARAMS(800000, KR8, Full), - __DEFINE_LINK_MODE_PARAMS(800000, DR8, Full), - __DEFINE_LINK_MODE_PARAMS(800000, DR8_2, Full), - __DEFINE_LINK_MODE_PARAMS(800000, SR8, Full), - __DEFINE_LINK_MODE_PARAMS(800000, VR8, Full), - __DEFINE_LINK_MODE_PARAMS(10, T1S, Full), - __DEFINE_LINK_MODE_PARAMS(10, T1S, Half), - __DEFINE_LINK_MODE_PARAMS(10, T1S_P2MP, Half), - __DEFINE_LINK_MODE_PARAMS(10, T1BRR, Full), - __DEFINE_LINK_MODE_PARAMS(200000, CR, Full), - __DEFINE_LINK_MODE_PARAMS(200000, KR, Full), - __DEFINE_LINK_MODE_PARAMS(200000, DR, Full), - __DEFINE_LINK_MODE_PARAMS(200000, DR_2, Full), - __DEFINE_LINK_MODE_PARAMS(200000, SR, Full), - __DEFINE_LINK_MODE_PARAMS(200000, VR, Full), - __DEFINE_LINK_MODE_PARAMS(400000, CR2, Full), - __DEFINE_LINK_MODE_PARAMS(400000, KR2, Full), - __DEFINE_LINK_MODE_PARAMS(400000, DR2, Full), - __DEFINE_LINK_MODE_PARAMS(400000, DR2_2, Full), - __DEFINE_LINK_MODE_PARAMS(400000, SR2, Full), - __DEFINE_LINK_MODE_PARAMS(400000, VR2, Full), - __DEFINE_LINK_MODE_PARAMS(800000, CR4, Full), - __DEFINE_LINK_MODE_PARAMS(800000, KR4, Full), - __DEFINE_LINK_MODE_PARAMS(800000, DR4, Full), - __DEFINE_LINK_MODE_PARAMS(800000, DR4_2, Full), - __DEFINE_LINK_MODE_PARAMS(800000, SR4, Full), - __DEFINE_LINK_MODE_PARAMS(800000, VR4, Full), + __DEFINE_LINK_MODE_PARAMS(100000, KR, Full, K), + __DEFINE_LINK_MODE_PARAMS(100000, SR, Full, S), + __DEFINE_LINK_MODE_PARAMS_MEDIUMS(100000, LR_ER_FR, Full, + __MED(L) | __MED(E) | __MED(F)), + __DEFINE_LINK_MODE_PARAMS(100000, DR, Full, D), + __DEFINE_LINK_MODE_PARAMS(100000, CR, Full, C), + __DEFINE_LINK_MODE_PARAMS(200000, KR2, Full, K), + __DEFINE_LINK_MODE_PARAMS(200000, SR2, Full, S), + __DEFINE_LINK_MODE_PARAMS_MEDIUMS(200000, LR2_ER2_FR2, Full, + __MED(L) | __MED(E) | __MED(F)), + __DEFINE_LINK_MODE_PARAMS(200000, DR2, Full, D), + __DEFINE_LINK_MODE_PARAMS(200000, CR2, Full, C), + __DEFINE_LINK_MODE_PARAMS(400000, KR4, Full, K), + __DEFINE_LINK_MODE_PARAMS(400000, SR4, Full, S), + __DEFINE_LINK_MODE_PARAMS_MEDIUMS(400000, LR4_ER4_FR4, Full, + __MED(L) | __MED(E) | __MED(F)), + __DEFINE_LINK_MODE_PARAMS(400000, DR4, Full, D), + __DEFINE_LINK_MODE_PARAMS(400000, CR4, Full, C), + __DEFINE_LINK_MODE_PARAMS(100, FX, Half, F), + __DEFINE_LINK_MODE_PARAMS(100, FX, Full, F), + __DEFINE_LINK_MODE_PARAMS(10, T1L, Full, T), + __DEFINE_LINK_MODE_PARAMS(800000, CR8, Full, C), + __DEFINE_LINK_MODE_PARAMS(800000, KR8, Full, K), + __DEFINE_LINK_MODE_PARAMS(800000, DR8, Full, D), + __DEFINE_LINK_MODE_PARAMS(800000, DR8_2, Full, D), + __DEFINE_LINK_MODE_PARAMS(800000, SR8, Full, S), + __DEFINE_LINK_MODE_PARAMS(800000, VR8, Full, V), + __DEFINE_LINK_MODE_PARAMS(10, T1S, Full, T), + __DEFINE_LINK_MODE_PARAMS(10, T1S, Half, T), + __DEFINE_LINK_MODE_PARAMS(10, T1S_P2MP, Half, T), + __DEFINE_LINK_MODE_PARAMS(10, T1BRR, Full, T), + __DEFINE_LINK_MODE_PARAMS(200000, CR, Full, C), + __DEFINE_LINK_MODE_PARAMS(200000, KR, Full, K), + __DEFINE_LINK_MODE_PARAMS(200000, DR, Full, D), + __DEFINE_LINK_MODE_PARAMS(200000, DR_2, Full, D), + __DEFINE_LINK_MODE_PARAMS(200000, SR, Full, S), + __DEFINE_LINK_MODE_PARAMS(200000, VR, Full, V), + __DEFINE_LINK_MODE_PARAMS(400000, CR2, Full, C), + __DEFINE_LINK_MODE_PARAMS(400000, KR2, Full, K), + __DEFINE_LINK_MODE_PARAMS(400000, DR2, Full, D), + __DEFINE_LINK_MODE_PARAMS(400000, DR2_2, Full, D), + __DEFINE_LINK_MODE_PARAMS(400000, SR2, Full, S), + __DEFINE_LINK_MODE_PARAMS(400000, VR2, Full, V), + __DEFINE_LINK_MODE_PARAMS(800000, CR4, Full, C), + __DEFINE_LINK_MODE_PARAMS(800000, KR4, Full, K), + __DEFINE_LINK_MODE_PARAMS(800000, DR4, Full, D), + __DEFINE_LINK_MODE_PARAMS(800000, DR4_2, Full, D), + __DEFINE_LINK_MODE_PARAMS(800000, SR4, Full, S), + __DEFINE_LINK_MODE_PARAMS(800000, VR4, Full, V), }; static_assert(ARRAY_SIZE(link_mode_params) =3D=3D __ETHTOOL_LINK_MODE_MASK= _NBITS); EXPORT_SYMBOL_GPL(link_mode_params); =20 +const char ethtool_link_medium_names[][ETH_GSTRING_LEN] =3D { + [ETHTOOL_LINK_MEDIUM_BASET] =3D "BaseT", + [ETHTOOL_LINK_MEDIUM_BASEK] =3D "BaseK", + [ETHTOOL_LINK_MEDIUM_BASES] =3D "BaseS", + [ETHTOOL_LINK_MEDIUM_BASEC] =3D "BaseC", + [ETHTOOL_LINK_MEDIUM_BASEL] =3D "BaseL", + [ETHTOOL_LINK_MEDIUM_BASED] =3D "BaseD", + [ETHTOOL_LINK_MEDIUM_BASEE] =3D "BaseE", + [ETHTOOL_LINK_MEDIUM_BASEF] =3D "BaseF", + [ETHTOOL_LINK_MEDIUM_BASEV] =3D "BaseV", + [ETHTOOL_LINK_MEDIUM_BASEMLD] =3D "BaseMLD", + [ETHTOOL_LINK_MEDIUM_NONE] =3D "None", +}; +static_assert(ARRAY_SIZE(ethtool_link_medium_names) =3D=3D __ETHTOOL_LINK_= MEDIUM_LAST); +EXPORT_SYMBOL_GPL(ethtool_link_medium_names); + const char netif_msg_class_names[][ETH_GSTRING_LEN] =3D { [NETIF_MSG_DRV_BIT] =3D "drv", [NETIF_MSG_PROBE_BIT] =3D "probe", --=20 2.49.0 From nobody Thu Oct 2 22:52:49 2025 Received: from smtpout-04.galae.net (smtpout-04.galae.net [185.171.202.116]) (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 3F8AF3568E8 for ; Tue, 9 Sep 2025 15:27:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.171.202.116 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431647; cv=none; b=PTS98GcuVi1d83/gePpAZZBVijBvhFE8KhN8IUrcFNz2x9ac8DKyYHe/Vv8Kwstkf4QS+JHAqfwL0gKUfnNP3mpxY62u2JFYdTVUKV8PSETw9s9pizsD4ObKrAfRXwzWOcLIH/fJJX5V6CAaJs99EnKWFiayZAq8fB5KkNpxiCw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431647; c=relaxed/simple; bh=OQa0uVPUF9VzAI4gFwlZETclaiIKfs2vNWwt7aDYV7k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fNAcfrhhcZaqcutwdw9JUO7EVr4/Ot2lsNMFBrrzzayQxHv3bNBWy7LORFNO69//xSSKAyjUuCuTWYksqQCJ5wgREq/Glc4D7OIR/kd5ro3FogOh2V+bzLh892KeCPtmk/cNaUCmWbkvNNW68p79PusDMSUvkw4VV+xlCf1yWEE= 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=Pu8S08in; arc=none smtp.client-ip=185.171.202.116 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="Pu8S08in" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-04.galae.net (Postfix) with ESMTPS id 14483C6B394; Tue, 9 Sep 2025 15:27:08 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id BDB3360630; Tue, 9 Sep 2025 15:27:23 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 4709A102F2584; Tue, 9 Sep 2025 17:27:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1757431642; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=GidDznFTJZwr4siUz9fkoNkPHfz5yVaFWqy5INuD/ig=; b=Pu8S08inF2wsrkQmjKUXhbyr4wMHkPR01g8U8oY/6ihvraVtnn2xUQtgRPB4lDEHOpq9eP vYCGJWmYwKIETrFVtgmklUGdJbhMEd+CIrQ9FdCwU3+WlYBBzcSXl+cftokhCy+3DukvdN 1DoZOAjNZPaw23WKeSkhvStwqq4gp8wVl8cHPfLIjwd14ELhgStAT6kMErSgG9DvtIqQQF b99MDWYsuriMzs/p1x6BgaTf0oyl2DzeF03qaozWGAaDYkRLgnlJwANn6HQztl3NuTq0Fv iZ0LEbC8yhW0l4YvrmloPD/xprsl5QTst/rx4GtzlRDI7Xxuk9b/k4VbrhAq3A== 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 Subject: [PATCH net-next v12 04/18] net: phy: Introduce PHY ports representation Date: Tue, 9 Sep 2025 17:26:00 +0200 Message-ID: <20250909152617.119554-5-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250909152617.119554-1-maxime.chevallier@bootlin.com> References: <20250909152617.119554-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 Content-Type: text/plain; charset="utf-8" Ethernet provides a wide variety of layer 1 protocols and standards for data transmission. The front-facing ports of an interface have their own complexity and configurability. Introduce a representation of these front-facing ports. The current code is minimalistic and only support ports controlled by PHY devices, but the plan is to extend that to SFP as well as raw Ethernet MACs that don't use PHY devices. This minimal port representation allows describing the media and number of lanes of a port. From that information, we can derive the linkmodes usable on the port, which can be used to limit the capabilities of an interface. For now, the port lanes and medium is derived from devicetree, defined by the PHY driver, or populated with default values (as we assume that all PHYs expose at least one port). The typical example is 100M ethernet. 100BaseT can work using only 2 lanes on a Cat 5 cables. However, in the situation where a 10/100/1000 capable PHY is wired to its RJ45 port through 2 lanes only, we have no way of detecting that. The "max-speed" DT property can be used, but a more accurate representation can be used : mdi { connector-0 { media =3D "BaseT"; lanes =3D <2>; }; }; From that information, we can derive the max speed reachable on the port. Another benefit of having that is to avoid vendor-specific DT properties (micrel,fiber-mode or ti,fiber-mode). This basic representation is meant to be expanded, by the introduction of port ops, userspace listing of ports, and support for multi-port devices. Signed-off-by: Maxime Chevallier Reviewed-by: Christophe Leroy Tested-by: Christophe Leroy Tested-by: Florian Fainelli Tested-by: Oleksij Rempel --- MAINTAINERS | 1 + drivers/net/phy/Makefile | 2 +- drivers/net/phy/phy-caps.h | 5 + drivers/net/phy/phy-core.c | 6 ++ drivers/net/phy/phy_caps.c | 56 +++++++++++ drivers/net/phy/phy_device.c | 185 +++++++++++++++++++++++++++++++++++ drivers/net/phy/phy_port.c | 135 +++++++++++++++++++++++++ include/linux/ethtool.h | 26 +++++ include/linux/phy.h | 55 +++++++++++ include/linux/phy_port.h | 96 ++++++++++++++++++ 10 files changed, 566 insertions(+), 1 deletion(-) create mode 100644 drivers/net/phy/phy_port.c create mode 100644 include/linux/phy_port.h diff --git a/MAINTAINERS b/MAINTAINERS index 384bb1dc8424..31e5293df595 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9127,6 +9127,7 @@ F: include/linux/of_net.h F: include/linux/phy.h F: include/linux/phy_fixed.h F: include/linux/phy_link_topology.h +F: include/linux/phy_port.h F: include/linux/phylib_stubs.h F: include/linux/platform_data/mdio-bcm-unimac.h F: include/linux/platform_data/mdio-gpio.h diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 402a33d559de..74922f350b0c 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -3,7 +3,7 @@ =20 libphy-y :=3D phy.o phy-c45.o phy-core.o phy_device.o \ linkmode.o phy_link_topology.o \ - phy_caps.o mdio_bus_provider.o + phy_caps.o mdio_bus_provider.o phy_port.o mdio-bus-y +=3D mdio_bus.o mdio_device.o =20 ifdef CONFIG_PHYLIB diff --git a/drivers/net/phy/phy-caps.h b/drivers/net/phy/phy-caps.h index 157759966650..01df1bdc1516 100644 --- a/drivers/net/phy/phy-caps.h +++ b/drivers/net/phy/phy-caps.h @@ -60,4 +60,9 @@ const struct link_capabilities * phy_caps_lookup(int speed, unsigned int duplex, const unsigned long *suppo= rted, bool exact); =20 +void phy_caps_medium_get_supported(unsigned long *supported, + enum ethtool_link_medium medium, + int lanes); +u32 phy_caps_mediums_from_linkmodes(unsigned long *linkmodes); + #endif /* __PHY_CAPS_H */ diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c index 605ca20ae192..6f825f63c1bf 100644 --- a/drivers/net/phy/phy-core.c +++ b/drivers/net/phy/phy-core.c @@ -4,6 +4,7 @@ */ #include #include +#include #include =20 #include "phylib.h" @@ -163,7 +164,12 @@ EXPORT_SYMBOL_GPL(phy_interface_num_ports); =20 static void __set_phy_supported(struct phy_device *phydev, u32 max_speed) { + struct phy_port *port; + phy_caps_linkmode_max_speed(max_speed, phydev->supported); + + phy_for_each_port(phydev, port) + phy_caps_linkmode_max_speed(max_speed, port->supported); } =20 /** diff --git a/drivers/net/phy/phy_caps.c b/drivers/net/phy/phy_caps.c index 990c36ccd9e7..e4efd5c477b4 100644 --- a/drivers/net/phy/phy_caps.c +++ b/drivers/net/phy/phy_caps.c @@ -384,3 +384,59 @@ unsigned long phy_caps_from_interface(phy_interface_t = interface) return link_caps; } EXPORT_SYMBOL_GPL(phy_caps_from_interface); + +/** + * phy_caps_medium_get_supported() - Returns linkmodes supported on a give= n medium + * @supported: After this call, contains all possible linkmodes on a given= medium, + * and with the given number of lanes, or less. + * @medium: The medium to get the support from + * @lanes: The number of lanes used on the given medium + * + * If no match exists, the supported field is left untouched. + */ +void phy_caps_medium_get_supported(unsigned long *supported, + enum ethtool_link_medium medium, + int lanes) +{ + int i; + + for (i =3D 0; i < __ETHTOOL_LINK_MODE_MASK_NBITS; i++) { + /* Special bits such as Autoneg, Pause, Asym_pause, etc. are + * set and will be masked away by the port parent. + */ + if (link_mode_params[i].mediums =3D=3D BIT(ETHTOOL_LINK_MEDIUM_NONE)) { + linkmode_set_bit(i, supported); + continue; + } + + /* For most cases, min_lanes =3D=3D lanes, except for 10/100BaseT that w= ork + * on 2 lanes but are compatible with 4 lanes mediums + */ + if (link_mode_params[i].mediums & BIT(medium) && + link_mode_params[i].min_lanes <=3D lanes) + linkmode_set_bit(i, supported); + } +} +EXPORT_SYMBOL_GPL(phy_caps_medium_get_supported); + +/** + * phy_caps_mediums_from_linkmodes() - Get all mediums from a linkmodes li= st + * @linkmodes: A bitset of linkmodes to get the mediums from + * + * Returns: A bitset of ETHTOOL_MEDIUM_XXX values corresponding to all med= ium + * types in the linkmodes list + */ +u32 phy_caps_mediums_from_linkmodes(unsigned long *linkmodes) +{ + const struct link_mode_info *linkmode; + u32 mediums =3D 0; + int i; + + for_each_set_bit(i, linkmodes, __ETHTOOL_LINK_MODE_MASK_NBITS) { + linkmode =3D &link_mode_params[i]; + mediums |=3D linkmode->mediums; + } + + return mediums; +} +EXPORT_SYMBOL_GPL(phy_caps_mediums_from_linkmodes); diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 7556aa3dd7ee..8f6bef8ee263 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -836,6 +837,13 @@ struct phy_device *phy_device_create(struct mii_bus *b= us, int addr, u32 phy_id, =20 dev->state =3D PHY_DOWN; INIT_LIST_HEAD(&dev->leds); + INIT_LIST_HEAD(&dev->ports); + + /* The driver's probe function must change that to the real number + * of ports possible on the PHY. We assume by default we are dealing + * with a single-port PHY + */ + dev->max_n_ports =3D 1; =20 mutex_init(&dev->lock); INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine); @@ -1579,6 +1587,51 @@ void phy_sfp_detach(void *upstream, struct sfp_bus *= bus) } EXPORT_SYMBOL(phy_sfp_detach); =20 +static int phy_add_port(struct phy_device *phydev, struct phy_port *port) +{ + int ret =3D 0; + + if (phydev->n_ports =3D=3D phydev->max_n_ports) + return -EBUSY; + + /* We set all ports as active by default, PHY drivers may deactivate + * them (when unused) + */ + port->active =3D true; + + if (port->is_mii) { + if (phydev->drv && phydev->drv->attach_mii_port) + ret =3D phydev->drv->attach_mii_port(phydev, port); + } else { + if (phydev->drv && phydev->drv->attach_mdi_port) + ret =3D phydev->drv->attach_mdi_port(phydev, port); + } + + if (ret) + return ret; + + /* The PHY driver might have added, removed or set medium/lanes info, + * so update the port supported accordingly. + */ + phy_port_update_supported(port); + + list_add(&port->head, &phydev->ports); + + phydev->n_ports++; + + return 0; +} + +static void phy_del_port(struct phy_device *phydev, struct phy_port *port) +{ + if (!phydev->n_ports) + return; + + list_del(&port->head); + + phydev->n_ports--; +} + /** * phy_sfp_probe - probe for a SFP cage attached to this PHY device * @phydev: Pointer to phy_device @@ -3312,6 +3365,131 @@ static int of_phy_leds(struct phy_device *phydev) return 0; } =20 +static void phy_cleanup_ports(struct phy_device *phydev) +{ + struct phy_port *tmp, *port; + + list_for_each_entry_safe(port, tmp, &phydev->ports, head) { + phy_del_port(phydev, port); + phy_port_destroy(port); + } +} + +static int phy_default_setup_single_port(struct phy_device *phydev) +{ + struct phy_port *port =3D phy_port_alloc(); + + if (!port) + return -ENOMEM; + + port->parent_type =3D PHY_PORT_PHY; + port->phy =3D phydev; + + /* Let the PHY driver know that this port was never described anywhere. + * This is the usual case, where we assume single-port PHY devices with + * no SFP. In that case, the port supports exactly the same thing as + * the PHY itself. + * + * However, this can also be because we have a combo-port PHY, with + * only one port described in DT, through SFP for example. + * + * In that case, the PHY driver will be in charge of saying what we can + * do on that non-represented port. + */ + port->not_described =3D true; + linkmode_copy(port->supported, phydev->supported); + port->mediums =3D phy_caps_mediums_from_linkmodes(port->supported); + + phy_add_port(phydev, port); + + return 0; +} + +static int of_phy_ports(struct phy_device *phydev) +{ + struct device_node *node =3D phydev->mdio.dev.of_node; + struct device_node *mdi; + struct phy_port *port; + int err; + + if (!IS_ENABLED(CONFIG_OF_MDIO)) + return 0; + + if (!node) + return 0; + + mdi =3D of_get_child_by_name(node, "mdi"); + if (!mdi) + return 0; + + for_each_available_child_of_node_scoped(mdi, port_node) { + port =3D phy_of_parse_port(port_node); + if (IS_ERR(port)) { + err =3D PTR_ERR(port); + goto out_err; + } + + port->parent_type =3D PHY_PORT_PHY; + port->phy =3D phydev; + err =3D phy_add_port(phydev, port); + if (err) + goto out_err; + } + of_node_put(mdi); + + return 0; + +out_err: + phy_cleanup_ports(phydev); + of_node_put(mdi); + return err; +} + +static int phy_setup_ports(struct phy_device *phydev) +{ + __ETHTOOL_DECLARE_LINK_MODE_MASK(ports_supported); + struct phy_port *port; + int ret; + + ret =3D of_phy_ports(phydev); + if (ret) + return ret; + + if (phydev->n_ports < phydev->max_n_ports) { + ret =3D phy_default_setup_single_port(phydev); + if (ret) + goto out; + } + + linkmode_zero(ports_supported); + + /* Aggregate the supported modes, which are made-up of : + * - What the PHY itself supports + * - What the sum of all ports support + */ + list_for_each_entry(port, &phydev->ports, head) + if (port->active) + linkmode_or(ports_supported, ports_supported, + port->supported); + + if (!linkmode_empty(ports_supported)) + linkmode_and(phydev->supported, phydev->supported, + ports_supported); + + /* For now, the phy->port field is set as the first active port's type */ + list_for_each_entry(port, &phydev->ports, head) + if (port->active) { + phydev->port =3D phy_port_get_type(port); + break; + } + + return 0; + +out: + phy_cleanup_ports(phydev); + return ret; +} + /** * fwnode_mdio_find_device - Given a fwnode, find the mdio_device * @fwnode: pointer to the mdio_device's fwnode @@ -3449,6 +3627,11 @@ static int phy_probe(struct device *dev) phydev->is_gigabit_capable =3D 1; =20 of_set_phy_supported(phydev); + + err =3D phy_setup_ports(phydev); + if (err) + goto out; + phy_advertise_supported(phydev); =20 /* Get PHY default EEE advertising modes and handle them as potentially @@ -3524,6 +3707,8 @@ static int phy_remove(struct device *dev) =20 phydev->state =3D PHY_DOWN; =20 + phy_cleanup_ports(phydev); + sfp_bus_del_upstream(phydev->sfp_bus); phydev->sfp_bus =3D NULL; =20 diff --git a/drivers/net/phy/phy_port.c b/drivers/net/phy/phy_port.c new file mode 100644 index 000000000000..cf897ed74c4c --- /dev/null +++ b/drivers/net/phy/phy_port.c @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* Framework to drive Ethernet ports + * + * Copyright (c) 2024 Maxime Chevallier + */ + +#include +#include +#include + +#include "phy-caps.h" + +/** + * phy_port_alloc() - Allocate a new phy_port + * + * Returns: a newly allocated struct phy_port, or NULL. + */ +struct phy_port *phy_port_alloc(void) +{ + struct phy_port *port; + + port =3D kzalloc(sizeof(*port), GFP_KERNEL); + if (!port) + return NULL; + + linkmode_zero(port->supported); + INIT_LIST_HEAD(&port->head); + + return port; +} +EXPORT_SYMBOL_GPL(phy_port_alloc); + +/** + * phy_port_destroy() - Free a struct phy_port + * @port: The port to destroy + */ +void phy_port_destroy(struct phy_port *port) +{ + kfree(port); +} +EXPORT_SYMBOL_GPL(phy_port_destroy); + +/** + * phy_of_parse_port() - Create a phy_port from a firmware representation + * @dn: device_node representation of the port, following the + * ethernet-connector.yaml binding + * + * Returns: a newly allocated and initialized phy_port pointer, or an ERR_= PTR. + */ +struct phy_port *phy_of_parse_port(struct device_node *dn) +{ + struct fwnode_handle *fwnode =3D of_fwnode_handle(dn); + enum ethtool_link_medium medium; + struct phy_port *port; + const char *med_str; + u32 lanes, mediums =3D 0; + int ret; + + ret =3D fwnode_property_read_u32(fwnode, "lanes", &lanes); + if (ret) + return ERR_PTR(ret); + + ret =3D fwnode_property_read_string(fwnode, "media", &med_str); + if (ret) + return ERR_PTR(ret); + + medium =3D ethtool_str_to_medium(med_str); + if (medium =3D=3D ETHTOOL_LINK_MEDIUM_NONE) + return ERR_PTR(-EINVAL); + + mediums |=3D BIT(medium); + + if (!mediums) + return ERR_PTR(-EINVAL); + + port =3D phy_port_alloc(); + if (!port) + return ERR_PTR(-ENOMEM); + + port->lanes =3D lanes; + port->mediums =3D mediums; + + return port; +} +EXPORT_SYMBOL_GPL(phy_of_parse_port); + +/** + * phy_port_update_supported() - Setup the port->supported field + * @port: the port to update + * + * Once the port's medium list and number of lanes has been configured bas= ed + * on firmware, straps and vendor-specific properties, this function may be + * called to update the port's supported linkmodes list. + * + * Any mode that was manually set in the port's supported list remains set. + */ +void phy_port_update_supported(struct phy_port *port) +{ + __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) =3D { 0 }; + int i, lanes =3D 1; + + /* If there's no lanes specified, we grab the default number of + * lanes as the max of the default lanes for each medium + */ + if (!port->lanes) + for_each_set_bit(i, &port->mediums, __ETHTOOL_LINK_MEDIUM_LAST) + lanes =3D max_t(int, lanes, phy_medium_default_lanes(i)); + + port->lanes =3D lanes; + + for_each_set_bit(i, &port->mediums, __ETHTOOL_LINK_MEDIUM_LAST) { + linkmode_zero(supported); + phy_caps_medium_get_supported(supported, i, port->lanes); + linkmode_or(port->supported, port->supported, supported); + } +} +EXPORT_SYMBOL_GPL(phy_port_update_supported); + +/** + * phy_port_get_type() - get the PORT_* attribute for that port. + * @port: The port we want the information from + * + * Returns: A PORT_XXX value. + */ +int phy_port_get_type(struct phy_port *port) +{ + if (port->mediums & BIT(ETHTOOL_LINK_MEDIUM_BASET)) + return PORT_TP; + + if (phy_port_is_fiber(port)) + return PORT_FIBRE; + + return PORT_OTHER; +} +EXPORT_SYMBOL_GPL(phy_port_get_type); diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index a0696cb840f7..baa5ec1d76ed 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -227,6 +227,10 @@ extern const struct link_mode_info link_mode_params[]; =20 extern const char ethtool_link_medium_names[][ETH_GSTRING_LEN]; =20 +#define ETHTOOL_MEDIUM_FIBER_BITS (BIT(ETHTOOL_LINK_MEDIUM_BASES) | \ + BIT(ETHTOOL_LINK_MEDIUM_BASEL) | \ + BIT(ETHTOOL_LINK_MEDIUM_BASEF)) + static inline const char *phy_mediums(enum ethtool_link_medium medium) { if (medium >=3D __ETHTOOL_LINK_MEDIUM_LAST) @@ -235,6 +239,28 @@ static inline const char *phy_mediums(enum ethtool_lin= k_medium medium) return ethtool_link_medium_names[medium]; } =20 +static inline enum ethtool_link_medium ethtool_str_to_medium(const char *s= tr) +{ + int i; + + for (i =3D 0; i < __ETHTOOL_LINK_MEDIUM_LAST; i++) + if (!strcmp(phy_mediums(i), str)) + return i; + + return ETHTOOL_LINK_MEDIUM_NONE; +} + +static inline int phy_medium_default_lanes(enum ethtool_link_medium medium) +{ + /* Let's consider that the default BaseT ethernet is BaseT4, i.e. + * Gigabit Ethernet. + */ + if (medium =3D=3D ETHTOOL_LINK_MEDIUM_BASET) + return 4; + + return 1; +} + /* declare a link mode bitmap */ #define __ETHTOOL_DECLARE_LINK_MODE_MASK(name) \ DECLARE_BITMAP(name, __ETHTOOL_LINK_MODE_MASK_NBITS) diff --git a/include/linux/phy.h b/include/linux/phy.h index 04553419adc3..a6cd0465b059 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -322,6 +322,7 @@ static inline long rgmii_clock(int speed) struct device; struct kernel_hwtstamp_config; struct phylink; +struct phy_port; struct sfp_bus; struct sfp_upstream_ops; struct sk_buff; @@ -616,6 +617,9 @@ struct macsec_ops; * @master_slave_state: Current master/slave configuration * @mii_ts: Pointer to time stamper callbacks * @psec: Pointer to Power Sourcing Equipment control struct + * @ports: List of PHY ports structures + * @n_ports: Number of ports currently attached to the PHY + * @max_n_ports: Max number of ports this PHY can expose * @lock: Mutex for serialization access to PHY * @state_queue: Work queue for state machine * @link_down_events: Number of times link was lost @@ -753,6 +757,10 @@ struct phy_device { struct mii_timestamper *mii_ts; struct pse_control *psec; =20 + struct list_head ports; + int n_ports; + int max_n_ports; + u8 mdix; u8 mdix_ctrl; =20 @@ -775,6 +783,9 @@ struct phy_device { =20 #define to_phy_device(__dev) container_of_const(to_mdio_device(__dev), str= uct phy_device, mdio) =20 +#define phy_for_each_port(phydev, port) \ + list_for_each_entry(port, &(phydev)->ports, head) + /** * struct phy_tdr_config - Configuration of a TDR raw test * @@ -1269,6 +1280,49 @@ struct phy_driver { * Returns the time in jiffies until the next update event. */ unsigned int (*get_next_update_time)(struct phy_device *dev); + + /** + * @attach_mii_port: Attach the given MII port to the PHY device + * @dev: PHY device to notify + * @port: The port being added + * + * Called when an MII port that needs to be driven by the PHY is found. + * + * The port that is being passed may or may not be initialized. If it is + * already initialized, it is by the generic port representation from + * devicetree, which superseeds any strapping or vendor-specific + * properties. + * + * If the port isn't initialized, the port->mediums and port->lanes + * fields must be set, possibly according to strapping information. + * + * The PHY driver must set the port->interfaces field to indicate the + * possible MII modes that this PHY can output on the port. + * + * Returns 0, or an error code. + */ + int (*attach_mii_port)(struct phy_device *dev, struct phy_port *port); + + /** + * @attach_mdi_port: Attach the given MII port to the PHY device + * @dev: PHY device to notify + * @port: The port being added + * + * Called when a port that needs to be driven by the PHY is found. The + * number of time this will be called depends on phydev->max_n_ports, + * which the driver can change in .probe(). + * + * The port that is being passed may or may not be initialized. If it is + * already initialized, it is by the generic port representation from + * devicetree, which superseeds any strapping or vendor-specific + * properties. + * + * If the port isn't initialized, the port->mediums and port->lanes + * fields must be set, possibly according to strapping information. + * + * Returns 0, or an error code. + */ + int (*attach_mdi_port)(struct phy_device *dev, struct phy_port *port); }; #define to_phy_driver(d) container_of_const(to_mdio_common_driver(d), \ struct phy_driver, mdiodrv) @@ -2023,6 +2077,7 @@ void phy_trigger_machine(struct phy_device *phydev); void phy_mac_interrupt(struct phy_device *phydev); void phy_start_machine(struct phy_device *phydev); void phy_stop_machine(struct phy_device *phydev); + void phy_ethtool_ksettings_get(struct phy_device *phydev, struct ethtool_link_ksettings *cmd); int phy_ethtool_ksettings_set(struct phy_device *phydev, diff --git a/include/linux/phy_port.h b/include/linux/phy_port.h new file mode 100644 index 000000000000..f47ac5f5ef9e --- /dev/null +++ b/include/linux/phy_port.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef __PHY_PORT_H +#define __PHY_PORT_H + +#include +#include +#include + +struct phy_port; + +/** + * enum phy_port_parent - The device this port is attached to + * + * @PHY_PORT_PHY: Indicates that the port is driven by a PHY device + */ +enum phy_port_parent { + PHY_PORT_PHY, +}; + +struct phy_port_ops { + /* Sometimes, the link state can be retrieved from physical, + * out-of-band channels such as the LOS signal on SFP. These + * callbacks allows notifying the port about state changes + */ + void (*link_up)(struct phy_port *port); + void (*link_down)(struct phy_port *port); + + /* If the port acts as a Media Independent Interface (Serdes port), + * configures the port with the relevant state and mode. When enable is + * not set, interface should be ignored + */ + int (*configure_mii)(struct phy_port *port, bool enable, phy_interface_t = interface); +}; + +/** + * struct phy_port - A representation of a network device physical interfa= ce + * + * @head: Used by the port's parent to list ports + * @parent_type: The type of device this port is directly connected to + * @phy: If the parent is PHY_PORT_PHYDEV, the PHY controlling that port + * @ops: Callback ops implemented by the port controller + * @lanes: The number of lanes (diff pairs) this port has, 0 if not applic= able + * @mediums: Bitmask of the physical mediums this port provides access to + * @supported: The link modes this port can expose, if this port is MDI (n= ot MII) + * @interfaces: The MII interfaces this port supports, if this port is MII + * @not_described: Indicates to the parent driver if this port isn't descr= ibed, + * so it's up to the parent to filter its capabilities. + * @active: Indicates if the port is currently part of the active link. + * @is_mii: Indicates if this port is MII (Media Independent Interface), + * or MDI (Media Dependent Interface). + */ +struct phy_port { + struct list_head head; + enum phy_port_parent parent_type; + union { + struct phy_device *phy; + }; + + const struct phy_port_ops *ops; + + int lanes; + unsigned long mediums; + __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); + DECLARE_PHY_INTERFACE_MASK(interfaces); + + unsigned int not_described:1; + unsigned int active:1; + unsigned int is_mii:1; +}; + +struct phy_port *phy_port_alloc(void); +void phy_port_destroy(struct phy_port *port); + +static inline struct phy_device *port_phydev(struct phy_port *port) +{ + return port->phy; +} + +struct phy_port *phy_of_parse_port(struct device_node *dn); + +static inline bool phy_port_is_copper(struct phy_port *port) +{ + return port->mediums =3D=3D BIT(ETHTOOL_LINK_MEDIUM_BASET); +} + +static inline bool phy_port_is_fiber(struct phy_port *port) +{ + return !!(port->mediums & ETHTOOL_MEDIUM_FIBER_BITS); +} + +void phy_port_update_supported(struct phy_port *port); + +int phy_port_get_type(struct phy_port *port); + +#endif --=20 2.49.0 From nobody Thu Oct 2 22:52:49 2025 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (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 16AB83570C4; Tue, 9 Sep 2025 15:27:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431653; cv=none; b=X1WITHbXS+GSDoYFNNmOyAg5HE4PabVHj50RIAr7ugclQWSPfYLBHEpPTYqLZIeL0ZCDGFFcL/4jCjigJCcEQg7HxDg2M2pwyOUmfT9NXB2jAW3Tni3eTKk5nWCxvIanaRoryNupptQ0pSQqXbwwCQ8ecZ2HnC4MyOkvAzGG5Bw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431653; c=relaxed/simple; bh=D2jcMQua3eSrJB6pY6nhLWxJt4N7RjySISDihOnq7/M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Eu5D3oXTFk2GY7t3pyxAsB+trc8JqcplbrRNwC3QCAw5h19O6H2oWZ4mDboHCyK/E8NJOlpb71RiHuQbjZBUR1N40oQT4hHWmtn33K5rO/VXAA/aG/KnGPrQUTDF/yTWlIOWd6gP/Y4sMlJ8BwwtvDDeQ87sIQxNmhL7C3akXck= 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=GWjlKDqa; arc=none smtp.client-ip=185.246.84.56 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="GWjlKDqa" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id 9ABA21A087F; Tue, 9 Sep 2025 15:27:30 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 6C8DD60630; Tue, 9 Sep 2025 15:27:30 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id DB8D6102F2835; Tue, 9 Sep 2025 17:27:22 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1757431649; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=cnnPXVHMdN2zHZd/dXgZMnTBDE0Y5BUkh+t5k0w6Te0=; b=GWjlKDqaXRidRMVPrNLgCYY3xq8fVaCEAdVeHV/DrG+jSeUxe/MF+7VgAdnOuYRcu/v/pZ a5lc5F5FNwL1xrMRYNKdf/armwI5gwcIqrpHX0xUiSPEl6IBQ4mu+Lha2LwLSXU+Ac5CPk 6t0cQLsbAXyJBXPdbAXaZqoVa2gjn5QidXbjkh2UM+zlBzC76QlpBnHWFZ+t1FtCyWVuyR 1DKvf9XXahKgQQtHg2az+NA9prLP29knsyseNx3BA5RK3Yszd2FU29UzPzr1kbw4DMcGFR s4McXvI8VAkL2YQfiPuJBjopW2w8nCaD+PNQeS0pilvk+X37wEnYuUxjFO3p5A== 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 Subject: [PATCH net-next v12 05/18] net: phy: dp83822: Add support for phy_port representation Date: Tue, 9 Sep 2025 17:26:01 +0200 Message-ID: <20250909152617.119554-6-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250909152617.119554-1-maxime.chevallier@bootlin.com> References: <20250909152617.119554-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 Content-Type: text/plain; charset="utf-8" With the phy_port representation introduced, we can use .attach_port to populate the port information based on either the straps or the ti,fiber-mode property. This allows simplifying the probe function and allow users to override the strapping configuration. Signed-off-by: Maxime Chevallier Reviewed-by: Christophe Leroy Tested-by: Christophe Leroy Tested-by: Florian Fainelli Tested-by: Oleksij Rempel --- drivers/net/phy/dp83822.c | 72 +++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 26 deletions(-) diff --git a/drivers/net/phy/dp83822.c b/drivers/net/phy/dp83822.c index 33db21251f2e..c6e5b7244658 100644 --- a/drivers/net/phy/dp83822.c +++ b/drivers/net/phy/dp83822.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include =20 @@ -811,17 +812,6 @@ static int dp83822_of_init(struct phy_device *phydev) int i, ret; u32 val; =20 - /* Signal detection for the PHY is only enabled if the FX_EN and the - * SD_EN pins are strapped. Signal detection can only enabled if FX_EN - * is strapped otherwise signal detection is disabled for the PHY. - */ - if (dp83822->fx_enabled && dp83822->fx_sd_enable) - dp83822->fx_signal_det_low =3D device_property_present(dev, - "ti,link-loss-low"); - if (!dp83822->fx_enabled) - dp83822->fx_enabled =3D device_property_present(dev, - "ti,fiber-mode"); - if (!device_property_read_string(dev, "ti,gpio2-clk-out", &of_val)) { if (strcmp(of_val, "mac-if") =3D=3D 0) { dp83822->gpio2_clk_out =3D DP83822_CLK_SRC_MAC_IF; @@ -950,6 +940,49 @@ static int dp83822_read_straps(struct phy_device *phyd= ev) return 0; } =20 +static int dp83822_attach_mdi_port(struct phy_device *phydev, + struct phy_port *port) +{ + struct dp83822_private *dp83822 =3D phydev->priv; + int ret; + + if (port->mediums) { + if (phy_port_is_fiber(port)) + dp83822->fx_enabled =3D true; + } else { + ret =3D dp83822_read_straps(phydev); + if (ret) + return ret; + +#if IS_ENABLED(CONFIG_OF_MDIO) + if (dp83822->fx_enabled && dp83822->fx_sd_enable) + dp83822->fx_signal_det_low =3D + device_property_present(&phydev->mdio.dev, + "ti,link-loss-low"); + + /* ti,fiber-mode is still used for backwards compatibility, but + * has been replaced with the mdi node definition, see + * ethernet-port.yaml + */ + if (!dp83822->fx_enabled) + dp83822->fx_enabled =3D + device_property_present(&phydev->mdio.dev, + "ti,fiber-mode"); +#endif /* CONFIG_OF_MDIO */ + + if (dp83822->fx_enabled) { + port->lanes =3D 1; + port->mediums =3D BIT(ETHTOOL_LINK_MEDIUM_BASEF); + } else { + /* This PHY can only to 100BaseTX max, so on 2 lanes */ + port->lanes =3D 2; + port->mediums =3D BIT(ETHTOOL_LINK_MEDIUM_BASET); + } + } + + return 0; +} + static int dp8382x_probe(struct phy_device *phydev) { struct dp83822_private *dp83822; @@ -968,27 +1001,13 @@ static int dp8382x_probe(struct phy_device *phydev) =20 static int dp83822_probe(struct phy_device *phydev) { - struct dp83822_private *dp83822; int ret; =20 ret =3D dp8382x_probe(phydev); if (ret) return ret; =20 - dp83822 =3D phydev->priv; - - ret =3D dp83822_read_straps(phydev); - if (ret) - return ret; - - ret =3D dp83822_of_init(phydev); - if (ret) - return ret; - - if (dp83822->fx_enabled) - phydev->port =3D PORT_FIBRE; - - return 0; + return dp83822_of_init(phydev); } =20 static int dp83826_probe(struct phy_device *phydev) @@ -1172,6 +1191,7 @@ static int dp83822_led_hw_control_get(struct phy_devi= ce *phydev, u8 index, .led_hw_is_supported =3D dp83822_led_hw_is_supported, \ .led_hw_control_set =3D dp83822_led_hw_control_set, \ .led_hw_control_get =3D dp83822_led_hw_control_get, \ + .attach_mdi_port =3D dp83822_attach_mdi_port \ } =20 #define DP83825_PHY_DRIVER(_id, _name) \ --=20 2.49.0 From nobody Thu Oct 2 22:52:49 2025 Received: from smtpout-04.galae.net (smtpout-04.galae.net [185.171.202.116]) (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 1683B3568E8; Tue, 9 Sep 2025 15:27:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.171.202.116 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431659; cv=none; b=PN1niiI/H3J+cLHeK9PUTyySe/pKkf+T5f5oa0Dw70GfNVMVoTxDTQnP3dn4d4YhE3EF1OYCQIUw/hgMUnSLUEsgm3VBOoK0bTSpfkvFbQegDxnJeGgQkCU4a5SddmsHq5NI0LDGrdYMqUVR+7GbDhD3BYTgnk4lIe5Rojzov0I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431659; c=relaxed/simple; bh=kbMGAe/+JsSLuCWsd7AR+VOoMSNtPCA9vp8M4T5pLvM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NdhVmUXUXMSRwpvEiESYNKdsE9vz0j3ETnHyuUfNZ7SFEtwsCvcKyGZP/ovIGEbZr+Dn6EdoOy70V8ATK95OuKIkZn+CBN9JN0Qre2bs5/+RbT4pvRODPBpYi8DF3XlPxF4UyZHTJxrJATIxQOmSAtM9/+Z2IMK0YQcXI/dCdw4= 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=DJr3rNnA; arc=none smtp.client-ip=185.171.202.116 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="DJr3rNnA" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-04.galae.net (Postfix) with ESMTPS id ADD06C6B394; Tue, 9 Sep 2025 15:27:20 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 62D2E60630; Tue, 9 Sep 2025 15:27:36 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 9533B102F2894; Tue, 9 Sep 2025 17:27:29 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1757431655; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=/eFmuXxcv4zqFJtRDHtymL8tVc/bHkF0tbu9C4LZkWc=; b=DJr3rNnAni696gcEK98fgIM3zzRIPWo8a9vRmCrxvaMOUOC22MQJUlL1hrXH4XKr3GH0N/ 3Y8eaentva/xUG3Ms8FuzGfFHOyLydyyjmX6MA1hdCQ4uee8ZtEu74tKcdXon1yWue8r9y XKPjR5aA+lLuxYeCYREuM3AGBXg+E6RYJGCtw9qgcVo9HzyF8Xn+Axmz40j4zf97iiMFaj uQIYFz9bdzZMRS8nuPTmpebTGYiMw74Eld73FwF77U/peRINgnEeD/19DybJJfvFce3omL L3r3x9soUARTfeTgmbcC3ZuDx+s7U5i/y0j+X0AJYpQnKkCNkEwHV7oq9v4JAQ== 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 Subject: [PATCH net-next v12 06/18] dt-bindings: net: dp83822: Deprecate ti,fiber-mode Date: Tue, 9 Sep 2025 17:26:02 +0200 Message-ID: <20250909152617.119554-7-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250909152617.119554-1-maxime.chevallier@bootlin.com> References: <20250909152617.119554-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 Content-Type: text/plain; charset="utf-8" The newly added ethernet-connector binding allows describing an Ethernet connector with greater precision, and in a more generic manner, than ti,fiber-mode. Deprecate this property. Reviewed-by: Rob Herring (Arm) Signed-off-by: Maxime Chevallier Reviewed-by: Christophe Leroy Tested-by: Christophe Leroy Tested-by: Florian Fainelli Tested-by: Oleksij Rempel --- Documentation/devicetree/bindings/net/ti,dp83822.yaml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/net/ti,dp83822.yaml b/Docume= ntation/devicetree/bindings/net/ti,dp83822.yaml index 28a0bddb9af9..dc6c50413a67 100644 --- a/Documentation/devicetree/bindings/net/ti,dp83822.yaml +++ b/Documentation/devicetree/bindings/net/ti,dp83822.yaml @@ -47,6 +47,9 @@ properties: is disabled. In fiber mode, auto-negotiation is disabled and the PHY can only wo= rk in 100base-fx (full and half duplex) modes. + This property is deprecated, for details please refer to + Documentation/devicetree/bindings/net/ethernet-connector.yaml + deprecated: true =20 rx-internal-delay-ps: description: | @@ -141,7 +144,12 @@ examples: tx-internal-delay-ps =3D <1>; ti,gpio2-clk-out =3D "xi"; mac-termination-ohms =3D <43>; + mdi { + connector-0 { + lanes =3D <1>; + media =3D "BaseF"; + }; + }; }; }; - ... --=20 2.49.0 From nobody Thu Oct 2 22:52:49 2025 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (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 9983B35AAC3; Tue, 9 Sep 2025 15:27:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431663; cv=none; b=EHDmdK9BrIxzuO9m2k72VFWI0VrMvG/yribfHyo+T2xB1xFR20WQaCvztmpj8zsg15mx92sl5qoPbVK/l2j3+nEPcpZuOmE2tgIkPq4zuuyfzdyNbfg9ZFilFFRMMo9jibbKOPEcApAjL0giNfPkxr/NrjlM/yL9a1c6ZscEiuo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431663; c=relaxed/simple; bh=oDwT/ytfZ0MIgQePhuGpYEa7Pg+a462k96DQXvNJP9c=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cw1VVVBhbkh2FS2Pi9yB/kC0JsEVrfD5dnfFnGfWNAF4734HL9bmfE+QNhD2Ndfk5+pQA5xLndzvkSWHoeCibVz4MOcqeIq79stY4LDdMdwrhvZjj1UGmyNOUOTf0TV+YG0MrWMTR5k1rHvvRv22uc7MR3ZJxFLNAsSsq/fuyPY= 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=CaxyKxzP; arc=none smtp.client-ip=185.246.84.56 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="CaxyKxzP" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id 223571A0A15; Tue, 9 Sep 2025 15:27:40 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id E8A3C60630; Tue, 9 Sep 2025 15:27:39 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 7FB00102F28E8; Tue, 9 Sep 2025 17:27:35 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1757431658; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=5SortobNjbuyn2TGqqPOApb9i2lqjDnCF5/SjqGdns0=; b=CaxyKxzPINy8o8BW6IMR6S1nQht76NJz2XhyvcrhNj9prZGFyU8ZJWpkNmq0Crg64RVTZx lVMN5oqGsDyGsy5INQGrPtOgx/7+GjZ45Rn6ZeDjTvg6AykNsHF0saFLbnqZWFqqT0B81r 4HQtKgHovL+OXLtqO/3O6x4CEWc0aYI8sPZLO/aFJdtOqoHs8vCh0D8/ZFId26kJa3JiVu lOZLPxcUhHFsLhd9H/fW93cWnmpQd10lZdnM4NHgdFPMOvsT8frUZEvnj7bn/g1BCmUiYm umA0vI852gdkUKsSLkMJXMzT94IejGyRpTr9rx/ugGPRKcA+5VkegDhbTZV8TA== 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 Subject: [PATCH net-next v12 07/18] net: phy: Create a phy_port for PHY-driven SFPs Date: Tue, 9 Sep 2025 17:26:03 +0200 Message-ID: <20250909152617.119554-8-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250909152617.119554-1-maxime.chevallier@bootlin.com> References: <20250909152617.119554-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 Content-Type: text/plain; charset="utf-8" Some PHY devices may be used as media-converters to drive SFP ports (for example, to allow using SFP when the SoC can only output RGMII). This is already supported to some extend by allowing PHY drivers to registers themselves as being SFP upstream. However, the logic to drive the SFP can actually be split to a per-port control logic, allowing support for multi-port PHYs, or PHYs that can either drive SFPs or Copper. To that extent, create a phy_port when registering an SFP bus onto a PHY. This port is considered a "serdes" port, in that it can feed data to anther entity on the link. The PHY driver needs to specify the various PHY_INTERFACE_MODE_XXX that this port supports. Reviewed-by: Christophe Leroy Signed-off-by: Maxime Chevallier Tested-by: Christophe Leroy Tested-by: Florian Fainelli Tested-by: Oleksij Rempel --- drivers/net/phy/phy_device.c | 24 ++++++++++++++++++++++++ drivers/net/phy/phy_port.c | 15 +++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 8f6bef8ee263..d195e15bde11 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1632,6 +1632,26 @@ static void phy_del_port(struct phy_device *phydev, = struct phy_port *port) phydev->n_ports--; } =20 +static int phy_setup_sfp_port(struct phy_device *phydev) +{ + struct phy_port *port =3D phy_port_alloc(); + + if (!port) + return -ENOMEM; + + port->parent_type =3D PHY_PORT_PHY; + port->phy =3D phydev; + + /* The PHY is a media converter, the port connected to the SFP cage + * is a MII port. + */ + port->is_mii =3D true; + + phy_add_port(phydev, port); + + return 0; +} + /** * phy_sfp_probe - probe for a SFP cage attached to this PHY device * @phydev: Pointer to phy_device @@ -1653,6 +1673,10 @@ int phy_sfp_probe(struct phy_device *phydev, ret =3D sfp_bus_add_upstream(bus, phydev, ops); sfp_bus_put(bus); } + + if (phydev->sfp_bus) + ret =3D phy_setup_sfp_port(phydev); + return ret; } EXPORT_SYMBOL(phy_sfp_probe); diff --git a/drivers/net/phy/phy_port.c b/drivers/net/phy/phy_port.c index cf897ed74c4c..6fecaa68350e 100644 --- a/drivers/net/phy/phy_port.c +++ b/drivers/net/phy/phy_port.c @@ -113,6 +113,21 @@ void phy_port_update_supported(struct phy_port *port) phy_caps_medium_get_supported(supported, i, port->lanes); linkmode_or(port->supported, port->supported, supported); } + + /* Serdes ports supported through SFP may not have any medium set, + * as they will output PHY_INTERFACE_MODE_XXX modes. In that case, derive + * the supported list based on these interfaces + */ + if (port->is_mii && linkmode_empty(supported)) { + unsigned long interface, link_caps =3D 0; + + /* Get each interface's caps */ + for_each_set_bit(interface, port->interfaces, + PHY_INTERFACE_MODE_MAX) + link_caps |=3D phy_caps_from_interface(interface); + + phy_caps_linkmodes(link_caps, port->supported); + } } EXPORT_SYMBOL_GPL(phy_port_update_supported); =20 --=20 2.49.0 From nobody Thu Oct 2 22:52:49 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 C65E635CEAE; Tue, 9 Sep 2025 15:27:44 +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=1757431666; cv=none; b=CMauWrJPr3LeOADltRwU1NHctNxaRQiZitJN+Y7u6Ekoqb1KHnXYJ5KrprBrbV3fTiuVaguGVKwpE4C9dyP9kE6s8dzyhHwKMLowtqbgT3Hm93qLL4dw5K+qmZl9T0HuxsLnLYqtPk43vHcEV181/gcE4lJuIPTLIPUy7Jn+ElI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431666; c=relaxed/simple; bh=1QMAyCDXwo1SikEcaFlARF6cxr9KS6vNXdDKCZOEwXw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=AMikczccr4LbgLEnp4mC/WEVX3MrRu8k6fxuKjYuRBp18Opl1IS6h0WEomdGvDWYfFkUpGrEGdmr2dF2cXX/EMdMAsPbws2AxL6uUwluaM0V0AqUs5joGspU+isZ3uMc6VSnNNEIszsFOEKcjI+KewqrNB3dF6lqDQaHMbblTLw= 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=uWg0ecE/; 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="uWg0ecE/" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 7732F4E40C65; Tue, 9 Sep 2025 15:27:43 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 4950F60630; Tue, 9 Sep 2025 15:27:43 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id E1DC5102F28E9; Tue, 9 Sep 2025 17:27:38 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1757431662; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=lD7+lQSQKyYNAl6cv68hGjklZWdRmevwGyMdpKSRhJs=; b=uWg0ecE/zjCzQB0CFjTtNvnEwmoHTqeLHVxGKicxn+9LQe/ZI4P+a5OOPGDtHrjW34CQVL qG4upSoRPCRbfyZCZUrALHmK7ITiKRnUwZnr/x1ay6PBXJtQEs0tM2af5iLA5tH73pSYtv 0EdxbiDmyl0uh3EiSWEbP4Fe1LKK2npQLSv/KAh1FH49mKcwHWegBUg9CCKB+hRdi3AKeH v7Zt/kKkzenqDAujWURfH3uyWlyzrq37shfl+Jhq/zsX4yHlpOZSsed0ZSRvkvb9Xd2tUn glmgHgKtK0FPJgEOgHbOAJiO5Y1yqzrNVo2kgxMZHf0Op4dy4vk6TPq56MrzHQ== 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 Subject: [PATCH net-next v12 08/18] net: phylink: Move phylink_interface_max_speed to phy_caps Date: Tue, 9 Sep 2025 17:26:04 +0200 Message-ID: <20250909152617.119554-9-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250909152617.119554-1-maxime.chevallier@bootlin.com> References: <20250909152617.119554-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 Content-Type: text/plain; charset="utf-8" The phylink_interface_max_speed() retrieves the max achievable speed on a MII interface. This logic needs to be re-used in other parts of the PHY stack, let's move it to phy_caps as it already contains most of the interface attribute accessors. Signed-off-by: Maxime Chevallier Reviewed-by: Christophe Leroy Tested-by: Christophe Leroy Tested-by: Florian Fainelli Tested-by: Oleksij Rempel --- drivers/net/phy/phy-caps.h | 1 + drivers/net/phy/phy_caps.c | 80 +++++++++++++++++++++++++++++++++++ drivers/net/phy/phylink.c | 87 ++------------------------------------ 3 files changed, 85 insertions(+), 83 deletions(-) diff --git a/drivers/net/phy/phy-caps.h b/drivers/net/phy/phy-caps.h index 01df1bdc1516..ba81cd75e122 100644 --- a/drivers/net/phy/phy-caps.h +++ b/drivers/net/phy/phy-caps.h @@ -49,6 +49,7 @@ void phy_caps_linkmode_max_speed(u32 max_speed, unsigned = long *linkmodes); bool phy_caps_valid(int speed, int duplex, const unsigned long *linkmodes); void phy_caps_linkmodes(unsigned long caps, unsigned long *linkmodes); unsigned long phy_caps_from_interface(phy_interface_t interface); +int phy_caps_interface_max_speed(phy_interface_t interface); =20 const struct link_capabilities * phy_caps_lookup_by_linkmode(const unsigned long *linkmodes); diff --git a/drivers/net/phy/phy_caps.c b/drivers/net/phy/phy_caps.c index e4efd5c477b4..b38c567ec6ef 100644 --- a/drivers/net/phy/phy_caps.c +++ b/drivers/net/phy/phy_caps.c @@ -440,3 +440,83 @@ u32 phy_caps_mediums_from_linkmodes(unsigned long *lin= kmodes) return mediums; } EXPORT_SYMBOL_GPL(phy_caps_mediums_from_linkmodes); + +/** + * phy_caps_interface_max_speed() - get the maximum speed of a phy interfa= ce + * @interface: phy interface mode defined by &typedef phy_interface_t + * + * Determine the maximum speed of a phy interface. This is intended to help + * determine the correct speed to pass to the MAC when the phy is performi= ng + * rate matching. + * + * Return: The maximum speed of @interface + */ +int phy_caps_interface_max_speed(phy_interface_t interface) +{ + switch (interface) { + case PHY_INTERFACE_MODE_100BASEX: + case PHY_INTERFACE_MODE_REVRMII: + case PHY_INTERFACE_MODE_RMII: + case PHY_INTERFACE_MODE_SMII: + case PHY_INTERFACE_MODE_REVMII: + case PHY_INTERFACE_MODE_MII: + case PHY_INTERFACE_MODE_MIILITE: + return SPEED_100; + + case PHY_INTERFACE_MODE_TBI: + case PHY_INTERFACE_MODE_MOCA: + case PHY_INTERFACE_MODE_RTBI: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_1000BASEKX: + case PHY_INTERFACE_MODE_TRGMII: + case PHY_INTERFACE_MODE_RGMII_TXID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_PSGMII: + case PHY_INTERFACE_MODE_QSGMII: + case PHY_INTERFACE_MODE_QUSGMII: + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_GMII: + return SPEED_1000; + + case PHY_INTERFACE_MODE_2500BASEX: + case PHY_INTERFACE_MODE_10G_QXGMII: + return SPEED_2500; + + case PHY_INTERFACE_MODE_5GBASER: + return SPEED_5000; + + case PHY_INTERFACE_MODE_XGMII: + case PHY_INTERFACE_MODE_RXAUI: + case PHY_INTERFACE_MODE_XAUI: + case PHY_INTERFACE_MODE_10GBASER: + case PHY_INTERFACE_MODE_10GKR: + case PHY_INTERFACE_MODE_USXGMII: + return SPEED_10000; + + case PHY_INTERFACE_MODE_25GBASER: + return SPEED_25000; + + case PHY_INTERFACE_MODE_XLGMII: + return SPEED_40000; + + case PHY_INTERFACE_MODE_50GBASER: + case PHY_INTERFACE_MODE_LAUI: + return SPEED_50000; + + case PHY_INTERFACE_MODE_100GBASEP: + return SPEED_100000; + + case PHY_INTERFACE_MODE_INTERNAL: + case PHY_INTERFACE_MODE_NA: + case PHY_INTERFACE_MODE_MAX: + /* No idea! Garbage in, unknown out */ + return SPEED_UNKNOWN; + } + + /* If we get here, someone forgot to add an interface mode above */ + WARN_ON_ONCE(1); + return SPEED_UNKNOWN; +} +EXPORT_SYMBOL_GPL(phy_caps_interface_max_speed); diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index c7cb95aa8007..091b1ee5c49a 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -218,85 +218,6 @@ static unsigned int phylink_interface_signal_rate(phy_= interface_t interface) } } =20 -/** - * phylink_interface_max_speed() - get the maximum speed of a phy interface - * @interface: phy interface mode defined by &typedef phy_interface_t - * - * Determine the maximum speed of a phy interface. This is intended to help - * determine the correct speed to pass to the MAC when the phy is performi= ng - * rate matching. - * - * Return: The maximum speed of @interface - */ -static int phylink_interface_max_speed(phy_interface_t interface) -{ - switch (interface) { - case PHY_INTERFACE_MODE_100BASEX: - case PHY_INTERFACE_MODE_REVRMII: - case PHY_INTERFACE_MODE_RMII: - case PHY_INTERFACE_MODE_SMII: - case PHY_INTERFACE_MODE_REVMII: - case PHY_INTERFACE_MODE_MII: - case PHY_INTERFACE_MODE_MIILITE: - return SPEED_100; - - case PHY_INTERFACE_MODE_TBI: - case PHY_INTERFACE_MODE_MOCA: - case PHY_INTERFACE_MODE_RTBI: - case PHY_INTERFACE_MODE_1000BASEX: - case PHY_INTERFACE_MODE_1000BASEKX: - case PHY_INTERFACE_MODE_TRGMII: - case PHY_INTERFACE_MODE_RGMII_TXID: - case PHY_INTERFACE_MODE_RGMII_RXID: - case PHY_INTERFACE_MODE_RGMII_ID: - case PHY_INTERFACE_MODE_RGMII: - case PHY_INTERFACE_MODE_PSGMII: - case PHY_INTERFACE_MODE_QSGMII: - case PHY_INTERFACE_MODE_QUSGMII: - case PHY_INTERFACE_MODE_SGMII: - case PHY_INTERFACE_MODE_GMII: - return SPEED_1000; - - case PHY_INTERFACE_MODE_2500BASEX: - case PHY_INTERFACE_MODE_10G_QXGMII: - return SPEED_2500; - - case PHY_INTERFACE_MODE_5GBASER: - return SPEED_5000; - - case PHY_INTERFACE_MODE_XGMII: - case PHY_INTERFACE_MODE_RXAUI: - case PHY_INTERFACE_MODE_XAUI: - case PHY_INTERFACE_MODE_10GBASER: - case PHY_INTERFACE_MODE_10GKR: - case PHY_INTERFACE_MODE_USXGMII: - return SPEED_10000; - - case PHY_INTERFACE_MODE_25GBASER: - return SPEED_25000; - - case PHY_INTERFACE_MODE_XLGMII: - return SPEED_40000; - - case PHY_INTERFACE_MODE_50GBASER: - case PHY_INTERFACE_MODE_LAUI: - return SPEED_50000; - - case PHY_INTERFACE_MODE_100GBASEP: - return SPEED_100000; - - case PHY_INTERFACE_MODE_INTERNAL: - case PHY_INTERFACE_MODE_NA: - case PHY_INTERFACE_MODE_MAX: - /* No idea! Garbage in, unknown out */ - return SPEED_UNKNOWN; - } - - /* If we get here, someone forgot to add an interface mode above */ - WARN_ON_ONCE(1); - return SPEED_UNKNOWN; -} - static struct { unsigned long mask; int speed; @@ -430,7 +351,7 @@ static unsigned long phylink_get_capabilities(phy_inter= face_t interface, int rate_matching) { unsigned long link_caps =3D phy_caps_from_interface(interface); - int max_speed =3D phylink_interface_max_speed(interface); + int max_speed =3D phy_caps_interface_max_speed(interface); unsigned long caps =3D MAC_SYM_PAUSE | MAC_ASYM_PAUSE; unsigned long matched_caps =3D 0; =20 @@ -1529,7 +1450,7 @@ static void phylink_link_up(struct phylink *pl, * the link_state) to the interface speed, and will send * pause frames to the MAC to limit its transmission speed. */ - speed =3D phylink_interface_max_speed(link_state.interface); + speed =3D phy_caps_interface_max_speed(link_state.interface); duplex =3D DUPLEX_FULL; rx_pause =3D true; break; @@ -1539,7 +1460,7 @@ static void phylink_link_up(struct phylink *pl, * the link_state) to the interface speed, and will cause * collisions to the MAC to limit its transmission speed. */ - speed =3D phylink_interface_max_speed(link_state.interface); + speed =3D phy_caps_interface_max_speed(link_state.interface); duplex =3D DUPLEX_HALF; break; } @@ -2732,7 +2653,7 @@ static phy_interface_t phylink_sfp_select_interface_s= peed(struct phylink *pl, if (!test_bit(interface, pl->sfp_interfaces)) continue; =20 - max_speed =3D phylink_interface_max_speed(interface); + max_speed =3D phy_caps_interface_max_speed(interface); =20 /* The logic here is: if speed =3D=3D max_speed, then we've found * the best interface. Otherwise we find the interface that --=20 2.49.0 From nobody Thu Oct 2 22:52:49 2025 Received: from smtpout-04.galae.net (smtpout-04.galae.net [185.171.202.116]) (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 3818B352FEE; Tue, 9 Sep 2025 15:27:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.171.202.116 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431670; cv=none; b=XX1P3EZkQmgQVmOUOJx+DJ7900/ZQbqvlJIaMFyPlivScO4Dba/mtTqF7v3xH5jz/s96LFt8jehuYewfw+ShJ9VPQHZNvaFZFde1Bloln3eWRoargZB1M+KPv7dHPWFr7o8864GE4Wk7QHaxycfyK6HynRT0t/BRGIIpptb6+Lc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431670; c=relaxed/simple; bh=o5FYh3oTZugN9LT68qVrM5gz/OPBK7ZZw3rN85EunQA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bQefWW7NHzbg4NluSMg+cNVMEMDW7pLcPJu/Px06D8Eg39+dusdeBRBCqDEgc/fIXcj4da9k3b0E7G+gc06fx7WMNKQJZ8kL1zCB/DK2tvjPjBHia5IxRm58MrgqiOEGkYWJkJ3azwuo02+YDIdvHjF1hk/3zWziqc6pk2Ot8jg= 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=iGEhGuuC; arc=none smtp.client-ip=185.171.202.116 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="iGEhGuuC" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-04.galae.net (Postfix) with ESMTPS id 4A324C6B394; Tue, 9 Sep 2025 15:27:31 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 002F560630; Tue, 9 Sep 2025 15:27:47 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 81548102F28B4; Tue, 9 Sep 2025 17:27:42 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1757431665; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=s4q+SEA1JILehYKkJLFt8JUFivmtIE7L8Bs9yFeUzdQ=; b=iGEhGuuCt+fSYRZ91tqfX/q9s0Jen6eOnvIRm32d5D/iQF+UzD4S1fdYipjSztGQFVCmoz mBTqyD+jQzdBxoIavK531VksHXEh9btxzwheB0qzCDDhdKFnXV33cyVSDvNv+zUr2Bm+SN a7Iw89XRl2C10g1mLhw/WgtLR1BJT5oLMwYU8Wj2SIDEfKW3QAJ4mHcEAkGGIU47bFH/M0 5/bcKnI5QZqKT+t6iMO2rHi0ycmlcUdlxHqRHcAG5h9Q6Ksrq7M+SrX9Not/YlI7E2bCRQ f/28N6jql6w90qcj1FP0efuL/LYFAhYfPnpGR1bkX4bz6PJdz/t3HqGuIYqBoA== 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 Subject: [PATCH net-next v12 09/18] net: phylink: Move sfp interface selection and filtering to phy_caps Date: Tue, 9 Sep 2025 17:26:05 +0200 Message-ID: <20250909152617.119554-10-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250909152617.119554-1-maxime.chevallier@bootlin.com> References: <20250909152617.119554-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 Content-Type: text/plain; charset="utf-8" Phylink's helpers to get the interfaces usable on an SFP module based on speed and linkmodes can be modes to phy_caps, so that it can benefit to PHY-driver SFP support. Signed-off-by: Maxime Chevallier Reviewed-by: Christophe Leroy Tested-by: Christophe Leroy Tested-by: Florian Fainelli Tested-by: Oleksij Rempel --- drivers/net/phy/phy-caps.h | 6 ++++ drivers/net/phy/phy_caps.c | 72 ++++++++++++++++++++++++++++++++++++++ drivers/net/phy/phylink.c | 72 +++++--------------------------------- 3 files changed, 86 insertions(+), 64 deletions(-) diff --git a/drivers/net/phy/phy-caps.h b/drivers/net/phy/phy-caps.h index ba81cd75e122..ebed340a2e77 100644 --- a/drivers/net/phy/phy-caps.h +++ b/drivers/net/phy/phy-caps.h @@ -66,4 +66,10 @@ void phy_caps_medium_get_supported(unsigned long *suppor= ted, int lanes); u32 phy_caps_mediums_from_linkmodes(unsigned long *linkmodes); =20 +void phy_caps_filter_sfp_interfaces(unsigned long *dst, + const unsigned long *interfaces); +phy_interface_t phy_caps_select_sfp_interface_speed(const unsigned long *i= nterfaces, + u32 speed); +phy_interface_t phy_caps_choose_sfp_interface(const unsigned long *interfa= ces); + #endif /* __PHY_CAPS_H */ diff --git a/drivers/net/phy/phy_caps.c b/drivers/net/phy/phy_caps.c index b38c567ec6ef..e4adc36e0fe3 100644 --- a/drivers/net/phy/phy_caps.c +++ b/drivers/net/phy/phy_caps.c @@ -63,6 +63,22 @@ static int speed_duplex_to_capa(int speed, unsigned int = duplex) #define for_each_link_caps_desc_speed(cap) \ for (cap =3D &link_caps[__LINK_CAPA_MAX - 1]; cap >=3D link_caps; cap--) =20 +static const phy_interface_t phy_caps_sfp_interface_preference[] =3D { + PHY_INTERFACE_MODE_100GBASEP, + PHY_INTERFACE_MODE_50GBASER, + PHY_INTERFACE_MODE_LAUI, + PHY_INTERFACE_MODE_25GBASER, + PHY_INTERFACE_MODE_USXGMII, + PHY_INTERFACE_MODE_10GBASER, + PHY_INTERFACE_MODE_5GBASER, + PHY_INTERFACE_MODE_2500BASEX, + PHY_INTERFACE_MODE_SGMII, + PHY_INTERFACE_MODE_1000BASEX, + PHY_INTERFACE_MODE_100BASEX, +}; + +static DECLARE_PHY_INTERFACE_MASK(phy_caps_sfp_interfaces); + /** * phy_caps_init() - Initializes the link_caps array from the link_mode_pa= rams. * @@ -100,6 +116,10 @@ int phy_caps_init(void) __set_bit(i, link_caps[capa].linkmodes); } =20 + for (int i =3D 0; i < ARRAY_SIZE(phy_caps_sfp_interface_preference); ++i) + __set_bit(phy_caps_sfp_interface_preference[i], + phy_caps_sfp_interfaces); + return 0; } =20 @@ -520,3 +540,55 @@ int phy_caps_interface_max_speed(phy_interface_t inter= face) return SPEED_UNKNOWN; } EXPORT_SYMBOL_GPL(phy_caps_interface_max_speed); + +void phy_caps_filter_sfp_interfaces(unsigned long *dst, + const unsigned long *interfaces) +{ + phy_interface_and(dst, interfaces, phy_caps_sfp_interfaces); +} + +phy_interface_t +phy_caps_select_sfp_interface_speed(const unsigned long *interfaces, u32 s= peed) +{ + phy_interface_t best_interface =3D PHY_INTERFACE_MODE_NA; + phy_interface_t interface; + u32 max_speed; + int i; + + for (i =3D 0; i < ARRAY_SIZE(phy_caps_sfp_interface_preference); i++) { + interface =3D phy_caps_sfp_interface_preference[i]; + if (!test_bit(interface, interfaces)) + continue; + + max_speed =3D phy_caps_interface_max_speed(interface); + + /* The logic here is: if speed =3D=3D max_speed, then we've found + * the best interface. Otherwise we find the interface that + * can just support the requested speed. + */ + if (max_speed >=3D speed) + best_interface =3D interface; + + if (max_speed <=3D speed) + break; + } + + return best_interface; +} +EXPORT_SYMBOL_GPL(phy_caps_select_sfp_interface_speed); + +phy_interface_t phy_caps_choose_sfp_interface(const unsigned long *interfa= ces) +{ + phy_interface_t interface; + size_t i; + + interface =3D PHY_INTERFACE_MODE_NA; + for (i =3D 0; i < ARRAY_SIZE(phy_caps_sfp_interface_preference); i++) + if (test_bit(phy_caps_sfp_interface_preference[i], interfaces)) { + interface =3D phy_caps_sfp_interface_preference[i]; + break; + } + + return interface; +} +EXPORT_SYMBOL_GPL(phy_caps_choose_sfp_interface); diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 091b1ee5c49a..91111ea1b149 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -126,22 +126,6 @@ do { \ }) #endif =20 -static const phy_interface_t phylink_sfp_interface_preference[] =3D { - PHY_INTERFACE_MODE_100GBASEP, - PHY_INTERFACE_MODE_50GBASER, - PHY_INTERFACE_MODE_LAUI, - PHY_INTERFACE_MODE_25GBASER, - PHY_INTERFACE_MODE_USXGMII, - PHY_INTERFACE_MODE_10GBASER, - PHY_INTERFACE_MODE_5GBASER, - PHY_INTERFACE_MODE_2500BASEX, - PHY_INTERFACE_MODE_SGMII, - PHY_INTERFACE_MODE_1000BASEX, - PHY_INTERFACE_MODE_100BASEX, -}; - -static DECLARE_PHY_INTERFACE_MASK(phylink_sfp_interfaces); - /** * phylink_set_port_modes() - set the port type modes in the ethtool mask * @mask: ethtool link mode mask @@ -1922,8 +1906,7 @@ static int phylink_validate_phy(struct phylink *pl, s= truct phy_device *phy, /* If the PHY is on a SFP, limit the interfaces to * those that can be used with a SFP module. */ - phy_interface_and(interfaces, interfaces, - phylink_sfp_interfaces); + phy_caps_filter_sfp_interfaces(interfaces, interfaces); =20 if (phy_interface_empty(interfaces)) { phylink_err(pl, "SFP PHY's possible interfaces becomes empty\n"); @@ -2643,34 +2626,16 @@ static phy_interface_t phylink_sfp_select_interface= (struct phylink *pl, static phy_interface_t phylink_sfp_select_interface_speed(struct phylink *= pl, u32 speed) { - phy_interface_t best_interface =3D PHY_INTERFACE_MODE_NA; phy_interface_t interface; - u32 max_speed; - int i; - - for (i =3D 0; i < ARRAY_SIZE(phylink_sfp_interface_preference); i++) { - interface =3D phylink_sfp_interface_preference[i]; - if (!test_bit(interface, pl->sfp_interfaces)) - continue; - - max_speed =3D phy_caps_interface_max_speed(interface); =20 - /* The logic here is: if speed =3D=3D max_speed, then we've found - * the best interface. Otherwise we find the interface that - * can just support the requested speed. - */ - if (max_speed >=3D speed) - best_interface =3D interface; - - if (max_speed <=3D speed) - break; - } + interface =3D phy_caps_select_sfp_interface_speed(pl->sfp_interfaces, + speed); =20 - if (best_interface =3D=3D PHY_INTERFACE_MODE_NA) + if (interface =3D=3D PHY_INTERFACE_MODE_NA) phylink_err(pl, "selection of interface failed, speed %u\n", speed); =20 - return best_interface; + return interface; } =20 static void phylink_merge_link_mode(unsigned long *dst, const unsigned lon= g *b) @@ -3450,17 +3415,7 @@ static void phylink_sfp_detach(void *upstream, struc= t sfp_bus *bus) static phy_interface_t phylink_choose_sfp_interface(struct phylink *pl, const unsigned long *intf) { - phy_interface_t interface; - size_t i; - - interface =3D PHY_INTERFACE_MODE_NA; - for (i =3D 0; i < ARRAY_SIZE(phylink_sfp_interface_preference); i++) - if (test_bit(phylink_sfp_interface_preference[i], intf)) { - interface =3D phylink_sfp_interface_preference[i]; - break; - } - - return interface; + return phy_caps_choose_sfp_interface(intf); } =20 static void phylink_sfp_set_config(struct phylink *pl, unsigned long *supp= orted, @@ -3737,8 +3692,8 @@ static int phylink_sfp_connect_phy(void *upstream, st= ruct phy_device *phy) phy_support_asym_pause(phy); =20 /* Set the PHY's host supported interfaces */ - phy_interface_and(phy->host_interfaces, phylink_sfp_interfaces, - pl->config->supported_interfaces); + phy_caps_filter_sfp_interfaces(phy->host_interfaces, + pl->config->supported_interfaces); =20 /* Do the initial configuration */ return phylink_sfp_config_phy(pl, phy); @@ -4166,16 +4121,5 @@ void phylink_mii_c45_pcs_get_state(struct mdio_devic= e *pcs, } EXPORT_SYMBOL_GPL(phylink_mii_c45_pcs_get_state); =20 -static int __init phylink_init(void) -{ - for (int i =3D 0; i < ARRAY_SIZE(phylink_sfp_interface_preference); ++i) - __set_bit(phylink_sfp_interface_preference[i], - phylink_sfp_interfaces); - - return 0; -} - -module_init(phylink_init); - MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("phylink models the MAC to optional PHY connection"); --=20 2.49.0 From nobody Thu Oct 2 22:52:49 2025 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (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 F3C8235FC06 for ; Tue, 9 Sep 2025 15:27:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431674; cv=none; b=uwPJIkAkZ+qQmRRSZBRxbiIrR/iMHyy7o+PL8jxPSGiq3A/0LgJ+t6z6FxrPuwgAAD8Aj17GTgkPMBzB7iySLl1TtcB6dJnyDnl+wqqsFJ3eMmRQWJjEmnALgMELL/EqogDNFLjwAF3TAYJAxlm/APZ7iXVUpqTzRfQaJ31EfBk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431674; c=relaxed/simple; bh=EE/5ok3OR5vAZOrQHO8/ZRplYPCIDe4gPHmzH2vflqo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SUQsOSTTA3n9yGibUgFcfCApk3UqTQPwnxC3PdPl8D1y0fzoy/9Jmu0KuG76jJbfef/0UP8Tx3d7cEEY5r/hYTAPAfLvqSdHt883zhWIV9zXAXJjujf/h7XNxRP5Nbdn9IF9mz+ZSqrtounKma1GSAH3YBMrLfMXnrq2kGrLy/I= 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=m+dqVcDy; arc=none smtp.client-ip=185.246.84.56 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="m+dqVcDy" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id 75D9C1A087F; Tue, 9 Sep 2025 15:27:51 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 4B4C760630; Tue, 9 Sep 2025 15:27:51 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 091DC102F2993; Tue, 9 Sep 2025 17:27:45 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1757431669; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=zNhWK752cxcpDpbOsrh4PVDPs4ps7jznAASK1JhMrSU=; b=m+dqVcDysbImEJzSl2cVCskbv06Fq1F6rMe6mWfD0+nWf8A2iyRof8Yb4Wv9aqDq1LxrdB 9hXhZHGx5Rruuuc+CnCFgfyi+O976WhAEfBrlfq9SfuX+OxOkJVAq9dULcuKyMOA0ZwHEd NQokvABu5tjsCOLvfW66IJ1tcL0pX5hU9o96FSH8ZRY9+ACjSVw3mP08ZCuaejlWtkPuKP s/CZIHLxdbGr0qH4SJFFqZXmz/v9HdMP/DRwRYrOF2IyaNKbq0RbglSu0bImiqmq90zeHJ /3qTva634OJ0WEidB7G9ttf1rxnCrKTc6p9QxtnWCzV4HHcol8oqaQ5BX5RbBg== 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 Subject: [PATCH net-next v12 10/18] net: phy: Introduce generic SFP handling for PHY drivers Date: Tue, 9 Sep 2025 17:26:06 +0200 Message-ID: <20250909152617.119554-11-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250909152617.119554-1-maxime.chevallier@bootlin.com> References: <20250909152617.119554-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 Content-Type: text/plain; charset="utf-8" There are currently 4 PHY drivers that can drive downstream SFPs: marvell.c, marvell10g.c, at803x.c and marvell-88x2222.c. Most of the logic is boilerplate, either calling into generic phylib helpers (for SFP PHY attach, bus attach, etc.) or performing the same tasks with a bit of validation : - Getting the module's expected interface mode - Making sure the PHY supports it - Optionaly perform some configuration to make sure the PHY outputs the right mode This can be made more generic by leveraging the phy_port, and its configure_mii() callback which allows setting a port's interfaces when the port is a serdes. Introduce a generic PHY SFP support. If a driver doesn't probe the SFP bus itself, but an SFP phandle is found in devicetree/firmware, then the generic PHY SFP support will be used, relying on port ops. PHY driver need to : - Register a .attach_port() callback - When a serdes port is registered to the PHY, drivers must set port->interfaces to the set of PHY_INTERFACE_MODE the port can output - If the port has limitations regarding speed, duplex and aneg, the port can also fine-tune the final linkmodes that can be supported - The port may register a set of ops, including .configure_mii(), that will be called at module_insert time to adjust the interface based on the module detected. Reviewed-by: Christophe Leroy Signed-off-by: Maxime Chevallier Tested-by: Christophe Leroy Tested-by: Florian Fainelli Tested-by: Oleksij Rempel --- drivers/net/phy/phy_device.c | 109 +++++++++++++++++++++++++++++++++++ include/linux/phy.h | 2 + include/linux/phy_port.h | 2 + 3 files changed, 113 insertions(+) diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index d195e15bde11..7b8ec7be473c 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1587,6 +1587,88 @@ void phy_sfp_detach(void *upstream, struct sfp_bus *= bus) } EXPORT_SYMBOL(phy_sfp_detach); =20 +static int phy_sfp_module_insert(void *upstream, const struct sfp_eeprom_i= d *id) +{ + struct phy_device *phydev =3D upstream; + struct phy_port *port; + + __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support); + DECLARE_PHY_INTERFACE_MASK(interfaces); + phy_interface_t iface; + + linkmode_zero(sfp_support); + + port =3D phy_get_sfp_port(phydev); + if (!port) + return -EINVAL; + + sfp_parse_support(phydev->sfp_bus, id, sfp_support, interfaces); + + if (phydev->n_ports =3D=3D 1) + phydev->port =3D sfp_parse_port(phydev->sfp_bus, id, sfp_support); + + linkmode_and(sfp_support, port->supported, sfp_support); + linkmode_and(interfaces, interfaces, port->interfaces); + + if (linkmode_empty(sfp_support)) { + dev_err(&phydev->mdio.dev, "incompatible SFP module inserted, no common = linkmode\n"); + return -EINVAL; + } + + iface =3D phy_caps_choose_sfp_interface(interfaces); + if (iface =3D=3D PHY_INTERFACE_MODE_NA) { + dev_err(&phydev->mdio.dev, "PHY %s does not support the SFP module's req= uested MII interfaces\n", + phydev_name(phydev)); + return -EINVAL; + } + + if (port->ops && port->ops->configure_mii) + return port->ops->configure_mii(port, true, iface); + + return 0; +} + +static void phy_sfp_module_remove(void *upstream) +{ + struct phy_device *phydev =3D upstream; + struct phy_port *port =3D phy_get_sfp_port(phydev); + + if (port && port->ops && port->ops->configure_mii) + port->ops->configure_mii(port, false, PHY_INTERFACE_MODE_NA); + + if (phydev->n_ports =3D=3D 1) + phydev->port =3D PORT_NONE; +} + +static void phy_sfp_link_up(void *upstream) +{ + struct phy_device *phydev =3D upstream; + struct phy_port *port =3D phy_get_sfp_port(phydev); + + if (port && port->ops && port->ops->link_up) + port->ops->link_up(port); +} + +static void phy_sfp_link_down(void *upstream) +{ + struct phy_device *phydev =3D upstream; + struct phy_port *port =3D phy_get_sfp_port(phydev); + + if (port && port->ops && port->ops->link_down) + port->ops->link_down(port); +} + +static const struct sfp_upstream_ops sfp_phydev_ops =3D { + .attach =3D phy_sfp_attach, + .detach =3D phy_sfp_detach, + .module_insert =3D phy_sfp_module_insert, + .module_remove =3D phy_sfp_module_remove, + .link_up =3D phy_sfp_link_up, + .link_down =3D phy_sfp_link_down, + .connect_phy =3D phy_sfp_connect_phy, + .disconnect_phy =3D phy_sfp_disconnect_phy, +}; + static int phy_add_port(struct phy_device *phydev, struct phy_port *port) { int ret =3D 0; @@ -1646,6 +1728,7 @@ static int phy_setup_sfp_port(struct phy_device *phyd= ev) * is a MII port. */ port->is_mii =3D true; + port->is_sfp =3D true; =20 phy_add_port(phydev, port); =20 @@ -3479,6 +3562,13 @@ static int phy_setup_ports(struct phy_device *phydev) if (ret) return ret; =20 + /* Use generic SFP probing only if the driver didn't do so already */ + if (!phydev->sfp_bus) { + ret =3D phy_sfp_probe(phydev, &sfp_phydev_ops); + if (ret) + goto out; + } + if (phydev->n_ports < phydev->max_n_ports) { ret =3D phy_default_setup_single_port(phydev); if (ret) @@ -3514,6 +3604,25 @@ static int phy_setup_ports(struct phy_device *phydev) return ret; } =20 +/** + * phy_get_sfp_port() - Returns the first valid SFP port of a PHY + * @phydev: pointer to the PHY device to get the SFP port from + * + * Returns: The first active SFP (serdes) port of a PHY device, NULL if no= ne + * exist. + */ +struct phy_port *phy_get_sfp_port(struct phy_device *phydev) +{ + struct phy_port *port; + + list_for_each_entry(port, &phydev->ports, head) + if (port->active && port->is_sfp) + return port; + + return NULL; +} +EXPORT_SYMBOL_GPL(phy_get_sfp_port); + /** * fwnode_mdio_find_device - Given a fwnode, find the mdio_device * @fwnode: pointer to the mdio_device's fwnode diff --git a/include/linux/phy.h b/include/linux/phy.h index a6cd0465b059..a376fe83e999 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -2168,6 +2168,8 @@ int __phy_hwtstamp_set(struct phy_device *phydev, struct kernel_hwtstamp_config *config, struct netlink_ext_ack *extack); =20 +struct phy_port *phy_get_sfp_port(struct phy_device *phydev); + extern const struct bus_type mdio_bus_type; extern const struct class mdio_bus_class; =20 diff --git a/include/linux/phy_port.h b/include/linux/phy_port.h index f47ac5f5ef9e..053c35c70071 100644 --- a/include/linux/phy_port.h +++ b/include/linux/phy_port.h @@ -49,6 +49,7 @@ struct phy_port_ops { * @active: Indicates if the port is currently part of the active link. * @is_mii: Indicates if this port is MII (Media Independent Interface), * or MDI (Media Dependent Interface). + * @is_sfp: Indicates if this port drives an SFP cage. */ struct phy_port { struct list_head head; @@ -67,6 +68,7 @@ struct phy_port { unsigned int not_described:1; unsigned int active:1; unsigned int is_mii:1; + unsigned int is_sfp:1; }; =20 struct phy_port *phy_port_alloc(void); --=20 2.49.0 From nobody Thu Oct 2 22:52:49 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 554C335FC3A; Tue, 9 Sep 2025 15:27:57 +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=1757431679; cv=none; b=Ril51NAyeHVI6OyJJi67Vh3CEhC/1QWaAAhfmIYtDeKbd67jn8tlIqjLrTpcEGC9zl6+ZmXeE+AOByP7LbfWKyO6BDuZp79ttpBJ3ILtgxL9DTxuMbUYBIs81F+0/Ow0M3DrJtYZsqdWgTXCVbNdae5kz0dkHvM945C3nUo5XlA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431679; c=relaxed/simple; bh=oCfjDcMQFDFXw+75U4+GIZVn+hcIWVXGFu34QVjVWs8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=oaNnPPi6/DaskijcFwZ77LlB5V+Idn6nN5zk9hUPnW99h+h2i2RDhaDF25p8dIJecAPbUf5ijdqjMarPWSUHeMeAfmMuPEWLUVfgZVdOI+Rst8wOjQzhwXTbAqbrp42fXEkyL9QX4ZVjcKzRGbOOfjKRSkoGqo+LNThQJvtLiSw= 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=h7I3b4db; 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="h7I3b4db" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id C84FA4E408EC; Tue, 9 Sep 2025 15:27:55 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 9F6B660630; Tue, 9 Sep 2025 15:27:55 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 67D16102F2584; Tue, 9 Sep 2025 17:27:50 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1757431674; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=JFrQJzmg8Zgzx93on0sdS3XZl9D0t9ynDO/E9zD8E+0=; b=h7I3b4dbU9/aFGeaZOSA5403hHQh6WbAM23+PK/rhsHn5TGcatMXpiNR5tUVdexbAL96wm LBRIVDsgWXa6tTsSSVXi++Sq+B9Puw7v0CLdou/GHIEdQDToWLlO5EiJqQY/SMUHUcWmkk wKdJhKuSiP1HJryRRgrr7KBqjU4DsOLJSSB3tfeUYd+FXJBm+1kWSTCyxKjQokoytJ/T2g +dTK7U4O/ZILbjcxnQBBpous3r9e6uSnUrmgJdx6iBEYfh4cKkUoq/KZoAp5wp6N+4dFyK XjYc8ZgMjE1qJCqgCdU6JfXJdcjYlxKB2xpkBpBC3M203T6mpXDNEMczFVInbA== 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 Subject: [PATCH net-next v12 11/18] net: phy: marvell-88x2222: Support SFP through phy_port interface Date: Tue, 9 Sep 2025 17:26:07 +0200 Message-ID: <20250909152617.119554-12-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250909152617.119554-1-maxime.chevallier@bootlin.com> References: <20250909152617.119554-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 Content-Type: text/plain; charset="utf-8" The 88x2222 PHY from Marvell only supports serialised modes as its line-facing interfaces. Convert that driver to the generic phylib SFP handling. Signed-off-by: Maxime Chevallier Reviewed-by: Christophe Leroy Tested-by: Christophe Leroy Tested-by: Florian Fainelli Tested-by: Oleksij Rempel --- drivers/net/phy/marvell-88x2222.c | 95 +++++++++++++------------------ 1 file changed, 38 insertions(+), 57 deletions(-) diff --git a/drivers/net/phy/marvell-88x2222.c b/drivers/net/phy/marvell-88= x2222.c index fad2f54c1eac..ba1bbb6c63d6 100644 --- a/drivers/net/phy/marvell-88x2222.c +++ b/drivers/net/phy/marvell-88x2222.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include =20 /* Port PCS Configuration */ @@ -473,90 +473,70 @@ static int mv2222_config_init(struct phy_device *phyd= ev) return 0; } =20 -static int mv2222_sfp_insert(void *upstream, const struct sfp_eeprom_id *i= d) +static int mv2222_configure_serdes(struct phy_port *port, bool enable, + phy_interface_t interface) { - DECLARE_PHY_INTERFACE_MASK(interfaces); - struct phy_device *phydev =3D upstream; - phy_interface_t sfp_interface; + struct phy_device *phydev =3D port_phydev(port); struct mv2222_data *priv; - struct device *dev; - int ret; - - __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_supported) =3D { 0, }; + int ret =3D 0; =20 priv =3D phydev->priv; - dev =3D &phydev->mdio.dev; - - sfp_parse_support(phydev->sfp_bus, id, sfp_supported, interfaces); - phydev->port =3D sfp_parse_port(phydev->sfp_bus, id, sfp_supported); - sfp_interface =3D sfp_select_interface(phydev->sfp_bus, sfp_supported); - - dev_info(dev, "%s SFP module inserted\n", phy_modes(sfp_interface)); + priv->line_interface =3D interface; =20 - if (sfp_interface !=3D PHY_INTERFACE_MODE_10GBASER && - sfp_interface !=3D PHY_INTERFACE_MODE_1000BASEX && - sfp_interface !=3D PHY_INTERFACE_MODE_SGMII) { - dev_err(dev, "Incompatible SFP module inserted\n"); + if (enable) { + linkmode_and(priv->supported, phydev->supported, port->supported); =20 - return -EINVAL; - } - - priv->line_interface =3D sfp_interface; - linkmode_and(priv->supported, phydev->supported, sfp_supported); + ret =3D mv2222_config_line(phydev); + if (ret < 0) + return ret; =20 - ret =3D mv2222_config_line(phydev); - if (ret < 0) - return ret; + if (mutex_trylock(&phydev->lock)) { + ret =3D mv2222_config_aneg(phydev); + mutex_unlock(&phydev->lock); + } =20 - if (mutex_trylock(&phydev->lock)) { - ret =3D mv2222_config_aneg(phydev); - mutex_unlock(&phydev->lock); + } else { + linkmode_zero(priv->supported); } =20 return ret; } =20 -static void mv2222_sfp_remove(void *upstream) +static void mv2222_port_link_up(struct phy_port *port) { - struct phy_device *phydev =3D upstream; - struct mv2222_data *priv; - - priv =3D phydev->priv; - - priv->line_interface =3D PHY_INTERFACE_MODE_NA; - linkmode_zero(priv->supported); - phydev->port =3D PORT_NONE; -} - -static void mv2222_sfp_link_up(void *upstream) -{ - struct phy_device *phydev =3D upstream; + struct phy_device *phydev =3D port_phydev(port); struct mv2222_data *priv; =20 priv =3D phydev->priv; priv->sfp_link =3D true; } =20 -static void mv2222_sfp_link_down(void *upstream) +static void mv2222_port_link_down(struct phy_port *port) { - struct phy_device *phydev =3D upstream; + struct phy_device *phydev =3D port_phydev(port); struct mv2222_data *priv; =20 priv =3D phydev->priv; priv->sfp_link =3D false; } =20 -static const struct sfp_upstream_ops sfp_phy_ops =3D { - .module_insert =3D mv2222_sfp_insert, - .module_remove =3D mv2222_sfp_remove, - .link_up =3D mv2222_sfp_link_up, - .link_down =3D mv2222_sfp_link_down, - .attach =3D phy_sfp_attach, - .detach =3D phy_sfp_detach, - .connect_phy =3D phy_sfp_connect_phy, - .disconnect_phy =3D phy_sfp_disconnect_phy, +static const struct phy_port_ops mv2222_port_ops =3D { + .link_up =3D mv2222_port_link_up, + .link_down =3D mv2222_port_link_down, + .configure_mii =3D mv2222_configure_serdes, }; =20 +static int mv2222_attach_mii_port(struct phy_device *phydev, struct phy_po= rt *port) +{ + port->ops =3D &mv2222_port_ops; + + __set_bit(PHY_INTERFACE_MODE_10GBASER, port->interfaces); + __set_bit(PHY_INTERFACE_MODE_1000BASEX, port->interfaces); + __set_bit(PHY_INTERFACE_MODE_SGMII, port->interfaces); + + return 0; +} + static int mv2222_probe(struct phy_device *phydev) { struct device *dev =3D &phydev->mdio.dev; @@ -592,7 +572,7 @@ static int mv2222_probe(struct phy_device *phydev) priv->line_interface =3D PHY_INTERFACE_MODE_NA; phydev->priv =3D priv; =20 - return phy_sfp_probe(phydev, &sfp_phy_ops); + return 0; } =20 static struct phy_driver mv2222_drivers[] =3D { @@ -609,6 +589,7 @@ static struct phy_driver mv2222_drivers[] =3D { .suspend =3D mv2222_suspend, .resume =3D mv2222_resume, .read_status =3D mv2222_read_status, + .attach_mii_port =3D mv2222_attach_mii_port, }, }; module_phy_driver(mv2222_drivers); --=20 2.49.0 From nobody Thu Oct 2 22:52:49 2025 Received: from smtpout-04.galae.net (smtpout-04.galae.net [185.171.202.116]) (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 1718236207D; Tue, 9 Sep 2025 15:27:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.171.202.116 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431682; cv=none; b=pkW3S9pv+ak/OQmIp1KjuPB3NG9jKIFTnYjygAV4+ZzE48IaubB7zXstA8RD5kt/ZFTw4qvr9oxkP7BpAKra38Z/49e2rJgzTedAKQ1AgANivRRcpO/2wc8DSSI/SiITkEdT4clFtPZ1GFjYSzQiIsxJlZS/dcauDP/a8ON1wVA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431682; c=relaxed/simple; bh=9MvuyOwOfLcc/LlUsmG2AeWiysYlc5iMjW4iaMuWfkg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Y5YEBtFNajg67NMertkyfCAwyjR8g8IutmMv/nkdl6GqTBzd15PrwxRiYLHiwAAy/4yus7Umj07sioJo6ztrN26WfFn5AWTof5Duk3x7yFiD9abFvN+HvDORqRcMnFk31pkJHRG5OJMjA/wlBaDe3nEBO30LjNrlMx+ZpcDLWbM= 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=fbTbXn/Q; arc=none smtp.client-ip=185.171.202.116 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="fbTbXn/Q" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-04.galae.net (Postfix) with ESMTPS id 01E8FC6B394; Tue, 9 Sep 2025 15:27:43 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id AC0F660630; Tue, 9 Sep 2025 15:27:58 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id B3834102F08F6; Tue, 9 Sep 2025 17:27:54 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1757431677; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=KWWG4hKYYlA02bsgRIuvB2vwBhYTHk9kJhB5edwHNWs=; b=fbTbXn/QQaV88SW+7kX6FLekXvHPRFVfLvBFd+k3cQ6PuYSvWPRRtD2XyTkXcrRYQtohoY 8UYnQU2wQIg6fAshJloEkO4rB8zM6ZvairrLQGxQeKzqXLJr1V1YV6bPbrtzO+Bvblqsyq FYQyTomqMvxAcbqtef4Hy67plKp19jjLDXamzF2yoptE/xt2Bq59zXrdZutUa5yh4STfkj W1P8TeCjaMkezUw4CLBxD6tzChMYoA8g2veXRaD7x0zn9m+MqD7pEwzz/vpH9WkmUb/YFu rVhcKfg5PSUppwck2VxeZT2PqqlY1W/1Gr9MTiuDR9Vcp9k6rsFvXPA3iE70AA== 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 Subject: [PATCH net-next v12 12/18] net: phy: marvell: Support SFP through phy_port interface Date: Tue, 9 Sep 2025 17:26:08 +0200 Message-ID: <20250909152617.119554-13-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250909152617.119554-1-maxime.chevallier@bootlin.com> References: <20250909152617.119554-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 Content-Type: text/plain; charset="utf-8" Convert the Marvell driver (especially the 88e1512 driver) to use the phy_port interface to handle SFPs. This means registering a .attach_port() handler to detect when a serdes line interface is used (most likely, and SFP module). Signed-off-by: Maxime Chevallier Tested-by: Christophe Leroy Tested-by: Florian Fainelli Tested-by: Oleksij Rempel --- drivers/net/phy/marvell.c | 94 ++++++++++++++------------------------- 1 file changed, 33 insertions(+), 61 deletions(-) diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 623292948fa7..467cf94e2d7f 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -29,10 +29,10 @@ #include #include #include +#include #include #include #include -#include =20 #include #include @@ -3561,42 +3561,38 @@ static int marvell_probe(struct phy_device *phydev) return marvell_hwmon_probe(phydev); } =20 -static int m88e1510_sfp_insert(void *upstream, const struct sfp_eeprom_id = *id) +static int m88e1510_port_configure_serdes(struct phy_port *port, bool enab= le, + phy_interface_t interface) { - DECLARE_PHY_INTERFACE_MASK(interfaces); - struct phy_device *phydev =3D upstream; - phy_interface_t interface; + struct phy_device *phydev =3D port_phydev(port); struct device *dev; int oldpage; int ret =3D 0; u16 mode; =20 - __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) =3D { 0, }; - dev =3D &phydev->mdio.dev; =20 - sfp_parse_support(phydev->sfp_bus, id, supported, interfaces); - interface =3D sfp_select_interface(phydev->sfp_bus, supported); + if (enable) { + switch (interface) { + case PHY_INTERFACE_MODE_1000BASEX: + mode =3D MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_1000X; =20 - dev_info(dev, "%s SFP module inserted\n", phy_modes(interface)); + break; + case PHY_INTERFACE_MODE_100BASEX: + mode =3D MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_100FX; =20 - switch (interface) { - case PHY_INTERFACE_MODE_1000BASEX: - mode =3D MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_1000X; + break; + case PHY_INTERFACE_MODE_SGMII: + mode =3D MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_SGMII; =20 - break; - case PHY_INTERFACE_MODE_100BASEX: - mode =3D MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_100FX; + break; + default: + dev_err(dev, "Incompatible SFP module inserted\n"); =20 - break; - case PHY_INTERFACE_MODE_SGMII: - mode =3D MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_SGMII; - - break; - default: - dev_err(dev, "Incompatible SFP module inserted\n"); - - return -EINVAL; + return -EINVAL; + } + } else { + mode =3D MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII; } =20 oldpage =3D phy_select_page(phydev, MII_MARVELL_MODE_PAGE); @@ -3613,49 +3609,24 @@ static int m88e1510_sfp_insert(void *upstream, cons= t struct sfp_eeprom_id *id) =20 error: return phy_restore_page(phydev, oldpage, ret); -} - -static void m88e1510_sfp_remove(void *upstream) -{ - struct phy_device *phydev =3D upstream; - int oldpage; - int ret =3D 0; - - oldpage =3D phy_select_page(phydev, MII_MARVELL_MODE_PAGE); - if (oldpage < 0) - goto error; - - ret =3D __phy_modify(phydev, MII_88E1510_GEN_CTRL_REG_1, - MII_88E1510_GEN_CTRL_REG_1_MODE_MASK, - MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII); - if (ret < 0) - goto error; - - ret =3D __phy_set_bits(phydev, MII_88E1510_GEN_CTRL_REG_1, - MII_88E1510_GEN_CTRL_REG_1_RESET); =20 -error: - phy_restore_page(phydev, oldpage, ret); + return 0; } =20 -static const struct sfp_upstream_ops m88e1510_sfp_ops =3D { - .module_insert =3D m88e1510_sfp_insert, - .module_remove =3D m88e1510_sfp_remove, - .attach =3D phy_sfp_attach, - .detach =3D phy_sfp_detach, - .connect_phy =3D phy_sfp_connect_phy, - .disconnect_phy =3D phy_sfp_disconnect_phy, +static const struct phy_port_ops m88e1510_serdes_port_ops =3D { + .configure_mii =3D m88e1510_port_configure_serdes, }; =20 -static int m88e1510_probe(struct phy_device *phydev) +static int m88e1510_attach_mii_port(struct phy_device *phy_device, + struct phy_port *port) { - int err; + port->ops =3D &m88e1510_serdes_port_ops; =20 - err =3D marvell_probe(phydev); - if (err) - return err; + __set_bit(PHY_INTERFACE_MODE_SGMII, port->interfaces); + __set_bit(PHY_INTERFACE_MODE_1000BASEX, port->interfaces); + __set_bit(PHY_INTERFACE_MODE_100BASEX, port->interfaces); =20 - return phy_sfp_probe(phydev, &m88e1510_sfp_ops); + return 0; } =20 static struct phy_driver marvell_drivers[] =3D { @@ -3915,7 +3886,7 @@ static struct phy_driver marvell_drivers[] =3D { .driver_data =3D DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops), .features =3D PHY_GBIT_FIBRE_FEATURES, .flags =3D PHY_POLL_CABLE_TEST, - .probe =3D m88e1510_probe, + .probe =3D marvell_probe, .config_init =3D m88e1510_config_init, .config_aneg =3D m88e1510_config_aneg, .read_status =3D marvell_read_status, @@ -3941,6 +3912,7 @@ static struct phy_driver marvell_drivers[] =3D { .led_hw_is_supported =3D m88e1318_led_hw_is_supported, .led_hw_control_set =3D m88e1318_led_hw_control_set, .led_hw_control_get =3D m88e1318_led_hw_control_get, + .attach_mii_port =3D m88e1510_attach_mii_port, }, { .phy_id =3D MARVELL_PHY_ID_88E1540, --=20 2.49.0 From nobody Thu Oct 2 22:52:49 2025 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (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 BB4A9362081 for ; Tue, 9 Sep 2025 15:28:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431685; cv=none; b=TfKNA11HF3rkt/L0oIP+qZJfLsBQ4tzSur5f3CasMzTBWtgR1lPzd2m3CUhV8FthSZAjIBKj3bkVRM8pRIPV8FT1a9ZH7oNmKBY/rllok1gnaIZ9mnaypcTXMM0l/cAml/yqeddleLg5pILMWUPOiTsXRg6/jr4msvdRTmdE3rw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431685; c=relaxed/simple; bh=DIu91AlIyqj5udBVoL4nNPIt2pY4kXiU4bsH713Nkas=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=O3IuD19E8QKWWOunP/2v5KTXSV1171oVnnhlN4JUBg1MmIe5ULL1pIC5GsI/q7gu3Hvisz7rZr/vRzmyQCGT3hIqbT4eLbMufLnqUVZXVJK0g6B4TQk977feWWbrDbDIvOVNe8Uw8g5o7ldLQSyzR17yGhkHOPm05kp2qKg9awE= 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=AUP8vyUI; arc=none smtp.client-ip=185.246.84.56 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="AUP8vyUI" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id 4CF7D1A087F; Tue, 9 Sep 2025 15:28:02 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id CD3F460630; Tue, 9 Sep 2025 15:28:01 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id B3CA1102F2866; Tue, 9 Sep 2025 17:27:57 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1757431680; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=HV/VBaz1cbuMI4PiuxG3jTVqnp+frC6Ei9d5ndVdoBE=; b=AUP8vyUIT7E8WXK1jQjZhUjWrpjSJSsThxQ6nHiOkQXiyibFgLF36Xzm0+Xf3WQQbEsDRt UVn2gAf2cN18HL0wscQsW3JYSuLJLkFDK4CHMRZU6sBQcTUl1JryJxEn2rDqL9fR/tJ0/9 U5PYs/FrrRuP4aY6Ba2eNHgYgdwYNljgHssM0j6pTT0otpzzTGAUKj23JbSlUiSVi8BGGk edqMl/AsPv4ULSMs46g+wpay/zMfwiFjdZh5/Rl11H9NJb33VrYQyYddoPTh1LTCKwr6JK C4uGhqth/009nVhMZTbaHWSMZ6QpJiWo4vd7ghoUaqLnJefvL0Xui3ZTUoTbHQ== 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 Subject: [PATCH net-next v12 13/18] net: phy: marvell10g: Support SFP through phy_port Date: Tue, 9 Sep 2025 17:26:09 +0200 Message-ID: <20250909152617.119554-14-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250909152617.119554-1-maxime.chevallier@bootlin.com> References: <20250909152617.119554-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 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. Signed-off-by: Maxime Chevallier Tested-by: Christophe Leroy Tested-by: Florian Fainelli Tested-by: Oleksij Rempel --- drivers/net/phy/marvell10g.c | 54 ++++++++++++++++++++++-------------- drivers/net/phy/phy_port.c | 44 +++++++++++++++++++++++++++++ include/linux/phy_port.h | 1 + 3 files changed, 78 insertions(+), 21 deletions(-) diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 13e81dff42c1..833ea0c0dc22 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,36 +463,36 @@ 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; - __ETHTOOL_DECLARE_LINK_MODE_MASK(support) =3D { 0, }; - DECLARE_PHY_INTERFACE_MASK(interfaces); - phy_interface_t iface; - - sfp_parse_support(phydev->sfp_bus, id, support, interfaces); - iface =3D sfp_select_interface(phydev->sfp_bus, support); + __set_bit(PHY_INTERFACE_MODE_10GBASER, port->interfaces); =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_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)); + + return 0; +} =20 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 || @@ -543,9 +543,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) @@ -1406,6 +1410,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, @@ -1425,6 +1431,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, @@ -1445,6 +1453,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, @@ -1463,6 +1473,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 6fecaa68350e..b1ba3e56c28d 100644 --- a/drivers/net/phy/phy_port.c +++ b/drivers/net/phy/phy_port.c @@ -131,6 +131,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->lanes); + + 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 otherwise. + */ +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 053c35c70071..82f1992d2395 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 From nobody Thu Oct 2 22:52:49 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 5989036207D for ; Tue, 9 Sep 2025 15:28:06 +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=1757431688; cv=none; b=gA+mikP7Mj2+U2DhkB8IhYQ+kG37GMwKashoz9Va5aqYpg4F7Yam1W52/tvikaLLlKeGJ+mC9TIgeFH9XM5PaeO2/WzuQk5krgdIx7CIzIbsMVq/PksaTZunQB9wNlzHoN7ucXGQdNbfV7oxAmeaJXSr0gGcvQDIy2jyJwC2p9o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431688; c=relaxed/simple; bh=3q46H2xMHoYSAcBfi2N4Vg6XFGr7ioYE/WtBo89L6lk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=THcUBh31wUyswrhRq57aw77BgxDw/OTdhzOqPuvQtb7BfeLk0W/5IRN/gt182lAB8yX+927GCoufLVc7pCQn6HSPbTFav7awddA495dhFYUE9ORNoAlXwvvB24111m8EyaLmzQ9QWOleDGRVmcr6ManKtsc+VyMdoyeVpbKaess= 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=CNY9j+kZ; 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="CNY9j+kZ" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id D24494E40C65; Tue, 9 Sep 2025 15:28:04 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id AB06C60630; Tue, 9 Sep 2025 15:28:04 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 9D496102F29C5; Tue, 9 Sep 2025 17:28:00 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1757431683; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=rRRw+QZoWFzbCFwAfXxX8Upx0XxhhxL6zjKX6dIb29k=; b=CNY9j+kZotl/aYwFELJ2FPCNGm+huzD7Sn4qfu2PH9HbR7vWu61dTX2uwy7+mCtrIukap+ +Wb8e8HDD+2/Hdi4nQbx1XWNzp2A2PJJdedNDdLuElYBgDlsox7xhTzuDTMHs56nbbZGYJ twfVB8RNuVaLFIxhrv1/I9pgDZdCVReFyckyxxc3vi5PHCG3j5x7GneADXe4Xbj/ePU3pO yCRMJu12+0h0IhTlUxWFB+iirSSuzX68pRaSkvtsYM2M1iSIYLpWnnJCzERKQScATNrPso 9jzM1MrAzkNw3TdBKsdV9MvW/iPux6Mu8P7gQE10ixlmA4JSimBMj+8TAxqkKA== 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 Subject: [PATCH net-next v12 14/18] net: phy: at803x: Support SFP through phy_port interface Date: Tue, 9 Sep 2025 17:26:10 +0200 Message-ID: <20250909152617.119554-15-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250909152617.119554-1-maxime.chevallier@bootlin.com> References: <20250909152617.119554-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 Content-Type: text/plain; charset="utf-8" Convert the at803x driver to use the generic phylib SFP handling, via a dedicated .attach_port() callback, populating the supported interfaces. As these devices are limited to 1000BaseX, a workaround is used to also support, in a very limited way, copper modules. This is done by supporting SGMII but limiting it to 1G full duplex (in which case it's somewhat compatible with 1000BaseX). Signed-off-by: Maxime Chevallier Tested-by: Christophe Leroy Tested-by: Florian Fainelli Tested-by: Oleksij Rempel --- drivers/net/phy/qcom/at803x.c | 78 ++++++++++++++--------------------- 1 file changed, 32 insertions(+), 46 deletions(-) diff --git a/drivers/net/phy/qcom/at803x.c b/drivers/net/phy/qcom/at803x.c index 51a132242462..2995b08bac96 100644 --- a/drivers/net/phy/qcom/at803x.c +++ b/drivers/net/phy/qcom/at803x.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include =20 #include "qcom.h" @@ -769,58 +769,44 @@ static int at8031_register_regulators(struct phy_devi= ce *phydev) return 0; } =20 -static int at8031_sfp_insert(void *upstream, const struct sfp_eeprom_id *i= d) +static int at803x_configure_mii(struct phy_port *port, bool enable, + phy_interface_t interface) { - struct phy_device *phydev =3D upstream; - __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_support); - __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support); - DECLARE_PHY_INTERFACE_MASK(interfaces); - phy_interface_t iface; - - linkmode_zero(phy_support); - phylink_set(phy_support, 1000baseX_Full); - phylink_set(phy_support, 1000baseT_Full); - phylink_set(phy_support, Autoneg); - 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); - /* 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); + struct phy_device *phydev =3D port_phydev(port); =20 - if (linkmode_empty(sfp_support)) { - dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n"); - return -EINVAL; - } + if (interface =3D=3D PHY_INTERFACE_MODE_SGMII) + dev_warn(&phydev->mdio.dev, + "module may not function if 1000Base-X not supported\n"); + + return 0; +} =20 - iface =3D sfp_select_interface(phydev->sfp_bus, sfp_support); +static const struct phy_port_ops at803x_port_ops =3D { + .configure_mii =3D at803x_configure_mii, +}; =20 - /* Only 1000Base-X is supported by AR8031/8033 as the downstream SerDes - * interface for use with SFP modules. - * However, some copper modules detected as having a preferred SGMII - * interface do default to and function in 1000Base-X mode, so just - * print a warning and allow such modules, as they may have some chance - * of working. +static int at8031_attach_mii_port(struct phy_device *phydev, + struct phy_port *port) +{ + linkmode_zero(port->supported); + phylink_set(port->supported, 1000baseX_Full); + phylink_set(port->supported, 1000baseT_Full); + phylink_set(port->supported, Autoneg); + phylink_set(port->supported, Pause); + phylink_set(port->supported, Asym_Pause); + + /* This device doesn't really support SGMII. However, do our best + * to be compatible with copper modules (that usually require SGMII), + * in a degraded mode as we only allow 1000BaseT Full */ - if (iface =3D=3D PHY_INTERFACE_MODE_SGMII) - dev_warn(&phydev->mdio.dev, "module may not function if 1000Base-X not s= upported\n"); - else if (iface !=3D PHY_INTERFACE_MODE_1000BASEX) - return -EINVAL; + __set_bit(PHY_INTERFACE_MODE_SGMII, port->interfaces); + __set_bit(PHY_INTERFACE_MODE_1000BASEX, port->interfaces); + + port->ops =3D &at803x_port_ops; =20 return 0; } =20 -static const struct sfp_upstream_ops at8031_sfp_ops =3D { - .attach =3D phy_sfp_attach, - .detach =3D phy_sfp_detach, - .module_insert =3D at8031_sfp_insert, - .connect_phy =3D phy_sfp_connect_phy, - .disconnect_phy =3D phy_sfp_disconnect_phy, -}; - static int at8031_parse_dt(struct phy_device *phydev) { struct device_node *node =3D phydev->mdio.dev.of_node; @@ -841,8 +827,7 @@ static int at8031_parse_dt(struct phy_device *phydev) return ret; } =20 - /* Only AR8031/8033 support 1000Base-X for SFP modules */ - return phy_sfp_probe(phydev, &at8031_sfp_ops); + return 0; } =20 static int at8031_probe(struct phy_device *phydev) @@ -1173,6 +1158,7 @@ static struct phy_driver at803x_driver[] =3D { .set_tunable =3D at803x_set_tunable, .cable_test_start =3D at8031_cable_test_start, .cable_test_get_status =3D at8031_cable_test_get_status, + .attach_mii_port =3D at8031_attach_mii_port, }, { /* Qualcomm Atheros AR8032 */ PHY_ID_MATCH_EXACT(ATH8032_PHY_ID), --=20 2.49.0 From nobody Thu Oct 2 22:52:49 2025 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (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 EA51C353369; Tue, 9 Sep 2025 15:28:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431696; cv=none; b=jVZyoEJmb4xPttB7t677WLy+yb2sU5lLng4TG4j/mKjdpYACgLVpcuhqz6ZA1GSxrTRY4UFuAB6HiHhEzRqlvrFvzorNWoOeXBCdklbjSxYRPNdX1GIM2IS5Tmdixy8Sax7UlhWkSbwYu3Q62xRYkSsIT9cL6hI+jxInazdXVHQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431696; c=relaxed/simple; bh=hPRLbKxYp6H2YSGn1BdPIskQUeQi9xvSVt+G7YFuubo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=O6Ek0GwPbtE0W3rvsJJX84cko47ce/vjQ0DvDN63axqMc+FP9AfvurZE+gXzRaf8nLHicKlGIFJPK/Wlt8q0mfTE0fn+CIkcomisRFPSg4ZBXEsaYqn0ML8OmF+sRrhwkS5jXcvXWjE7+uFkL2r1NSmloZeV0i1t9H7zArusNH8= 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=1MpD4RPx; arc=none smtp.client-ip=185.246.84.56 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="1MpD4RPx" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id 563231A087F; Tue, 9 Sep 2025 15:28:13 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 2A32560630; Tue, 9 Sep 2025 15:28:13 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id B3C53102F287B; Tue, 9 Sep 2025 17:28:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1757431691; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=PckfFG/dRb3ZsJpCAwSPy+akTUtZHor6elcL1m5whiE=; b=1MpD4RPxErW4thjbJfbgzq0OUnkACAmnZzPZ7JoaTmyMDR5mie1UXOfK4b9mGlhkTe/z3Y 2pLYmgzjrKj5v2g9iYorcIx6q1uWM/4GyjAa251/2/s3AQlqOhK3o2OX31a/RWZAuNJEYQ y6iyHVlxpu/QOMlBHoUq5xKjR+jtOY1Z7V8X+PmqL8K1MgQvYmeacbNQF0HSB+kKAV0h+K Is4FZwwqD8vRVlp9/LJpaFN9dfsk7bRU2dJ+fN3MazMvo0xHPCh1vD7799/pMBQfn7lKbb ojwXbRxhgrULxLUprHiGMFPpr2ao6QFqbiSV9DsT7HLuZ4jcLhwxI6InZ3Qoag== 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 Subject: [PATCH net-next v12 15/18] net: phy: qca807x: Support SFP through phy_port interface Date: Tue, 9 Sep 2025 17:26:11 +0200 Message-ID: <20250909152617.119554-16-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250909152617.119554-1-maxime.chevallier@bootlin.com> References: <20250909152617.119554-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 Content-Type: text/plain; charset="utf-8" QCA8072/8075 may be used as combo-port PHYs, with Serdes (100/1000BaseX) and Copper interfaces. The PHY has the ability to read the configuration it's in. If the configuration indicates the PHY is in combo mode, allow registering up to 2 ports. Register a dedicated set of port ops to handle the serdes port, and rely on generic phylib SFP support for the SFP handling. Signed-off-by: Maxime Chevallier Tested-by: Christophe Leroy Tested-by: Florian Fainelli Tested-by: Oleksij Rempel --- drivers/net/phy/qcom/qca807x.c | 73 ++++++++++++++-------------------- 1 file changed, 30 insertions(+), 43 deletions(-) diff --git a/drivers/net/phy/qcom/qca807x.c b/drivers/net/phy/qcom/qca807x.c index 070dc8c00835..d8f1ce5a7128 100644 --- a/drivers/net/phy/qcom/qca807x.c +++ b/drivers/net/phy/qcom/qca807x.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include =20 #include "../phylib.h" #include "qcom.h" @@ -643,68 +643,54 @@ static int qca807x_phy_package_config_init_once(struc= t phy_device *phydev) return ret; } =20 -static int qca807x_sfp_insert(void *upstream, const struct sfp_eeprom_id *= id) +static int qca807x_configure_serdes(struct phy_port *port, bool enable, + phy_interface_t interface) { - struct phy_device *phydev =3D upstream; - __ETHTOOL_DECLARE_LINK_MODE_MASK(support) =3D { 0, }; - phy_interface_t iface; + struct phy_device *phydev =3D port_phydev(port); int ret; - DECLARE_PHY_INTERFACE_MASK(interfaces); =20 - sfp_parse_support(phydev->sfp_bus, id, support, interfaces); - iface =3D sfp_select_interface(phydev->sfp_bus, support); + if (!phydev) + return -ENODEV; =20 - dev_info(&phydev->mdio.dev, "%s SFP module inserted\n", phy_modes(iface)); - - switch (iface) { - case PHY_INTERFACE_MODE_1000BASEX: - case PHY_INTERFACE_MODE_100BASEX: + if (enable) { /* Set PHY mode to PSGMII combo (1/4 copper + combo ports) mode */ ret =3D phy_modify(phydev, QCA807X_CHIP_CONFIGURATION, QCA807X_CHIP_CONFIGURATION_MODE_CFG_MASK, QCA807X_CHIP_CONFIGURATION_MODE_PSGMII_FIBER); + if (ret) + return ret; /* Enable fiber mode autodection (1000Base-X or 100Base-FX) */ ret =3D phy_set_bits_mmd(phydev, MDIO_MMD_AN, QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION, QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION_EN); - /* Select fiber page */ - ret =3D phy_clear_bits(phydev, - QCA807X_CHIP_CONFIGURATION, - QCA807X_BT_BX_REG_SEL); - - phydev->port =3D PORT_FIBRE; - break; - default: - dev_err(&phydev->mdio.dev, "Incompatible SFP module inserted\n"); - return -EINVAL; + if (ret) + return ret; } =20 - return ret; + phydev->port =3D enable ? PORT_FIBRE : PORT_TP; + + return phy_modify(phydev, QCA807X_CHIP_CONFIGURATION, + QCA807X_BT_BX_REG_SEL, + enable ? 0 : QCA807X_BT_BX_REG_SEL); } =20 -static void qca807x_sfp_remove(void *upstream) +static const struct phy_port_ops qca807x_serdes_port_ops =3D { + .configure_mii =3D qca807x_configure_serdes, +}; + +static int qca807x_attach_mii_port(struct phy_device *phydev, + struct phy_port *port) { - struct phy_device *phydev =3D upstream; + __set_bit(PHY_INTERFACE_MODE_1000BASEX, port->interfaces); + __set_bit(PHY_INTERFACE_MODE_100BASEX, port->interfaces); =20 - /* Select copper page */ - phy_set_bits(phydev, - QCA807X_CHIP_CONFIGURATION, - QCA807X_BT_BX_REG_SEL); + port->ops =3D &qca807x_serdes_port_ops; =20 - phydev->port =3D PORT_TP; + return 0; } =20 -static const struct sfp_upstream_ops qca807x_sfp_ops =3D { - .attach =3D phy_sfp_attach, - .detach =3D phy_sfp_detach, - .module_insert =3D qca807x_sfp_insert, - .module_remove =3D qca807x_sfp_remove, - .connect_phy =3D phy_sfp_connect_phy, - .disconnect_phy =3D phy_sfp_disconnect_phy, -}; - static int qca807x_probe(struct phy_device *phydev) { struct device_node *node =3D phydev->mdio.dev.of_node; @@ -745,9 +731,8 @@ static int qca807x_probe(struct phy_device *phydev) =20 /* Attach SFP bus on combo port*/ if (phy_read(phydev, QCA807X_CHIP_CONFIGURATION)) { - ret =3D phy_sfp_probe(phydev, &qca807x_sfp_ops); - if (ret) - return ret; + phydev->max_n_ports =3D 2; + linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported); linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->advertising); } @@ -825,6 +810,7 @@ static struct phy_driver qca807x_drivers[] =3D { .get_phy_stats =3D qca807x_get_phy_stats, .set_wol =3D at8031_set_wol, .get_wol =3D at803x_get_wol, + .attach_mii_port =3D qca807x_attach_mii_port, }, { PHY_ID_MATCH_EXACT(PHY_ID_QCA8075), @@ -852,6 +838,7 @@ static struct phy_driver qca807x_drivers[] =3D { .get_phy_stats =3D qca807x_get_phy_stats, .set_wol =3D at8031_set_wol, .get_wol =3D at803x_get_wol, + .attach_mii_port =3D qca807x_attach_mii_port, }, }; module_phy_driver(qca807x_drivers); --=20 2.49.0 From nobody Thu Oct 2 22:52:49 2025 Received: from smtpout-04.galae.net (smtpout-04.galae.net [185.171.202.116]) (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 E2BB436C081; Tue, 9 Sep 2025 15:28:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.171.202.116 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431699; cv=none; b=d2ZSx8VSRBiQZfmIgQ6mYgfAyRyiI0ng+nnIUz36VPqtQUweWT/fOtELe33fcRRdTlEfPdT+dB/3e65MPHWKODmNPXF3R1Upzsoq4Rfk3xNyIdiRsTOuFMUQyxOAKmxPFqs6Ws9Zdxy35dZIuoQ0nFdPd+2DZQQbeZsSby2RHro= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431699; c=relaxed/simple; bh=wMGMRPAOBAhgQaglfD0FETE3tXwXQfLKxRsyw+k2iq8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MVTHOCBMonkLSGMgH6GyzZOfUFe1huEeFH+cQHJqZq6tTNbprAAAhGmNqdL0Up7cN7ghIwW1fvV3y+RgJd1OEhxw+V95GS7wLYSJOEJO71E0i5ape4HFqhe6xwVO+5vbyeBAkwnU/opTSPfQmyXklugQGQ1jn84FASK8oaRquyQ= 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=19TCR6gX; arc=none smtp.client-ip=185.171.202.116 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="19TCR6gX" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-04.galae.net (Postfix) with ESMTPS id BCE9AC6B39E; Tue, 9 Sep 2025 15:28:00 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 7277660630; Tue, 9 Sep 2025 15:28:16 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 43C8E102F2835; Tue, 9 Sep 2025 17:28:12 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1757431694; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=M1KaFPFap5aEBhRYbWeaGzKBUg3KY7ZWFnipsaZey1k=; b=19TCR6gXOxh/CN3QvizJT6tEPu8uJ1aUfiJd1CqapTxKuKCYw8vWTh47ZoiHm3VTQTGrtR l8Rlz6YD5Quz2RT0NyOWQx6YKAoR1OI8X1gpux1Jx8t3QLqp4CgA687rwzpuTUhsfajmKN nP0/6PuO6C309XbgP0AEUSqAwaPtzVYFkkNHbUczYJQTVZteYKKeNIDKLsLGgKH0vAUUWY NMXK5E0xNhlZNQawVUsMzjneaMJosqPI1fmLdtOlKpJTBLNfAnRHobxFvV53tRxAtGK5Tt fNJnnt1JXQyO2OY8JjuVaxnDlVr3J50i6s4NrAQvgsRpfxoUOM0/WuY3KZzd7Q== 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 Subject: [PATCH net-next v12 16/18] net: phy: Only rely on phy_port for PHY-driven SFP Date: Tue, 9 Sep 2025 17:26:12 +0200 Message-ID: <20250909152617.119554-17-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250909152617.119554-1-maxime.chevallier@bootlin.com> References: <20250909152617.119554-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 Content-Type: text/plain; charset="utf-8" Now that all PHY drivers that support downstream SFP have been converted to phy_port serdes handling, we can make the generic PHY SFP handling mandatory, thus making all phylib sfp helpers static. Reviewed-by: Christophe Leroy Signed-off-by: Maxime Chevallier Tested-by: Christophe Leroy Tested-by: Florian Fainelli Tested-by: Oleksij Rempel --- drivers/net/phy/phy_device.c | 28 +++++++++------------------- include/linux/phy.h | 6 ------ 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 7b8ec7be473c..f59598973322 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1521,7 +1521,7 @@ static DEVICE_ATTR_RO(phy_standalone); * * Return: 0 on success, otherwise a negative error code. */ -int phy_sfp_connect_phy(void *upstream, struct phy_device *phy) +static int phy_sfp_connect_phy(void *upstream, struct phy_device *phy) { struct phy_device *phydev =3D upstream; struct net_device *dev =3D phydev->attached_dev; @@ -1531,7 +1531,6 @@ int phy_sfp_connect_phy(void *upstream, struct phy_de= vice *phy) =20 return 0; } -EXPORT_SYMBOL(phy_sfp_connect_phy); =20 /** * phy_sfp_disconnect_phy - Disconnect the SFP module's PHY from the upstr= eam PHY @@ -1543,7 +1542,7 @@ EXPORT_SYMBOL(phy_sfp_connect_phy); * will be destroyed, re-inserting the same module will add a new phy with= a * new index. */ -void phy_sfp_disconnect_phy(void *upstream, struct phy_device *phy) +static void phy_sfp_disconnect_phy(void *upstream, struct phy_device *phy) { struct phy_device *phydev =3D upstream; struct net_device *dev =3D phydev->attached_dev; @@ -1551,7 +1550,6 @@ void phy_sfp_disconnect_phy(void *upstream, struct ph= y_device *phy) if (dev) phy_link_topo_del_phy(dev, phy); } -EXPORT_SYMBOL(phy_sfp_disconnect_phy); =20 /** * phy_sfp_attach - attach the SFP bus to the PHY upstream network device @@ -1560,7 +1558,7 @@ EXPORT_SYMBOL(phy_sfp_disconnect_phy); * * This is used to fill in the sfp_upstream_ops .attach member. */ -void phy_sfp_attach(void *upstream, struct sfp_bus *bus) +static void phy_sfp_attach(void *upstream, struct sfp_bus *bus) { struct phy_device *phydev =3D upstream; =20 @@ -1568,7 +1566,6 @@ void phy_sfp_attach(void *upstream, struct sfp_bus *b= us) phydev->attached_dev->sfp_bus =3D bus; phydev->sfp_bus_attached =3D true; } -EXPORT_SYMBOL(phy_sfp_attach); =20 /** * phy_sfp_detach - detach the SFP bus from the PHY upstream network device @@ -1577,7 +1574,7 @@ EXPORT_SYMBOL(phy_sfp_attach); * * This is used to fill in the sfp_upstream_ops .detach member. */ -void phy_sfp_detach(void *upstream, struct sfp_bus *bus) +static void phy_sfp_detach(void *upstream, struct sfp_bus *bus) { struct phy_device *phydev =3D upstream; =20 @@ -1585,7 +1582,6 @@ void phy_sfp_detach(void *upstream, struct sfp_bus *b= us) phydev->attached_dev->sfp_bus =3D NULL; phydev->sfp_bus_attached =3D false; } -EXPORT_SYMBOL(phy_sfp_detach); =20 static int phy_sfp_module_insert(void *upstream, const struct sfp_eeprom_i= d *id) { @@ -1738,10 +1734,8 @@ static int phy_setup_sfp_port(struct phy_device *phy= dev) /** * phy_sfp_probe - probe for a SFP cage attached to this PHY device * @phydev: Pointer to phy_device - * @ops: SFP's upstream operations */ -int phy_sfp_probe(struct phy_device *phydev, - const struct sfp_upstream_ops *ops) +static int phy_sfp_probe(struct phy_device *phydev) { struct sfp_bus *bus; int ret =3D 0; @@ -1753,7 +1747,7 @@ int phy_sfp_probe(struct phy_device *phydev, =20 phydev->sfp_bus =3D bus; =20 - ret =3D sfp_bus_add_upstream(bus, phydev, ops); + ret =3D sfp_bus_add_upstream(bus, phydev, &sfp_phydev_ops); sfp_bus_put(bus); } =20 @@ -1762,7 +1756,6 @@ int phy_sfp_probe(struct phy_device *phydev, =20 return ret; } -EXPORT_SYMBOL(phy_sfp_probe); =20 static bool phy_drv_supports_irq(const struct phy_driver *phydrv) { @@ -3562,12 +3555,9 @@ static int phy_setup_ports(struct phy_device *phydev) if (ret) return ret; =20 - /* Use generic SFP probing only if the driver didn't do so already */ - if (!phydev->sfp_bus) { - ret =3D phy_sfp_probe(phydev, &sfp_phydev_ops); - if (ret) - goto out; - } + ret =3D phy_sfp_probe(phydev); + if (ret) + goto out; =20 if (phydev->n_ports < phydev->max_n_ports) { ret =3D phy_default_setup_single_port(phydev); diff --git a/include/linux/phy.h b/include/linux/phy.h index a376fe83e999..f02cbb1ff760 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1876,12 +1876,6 @@ int phy_suspend(struct phy_device *phydev); int phy_resume(struct phy_device *phydev); int __phy_resume(struct phy_device *phydev); int phy_loopback(struct phy_device *phydev, bool enable, int speed); -int phy_sfp_connect_phy(void *upstream, struct phy_device *phy); -void phy_sfp_disconnect_phy(void *upstream, struct phy_device *phy); -void phy_sfp_attach(void *upstream, struct sfp_bus *bus); -void phy_sfp_detach(void *upstream, struct sfp_bus *bus); -int phy_sfp_probe(struct phy_device *phydev, - const struct sfp_upstream_ops *ops); struct phy_device *phy_attach(struct net_device *dev, const char *bus_id, phy_interface_t interface); struct phy_device *phy_find_first(struct mii_bus *bus); --=20 2.49.0 From nobody Thu Oct 2 22:52:49 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 0EF9436CC91; Tue, 9 Sep 2025 15:28:20 +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=1757431702; cv=none; b=RyF8puLLRG70fnr+rEgDoLfB8jqhozSlOkqh+BoxydLbpgUnkAARlSQzc9CVOoVts5jw0vYpegWu6RKlfWN7kP8kVFZ2B2hwuDnTX/7OCH3AySgNBT6hHf50TjDbXkG8tDBgdkpzmMna3xHzBC/Q8U/XDHdhmvJAYv52Dps5WvQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431702; c=relaxed/simple; bh=0bMr2A2pzskdMOhBYUrXhySn2vY1g744UUV/+yzluss=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LJwi+9qA+LqpmiYx2MUhqU9EqHLYr+XKR36RKKn66XXeAhgtS06l80B4rts4Sxb0jpt3+17Fr8EBBt2rnrtmtdByzHlBNem3ZhZgEBeePg2/nvssip1ajwVdDU0fre+6jVxquxVTvZQ7gq4o6H+ofbgxZyj8N/AKyzVPiN+WnY8= 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=VO9nbsU7; 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="VO9nbsU7" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 990494E408EC; Tue, 9 Sep 2025 15:28:19 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 7083B60630; Tue, 9 Sep 2025 15:28:19 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 6C9AF102F29F0; Tue, 9 Sep 2025 17:28:15 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1757431698; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=bzmYOPr3hvVZTl1uon2prlEWvF1qYLbpQgHjwaF8RLM=; b=VO9nbsU7k7iEhxszjmqeDdS1pPJDKPGty0lxqL/hzenvhu9adKQ3WtQkSdHjKjkcsOETd7 A6jzWalJOoTQv6kc2WyEbBzWp5znEhEKcQULpeUCd3u18LjWsu1McXMfGi1r82hV7DNsE0 bYrzwgtEhpJ1fMVQM/5upGTGLo2DEqyHVPtD6kCywwsq7qeMc3PCFuxk8SRmFhIcByS7ZF aho66eMdsqgPNGnn5tC2M1+JAd4f1Ic3evYUIp9QkaPTXnLxXhGFJzpEcPxxrfhO9YExr4 kegv5DXaNq6ufTrHnCEv4cfle9zWgkKo7ThS5v423rZADgKyol8B+VFobtlQKg== 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 Subject: [PATCH net-next v12 17/18] net: phy: dp83822: Add SFP support through the phy_port interface Date: Tue, 9 Sep 2025 17:26:13 +0200 Message-ID: <20250909152617.119554-18-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250909152617.119554-1-maxime.chevallier@bootlin.com> References: <20250909152617.119554-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 Content-Type: text/plain; charset="utf-8" The DP83822 can support 100BaseFX. This mode was only accessible through custom DT properties, but there also exist SFP modules that support these modes. As this only requires setting the relevant supported interface in the driver, expose the port capability with the new phy_port API, allowing SFP support. Reviewed-by: Christophe Leroy Signed-off-by: Maxime Chevallier Tested-by: Christophe Leroy Tested-by: Florian Fainelli Tested-by: Oleksij Rempel --- drivers/net/phy/dp83822.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/phy/dp83822.c b/drivers/net/phy/dp83822.c index c6e5b7244658..94036e5af242 100644 --- a/drivers/net/phy/dp83822.c +++ b/drivers/net/phy/dp83822.c @@ -980,6 +980,13 @@ static int dp83822_attach_mdi_port(struct phy_device *= phydev, } } =20 + /* If attached from SFP, is_mii is set, but not the mediums. */ + if (port->is_mii) + dp83822->fx_enabled =3D true; + + if (dp83822->fx_enabled) + __set_bit(PHY_INTERFACE_MODE_100BASEX, port->interfaces); + return 0; } =20 --=20 2.49.0 From nobody Thu Oct 2 22:52:49 2025 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (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 D451536CE1C; Tue, 9 Sep 2025 15:28:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431705; cv=none; b=Jtkqb29MkbtWKVnQpVwRHI4cvoKybRkV97vhw6q4uMsl+fkjg+LC6/zaIoGtkpdI5yxg/K6T18/HvA56S8Wbs7MK2XZUrNjwq+fGsRv94CTiAjpG/5PyPsF/sVYbKQprKkF8bUR1N20NeYt+Rl5GsF69BFscJh9RWHSUn71fFgY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757431705; c=relaxed/simple; bh=iEge4bjlYp9qPy7RxJWOkif1xtGCW23M7V+rOHM4rgc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eZJjns8IEXGXdQ0xZ6oqi4/kuZvuJIr8G/lKkVr9+e6J8PhxYARYuZNulux6K4EdqcJM5w+QUDRCfacdKD+RJyYFfS0nLFtWRs3XKjvAcdv8NTd4TesQsDujbFu6b3yWMdf+lH1bnhOl3Cnghr68Dfsd8FEFkvuj0fGshgYYY/w= 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=UyQ3/5EG; arc=none smtp.client-ip=185.246.84.56 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="UyQ3/5EG" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id 85C021A0CCC; Tue, 9 Sep 2025 15:28:22 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 5B10D60630; Tue, 9 Sep 2025 15:28:22 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 84E57102F26A4; Tue, 9 Sep 2025 17:28:18 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1757431701; h=from:subject:date:message-id:to:cc:mime-version: content-transfer-encoding:in-reply-to:references; bh=+olRoEgX3HlrRX56jjhR0fg9dg8bH9fKzbpKGiLV6HI=; b=UyQ3/5EGbJPvok/KuWOAR6wQ+gA5rOYHZWr5CJ3PrDYJsSfXH90fUwuQ3K4a9ACNquiIDI GZxjUaTPeD0b476KRfeTWQ0vi2URXRDKAbX9Nw2ud85atFOSMIzRglgQf0vJ5m0RSaEdIl Xwvw51u16rkUfdrB89r+oojGLLRQ195QpjVpFY3fdKGToWdH94QHkKLtOtvhXskFBfVx4U +Ecz9Y9i4eASx/S7aUHFpCUmMsVR+d2efYX6bLJmA+Ne5hYl8q3NbIT55ImIWTx87El/xi 1TKXXcT0bv0NNiIkXb5vU4Hx4AWwhX42fWTaeG6JYKA7g2cEUELUY1vuTfwarA== 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 Subject: [PATCH net-next v12 18/18] Documentation: networking: Document the phy_port infrastructure Date: Tue, 9 Sep 2025 17:26:14 +0200 Message-ID: <20250909152617.119554-19-maxime.chevallier@bootlin.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250909152617.119554-1-maxime.chevallier@bootlin.com> References: <20250909152617.119554-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 Content-Type: text/plain; charset="utf-8" This documentation aims at describing the main goal of the phy_port infrastructure. Reviewed-by: Christophe Leroy Signed-off-by: Maxime Chevallier Tested-by: Christophe Leroy Tested-by: Florian Fainelli Tested-by: Oleksij Rempel --- Documentation/networking/index.rst | 1 + Documentation/networking/phy-port.rst | 111 ++++++++++++++++++++++++++ MAINTAINERS | 1 + 3 files changed, 113 insertions(+) create mode 100644 Documentation/networking/phy-port.rst diff --git a/Documentation/networking/index.rst b/Documentation/networking/= index.rst index b7a4969e9bc9..84d88607ee7d 100644 --- a/Documentation/networking/index.rst +++ b/Documentation/networking/index.rst @@ -96,6 +96,7 @@ Contents: packet_mmap phonet phy-link-topology + phy-port pktgen plip ppp_generic diff --git a/Documentation/networking/phy-port.rst b/Documentation/networki= ng/phy-port.rst new file mode 100644 index 000000000000..6d9d46ebe438 --- /dev/null +++ b/Documentation/networking/phy-port.rst @@ -0,0 +1,111 @@ +.. SPDX-License-Identifier: GPL-2.0 +.. _phy_port: + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +Ethernet ports +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +This document is a basic description of the phy_port infrastructure, +introduced to represent physical interfaces of Ethernet devices. + +Without phy_port, we already have quite a lot of information about what the +media-facing interface of a NIC can do and looks like, through the +:c:type:`struct ethtool_link_ksettings ` attribute= s, +which includes : + + - What the NIC can do through the :c:member:`supported` field + - What the Link Partner advertises through :c:member:`lp_advertising` + - Which features we're advertising through :c:member:`advertising` + +We also have info about the number of lanes and the PORT type. These setti= ngs +are built by aggregating together information reported by various devices = that +are sitting on the link : + + - The NIC itself, through the :c:member:`get_link_ksettings` callback + - Precise information from the MAC and PCS by using phylink in the MAC d= river + - Information reported by the PHY device + - Information reported by an SFP module (which can itself include a PHY) + +This model however starts showing its limitations when we consider devices= that +have more than one media interface. In such a case, only information about= the +actively used interface is reported, and it's not possible to know what the +other interfaces can do. In fact, we have very few information about wheth= er or +not there are any other media interfaces. + +The goal of the phy_port representation is to provide a way of representin= g a +physical interface of a NIC, regardless of what is driving the port (NIC t= hrough +a firmware, SFP module, Ethernet PHY). + +Multi-port interfaces examples +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D + +Several cases of multi-interface NICs have been observed so far : + +Internal MII Mux:: + + +------------------+ + | SoC | + | +-----+ | +-----+ + | +-----+ | |-------------| PHY | + | | MAC |--| Mux | | +-----+ +-----+ + | +-----+ | |-----| SFP | + | +-----+ | +-----+ + +------------------+ + +Internal Mux with internal PHY:: + + +------------------------+ + | SoC | + | +-----+ +-----+ + | +-----+ | |-| PHY | + | | MAC |--| Mux | +-----+ +-----+ + | +-----+ | |-----------| SFP | + | +-----+ | +-----+ + +------------------------+ + +External Mux:: + + +---------+ + | SoC | +-----+ +-----+ + | | | |--| PHY | + | +-----+ | | | +-----+ + | | MAC |----| Mux | +-----+ + | +-----+ | | |--| PHY | + | | +-----+ +-----+ + | | | + | GPIO-------+ + +---------+ + +Double-port PHY:: + + +---------+ + | SoC | +-----+ + | | | |--- RJ45 + | +-----+ | | | + | | MAC |---| PHY | +-----+ + | +-----+ | | |---| SFP | + +---------+ +-----+ +-----+ + +phy_port aims at providing a path to support all the above topologies, by +representing the media interfaces in a way that's agnostic to what's drivi= ng +the interface. the struct phy_port object has its own set of callback ops,= and +will eventually be able to report its own ksettings:: + + _____ +------+ + ( )-----| Port | + +-----+ ( ) +------+ + | MAC |--( ??? ) + +-----+ ( ) +------+ + (_____)-----| Port | + +------+ + +Next steps +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +As of writing this documentation, only ports controlled by PHY devices are +supported. The next steps will be to add the Netlink API to expose these +to userspace and add support for raw ports (controlled by some firmware, a= nd directly +managed by the NIC driver). + +Another parallel task is the introduction of a MII muxing framework to all= ow the +control of non-PHY driver multi-port setups. diff --git a/MAINTAINERS b/MAINTAINERS index 31e5293df595..9680dced1d02 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9111,6 +9111,7 @@ F: Documentation/devicetree/bindings/net/ethernet-con= nector.yaml F: Documentation/devicetree/bindings/net/ethernet-phy.yaml F: Documentation/devicetree/bindings/net/mdio* F: Documentation/devicetree/bindings/net/qca,ar803x.yaml +F: Documentation/networking/phy-port.rst F: Documentation/networking/phy.rst F: drivers/net/mdio/ F: drivers/net/mdio/acpi_mdio.c --=20 2.49.0