mirror of
				https://github.com/hzyitc/openwrt-redmi-ax3000
				synced 2025-11-02 16:27:05 +08:00 
			
		
		
		
	generic: backport phylink patches for PCS/PHY caps OPs
Backport phylink patches for PCS/PHY caps OPs. This makes it easier to align future generic PCS patch and permit supporting special PHY that needs specific tune if "in-band" mode is enabled (for example Aeonsemi PHYs) This is also mainly using the upstream version of the Mediatek patch 739-net-add-negotiation-of-in-band-capabilities. All affected patch automatically refreshed. Link: https://github.com/openwrt/openwrt/pull/20461 Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
This commit is contained in:
		@ -0,0 +1,41 @@
 | 
			
		||||
From 8cc5f4cb94c0b1c7c1ba8013c14fd02ffb1a25f3 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Fri, 8 Nov 2024 16:01:44 +0000
 | 
			
		||||
Subject: [PATCH 1/5] net: phylink: move manual flow control setting
 | 
			
		||||
 | 
			
		||||
Move the handling of manual flow control configuration to a common
 | 
			
		||||
location during resolve. We currently evaluate this for all but
 | 
			
		||||
fixed links.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1t9RQe-002Feh-T1@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phylink.c | 5 +++--
 | 
			
		||||
 1 file changed, 3 insertions(+), 2 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -1484,7 +1484,6 @@ static void phylink_resolve(struct work_
 | 
			
		||||
 		switch (pl->cur_link_an_mode) {
 | 
			
		||||
 		case MLO_AN_PHY:
 | 
			
		||||
 			link_state = pl->phy_state;
 | 
			
		||||
-			phylink_apply_manual_flow(pl, &link_state);
 | 
			
		||||
 			mac_config = link_state.link;
 | 
			
		||||
 			break;
 | 
			
		||||
 
 | 
			
		||||
@@ -1545,11 +1544,13 @@ static void phylink_resolve(struct work_
 | 
			
		||||
 				link_state.pause = pl->phy_state.pause;
 | 
			
		||||
 				mac_config = true;
 | 
			
		||||
 			}
 | 
			
		||||
-			phylink_apply_manual_flow(pl, &link_state);
 | 
			
		||||
 			break;
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
+	if (pl->cur_link_an_mode != MLO_AN_FIXED)
 | 
			
		||||
+		phylink_apply_manual_flow(pl, &link_state);
 | 
			
		||||
+
 | 
			
		||||
 	if (mac_config) {
 | 
			
		||||
 		if (link_state.interface != pl->link_config.interface) {
 | 
			
		||||
 			/* The interface has changed, force the link down and
 | 
			
		||||
@ -0,0 +1,42 @@
 | 
			
		||||
From 92abfcb4ced482afbe65d18980e6734fe1e62a34 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Fri, 8 Nov 2024 16:01:50 +0000
 | 
			
		||||
Subject: [PATCH 2/5] net: phylink: move MLO_AN_FIXED resolve handling to if()
 | 
			
		||||
 statement
 | 
			
		||||
 | 
			
		||||
The switch() statement doesn't sit very well with the preceeding if()
 | 
			
		||||
statements, and results in excessive indentation that spoils code
 | 
			
		||||
readability. Begin cleaning this up by converting the MLO_AN_FIXED case
 | 
			
		||||
to an if() statement.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1t9RQk-002Fen-1A@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phylink.c | 8 +++-----
 | 
			
		||||
 1 file changed, 3 insertions(+), 5 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -1480,6 +1480,9 @@ static void phylink_resolve(struct work_
 | 
			
		||||
 	} else if (pl->link_failed) {
 | 
			
		||||
 		link_state.link = false;
 | 
			
		||||
 		retrigger = true;
 | 
			
		||||
+	} else if (pl->cur_link_an_mode == MLO_AN_FIXED) {
 | 
			
		||||
+		phylink_get_fixed_state(pl, &link_state);
 | 
			
		||||
+		mac_config = link_state.link;
 | 
			
		||||
 	} else {
 | 
			
		||||
 		switch (pl->cur_link_an_mode) {
 | 
			
		||||
 		case MLO_AN_PHY:
 | 
			
		||||
@@ -1487,11 +1490,6 @@ static void phylink_resolve(struct work_
 | 
			
		||||
 			mac_config = link_state.link;
 | 
			
		||||
 			break;
 | 
			
		||||
 
 | 
			
		||||
-		case MLO_AN_FIXED:
 | 
			
		||||
-			phylink_get_fixed_state(pl, &link_state);
 | 
			
		||||
-			mac_config = link_state.link;
 | 
			
		||||
-			break;
 | 
			
		||||
-
 | 
			
		||||
 		case MLO_AN_INBAND:
 | 
			
		||||
 			phylink_mac_pcs_get_state(pl, &link_state);
 | 
			
		||||
 
 | 
			
		||||
@ -0,0 +1,37 @@
 | 
			
		||||
From f0f46c2a3d8ea9d1427298c8103a777d9e616c29 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Fri, 8 Nov 2024 16:01:55 +0000
 | 
			
		||||
Subject: [PATCH 3/5] net: phylink: move MLO_AN_PHY resolve handling to if()
 | 
			
		||||
 statement
 | 
			
		||||
 | 
			
		||||
The switch() statement doesn't sit very well with the preceeding if()
 | 
			
		||||
statements, and results in excessive indentation that spoils code
 | 
			
		||||
readability. Continue cleaning this up by converting the MLO_AN_PHY
 | 
			
		||||
case to use an if() statmeent.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1t9RQp-002Fet-5W@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phylink.c | 8 +++-----
 | 
			
		||||
 1 file changed, 3 insertions(+), 5 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -1483,13 +1483,11 @@ static void phylink_resolve(struct work_
 | 
			
		||||
 	} else if (pl->cur_link_an_mode == MLO_AN_FIXED) {
 | 
			
		||||
 		phylink_get_fixed_state(pl, &link_state);
 | 
			
		||||
 		mac_config = link_state.link;
 | 
			
		||||
+	} else if (pl->cur_link_an_mode == MLO_AN_PHY) {
 | 
			
		||||
+		link_state = pl->phy_state;
 | 
			
		||||
+		mac_config = link_state.link;
 | 
			
		||||
 	} else {
 | 
			
		||||
 		switch (pl->cur_link_an_mode) {
 | 
			
		||||
-		case MLO_AN_PHY:
 | 
			
		||||
-			link_state = pl->phy_state;
 | 
			
		||||
-			mac_config = link_state.link;
 | 
			
		||||
-			break;
 | 
			
		||||
-
 | 
			
		||||
 		case MLO_AN_INBAND:
 | 
			
		||||
 			phylink_mac_pcs_get_state(pl, &link_state);
 | 
			
		||||
 
 | 
			
		||||
@ -0,0 +1,127 @@
 | 
			
		||||
From d1a16dbbd84e02d2a6dcfcb8d5c4b8b2c0289f00 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Fri, 8 Nov 2024 16:02:00 +0000
 | 
			
		||||
Subject: [PATCH 4/5] net: phylink: remove switch() statement in resolve
 | 
			
		||||
 handling
 | 
			
		||||
 | 
			
		||||
The switch() statement doesn't sit very well with the preceeding if()
 | 
			
		||||
statements, so let's just convert everything to if()s. As a result of
 | 
			
		||||
the two preceding commits, there is now only one case in the switch()
 | 
			
		||||
statement. Remove the switch statement and reduce the code indentation.
 | 
			
		||||
Code reformatting will be in the following commit.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1t9RQu-002Fez-AA@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phylink.c | 94 +++++++++++++++++++--------------------
 | 
			
		||||
 1 file changed, 45 insertions(+), 49 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -1487,60 +1487,56 @@ static void phylink_resolve(struct work_
 | 
			
		||||
 		link_state = pl->phy_state;
 | 
			
		||||
 		mac_config = link_state.link;
 | 
			
		||||
 	} else {
 | 
			
		||||
-		switch (pl->cur_link_an_mode) {
 | 
			
		||||
-		case MLO_AN_INBAND:
 | 
			
		||||
-			phylink_mac_pcs_get_state(pl, &link_state);
 | 
			
		||||
-
 | 
			
		||||
-			/* The PCS may have a latching link-fail indicator.
 | 
			
		||||
-			 * If the link was up, bring the link down and
 | 
			
		||||
-			 * re-trigger the resolve. Otherwise, re-read the
 | 
			
		||||
-			 * PCS state to get the current status of the link.
 | 
			
		||||
+		phylink_mac_pcs_get_state(pl, &link_state);
 | 
			
		||||
+
 | 
			
		||||
+		/* The PCS may have a latching link-fail indicator.
 | 
			
		||||
+		 * If the link was up, bring the link down and
 | 
			
		||||
+		 * re-trigger the resolve. Otherwise, re-read the
 | 
			
		||||
+		 * PCS state to get the current status of the link.
 | 
			
		||||
+		 */
 | 
			
		||||
+		if (!link_state.link) {
 | 
			
		||||
+			if (cur_link_state)
 | 
			
		||||
+				retrigger = true;
 | 
			
		||||
+			else
 | 
			
		||||
+				phylink_mac_pcs_get_state(pl,
 | 
			
		||||
+							  &link_state);
 | 
			
		||||
+		}
 | 
			
		||||
+
 | 
			
		||||
+		/* If we have a phy, the "up" state is the union of
 | 
			
		||||
+		 * both the PHY and the MAC
 | 
			
		||||
+		 */
 | 
			
		||||
+		if (pl->phydev)
 | 
			
		||||
+			link_state.link &= pl->phy_state.link;
 | 
			
		||||
+
 | 
			
		||||
+		/* Only update if the PHY link is up */
 | 
			
		||||
+		if (pl->phydev && pl->phy_state.link) {
 | 
			
		||||
+			/* If the interface has changed, force a
 | 
			
		||||
+			 * link down event if the link isn't already
 | 
			
		||||
+			 * down, and re-resolve.
 | 
			
		||||
 			 */
 | 
			
		||||
-			if (!link_state.link) {
 | 
			
		||||
-				if (cur_link_state)
 | 
			
		||||
-					retrigger = true;
 | 
			
		||||
-				else
 | 
			
		||||
-					phylink_mac_pcs_get_state(pl,
 | 
			
		||||
-								  &link_state);
 | 
			
		||||
+			if (link_state.interface !=
 | 
			
		||||
+			    pl->phy_state.interface) {
 | 
			
		||||
+				retrigger = true;
 | 
			
		||||
+				link_state.link = false;
 | 
			
		||||
 			}
 | 
			
		||||
+			link_state.interface = pl->phy_state.interface;
 | 
			
		||||
 
 | 
			
		||||
-			/* If we have a phy, the "up" state is the union of
 | 
			
		||||
-			 * both the PHY and the MAC
 | 
			
		||||
+			/* If we are doing rate matching, then the
 | 
			
		||||
+			 * link speed/duplex comes from the PHY
 | 
			
		||||
 			 */
 | 
			
		||||
-			if (pl->phydev)
 | 
			
		||||
-				link_state.link &= pl->phy_state.link;
 | 
			
		||||
-
 | 
			
		||||
-			/* Only update if the PHY link is up */
 | 
			
		||||
-			if (pl->phydev && pl->phy_state.link) {
 | 
			
		||||
-				/* If the interface has changed, force a
 | 
			
		||||
-				 * link down event if the link isn't already
 | 
			
		||||
-				 * down, and re-resolve.
 | 
			
		||||
-				 */
 | 
			
		||||
-				if (link_state.interface !=
 | 
			
		||||
-				    pl->phy_state.interface) {
 | 
			
		||||
-					retrigger = true;
 | 
			
		||||
-					link_state.link = false;
 | 
			
		||||
-				}
 | 
			
		||||
-				link_state.interface = pl->phy_state.interface;
 | 
			
		||||
-
 | 
			
		||||
-				/* If we are doing rate matching, then the
 | 
			
		||||
-				 * link speed/duplex comes from the PHY
 | 
			
		||||
-				 */
 | 
			
		||||
-				if (pl->phy_state.rate_matching) {
 | 
			
		||||
-					link_state.rate_matching =
 | 
			
		||||
-						pl->phy_state.rate_matching;
 | 
			
		||||
-					link_state.speed = pl->phy_state.speed;
 | 
			
		||||
-					link_state.duplex =
 | 
			
		||||
-						pl->phy_state.duplex;
 | 
			
		||||
-				}
 | 
			
		||||
-
 | 
			
		||||
-				/* If we have a PHY, we need to update with
 | 
			
		||||
-				 * the PHY flow control bits.
 | 
			
		||||
-				 */
 | 
			
		||||
-				link_state.pause = pl->phy_state.pause;
 | 
			
		||||
-				mac_config = true;
 | 
			
		||||
+			if (pl->phy_state.rate_matching) {
 | 
			
		||||
+				link_state.rate_matching =
 | 
			
		||||
+					pl->phy_state.rate_matching;
 | 
			
		||||
+				link_state.speed = pl->phy_state.speed;
 | 
			
		||||
+				link_state.duplex =
 | 
			
		||||
+					pl->phy_state.duplex;
 | 
			
		||||
 			}
 | 
			
		||||
-			break;
 | 
			
		||||
+
 | 
			
		||||
+			/* If we have a PHY, we need to update with
 | 
			
		||||
+			 * the PHY flow control bits.
 | 
			
		||||
+			 */
 | 
			
		||||
+			link_state.pause = pl->phy_state.pause;
 | 
			
		||||
+			mac_config = true;
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
@ -0,0 +1,85 @@
 | 
			
		||||
From bc08ce37d99a3992e975a0f397503cb23404f25a Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Fri, 8 Nov 2024 16:02:05 +0000
 | 
			
		||||
Subject: [PATCH 5/5] net: phylink: clean up phylink_resolve()
 | 
			
		||||
 | 
			
		||||
Now that we have reduced the indentation level, clean up the code
 | 
			
		||||
formatting.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1t9RQz-002Ff5-EA@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phylink.c | 35 ++++++++++++++++-------------------
 | 
			
		||||
 1 file changed, 16 insertions(+), 19 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -1489,51 +1489,48 @@ static void phylink_resolve(struct work_
 | 
			
		||||
 	} else {
 | 
			
		||||
 		phylink_mac_pcs_get_state(pl, &link_state);
 | 
			
		||||
 
 | 
			
		||||
-		/* The PCS may have a latching link-fail indicator.
 | 
			
		||||
-		 * If the link was up, bring the link down and
 | 
			
		||||
-		 * re-trigger the resolve. Otherwise, re-read the
 | 
			
		||||
-		 * PCS state to get the current status of the link.
 | 
			
		||||
+		/* The PCS may have a latching link-fail indicator. If the link
 | 
			
		||||
+		 * was up, bring the link down and re-trigger the resolve.
 | 
			
		||||
+		 * Otherwise, re-read the PCS state to get the current status
 | 
			
		||||
+		 * of the link.
 | 
			
		||||
 		 */
 | 
			
		||||
 		if (!link_state.link) {
 | 
			
		||||
 			if (cur_link_state)
 | 
			
		||||
 				retrigger = true;
 | 
			
		||||
 			else
 | 
			
		||||
-				phylink_mac_pcs_get_state(pl,
 | 
			
		||||
-							  &link_state);
 | 
			
		||||
+				phylink_mac_pcs_get_state(pl, &link_state);
 | 
			
		||||
 		}
 | 
			
		||||
 
 | 
			
		||||
-		/* If we have a phy, the "up" state is the union of
 | 
			
		||||
-		 * both the PHY and the MAC
 | 
			
		||||
+		/* If we have a phy, the "up" state is the union of both the
 | 
			
		||||
+		 * PHY and the MAC
 | 
			
		||||
 		 */
 | 
			
		||||
 		if (pl->phydev)
 | 
			
		||||
 			link_state.link &= pl->phy_state.link;
 | 
			
		||||
 
 | 
			
		||||
 		/* Only update if the PHY link is up */
 | 
			
		||||
 		if (pl->phydev && pl->phy_state.link) {
 | 
			
		||||
-			/* If the interface has changed, force a
 | 
			
		||||
-			 * link down event if the link isn't already
 | 
			
		||||
-			 * down, and re-resolve.
 | 
			
		||||
+			/* If the interface has changed, force a link down
 | 
			
		||||
+			 * event if the link isn't already down, and re-resolve.
 | 
			
		||||
 			 */
 | 
			
		||||
-			if (link_state.interface !=
 | 
			
		||||
-			    pl->phy_state.interface) {
 | 
			
		||||
+			if (link_state.interface != pl->phy_state.interface) {
 | 
			
		||||
 				retrigger = true;
 | 
			
		||||
 				link_state.link = false;
 | 
			
		||||
 			}
 | 
			
		||||
+
 | 
			
		||||
 			link_state.interface = pl->phy_state.interface;
 | 
			
		||||
 
 | 
			
		||||
-			/* If we are doing rate matching, then the
 | 
			
		||||
-			 * link speed/duplex comes from the PHY
 | 
			
		||||
+			/* If we are doing rate matching, then the link
 | 
			
		||||
+			 * speed/duplex comes from the PHY
 | 
			
		||||
 			 */
 | 
			
		||||
 			if (pl->phy_state.rate_matching) {
 | 
			
		||||
 				link_state.rate_matching =
 | 
			
		||||
 					pl->phy_state.rate_matching;
 | 
			
		||||
 				link_state.speed = pl->phy_state.speed;
 | 
			
		||||
-				link_state.duplex =
 | 
			
		||||
-					pl->phy_state.duplex;
 | 
			
		||||
+				link_state.duplex = pl->phy_state.duplex;
 | 
			
		||||
 			}
 | 
			
		||||
 
 | 
			
		||||
-			/* If we have a PHY, we need to update with
 | 
			
		||||
-			 * the PHY flow control bits.
 | 
			
		||||
+			/* If we have a PHY, we need to update with the PHY
 | 
			
		||||
+			 * flow control bits.
 | 
			
		||||
 			 */
 | 
			
		||||
 			link_state.pause = pl->phy_state.pause;
 | 
			
		||||
 			mac_config = true;
 | 
			
		||||
@ -0,0 +1,95 @@
 | 
			
		||||
From 17ed1911f9c8d4f9af8e13b2c95103ee06dadc0f Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:30:47 +0000
 | 
			
		||||
Subject: [PATCH 01/13] net: phylink: pass phylink and pcs into
 | 
			
		||||
 phylink_pcs_neg_mode()
 | 
			
		||||
 | 
			
		||||
Move the call to phylink_pcs_neg_mode() in phylink_major_config() after
 | 
			
		||||
we have selected the appropriate PCS to allow the PCS to be passed in.
 | 
			
		||||
 | 
			
		||||
Add struct phylink and struct phylink_pcs pointers to
 | 
			
		||||
phylink_pcs_neg_mode() and pass in the appropriate structures. Set
 | 
			
		||||
pl->pcs_neg_mode before returning, and remove the return value.
 | 
			
		||||
 | 
			
		||||
This will allow the capabilities of the PCS and any PHY to be used when
 | 
			
		||||
deciding which pcs_neg_mode should be used.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUrP-006ITh-6u@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phylink.c | 26 +++++++++++++-------------
 | 
			
		||||
 1 file changed, 13 insertions(+), 13 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -1102,7 +1102,8 @@ static void phylink_pcs_an_restart(struc
 | 
			
		||||
 
 | 
			
		||||
 /**
 | 
			
		||||
  * phylink_pcs_neg_mode() - helper to determine PCS inband mode
 | 
			
		||||
- * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND.
 | 
			
		||||
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
 | 
			
		||||
+ * @pcs: a pointer to &struct phylink_pcs
 | 
			
		||||
  * @interface: interface mode to be used
 | 
			
		||||
  * @advertising: adertisement ethtool link mode mask
 | 
			
		||||
  *
 | 
			
		||||
@@ -1119,11 +1120,13 @@ static void phylink_pcs_an_restart(struc
 | 
			
		||||
  * Note: this is for cases where the PCS itself is involved in negotiation
 | 
			
		||||
  * (e.g. Clause 37, SGMII and similar) not Clause 73.
 | 
			
		||||
  */
 | 
			
		||||
-static unsigned int phylink_pcs_neg_mode(unsigned int mode,
 | 
			
		||||
-					 phy_interface_t interface,
 | 
			
		||||
-					 const unsigned long *advertising)
 | 
			
		||||
+static void phylink_pcs_neg_mode(struct phylink *pl, struct phylink_pcs *pcs,
 | 
			
		||||
+				 phy_interface_t interface,
 | 
			
		||||
+				 const unsigned long *advertising)
 | 
			
		||||
 {
 | 
			
		||||
-	unsigned int neg_mode;
 | 
			
		||||
+	unsigned int neg_mode, mode;
 | 
			
		||||
+
 | 
			
		||||
+	mode = pl->cur_link_an_mode;
 | 
			
		||||
 
 | 
			
		||||
 	switch (interface) {
 | 
			
		||||
 	case PHY_INTERFACE_MODE_SGMII:
 | 
			
		||||
@@ -1164,7 +1167,7 @@ static unsigned int phylink_pcs_neg_mode
 | 
			
		||||
 		break;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	return neg_mode;
 | 
			
		||||
+	pl->pcs_neg_mode = neg_mode;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void phylink_major_config(struct phylink *pl, bool restart,
 | 
			
		||||
@@ -1178,10 +1181,6 @@ static void phylink_major_config(struct
 | 
			
		||||
 
 | 
			
		||||
 	phylink_dbg(pl, "major config %s\n", phy_modes(state->interface));
 | 
			
		||||
 
 | 
			
		||||
-	pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode,
 | 
			
		||||
-						state->interface,
 | 
			
		||||
-						state->advertising);
 | 
			
		||||
-
 | 
			
		||||
 	if (pl->using_mac_select_pcs) {
 | 
			
		||||
 		pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface);
 | 
			
		||||
 		if (IS_ERR(pcs)) {
 | 
			
		||||
@@ -1194,6 +1193,8 @@ static void phylink_major_config(struct
 | 
			
		||||
 		pcs_changed = pcs && pl->pcs != pcs;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
+	phylink_pcs_neg_mode(pl, pcs, state->interface, state->advertising);
 | 
			
		||||
+
 | 
			
		||||
 	phylink_pcs_poll_stop(pl);
 | 
			
		||||
 
 | 
			
		||||
 	if (pl->mac_ops->mac_prepare) {
 | 
			
		||||
@@ -1284,9 +1285,8 @@ static int phylink_change_inband_advert(
 | 
			
		||||
 		    pl->link_config.pause);
 | 
			
		||||
 
 | 
			
		||||
 	/* Recompute the PCS neg mode */
 | 
			
		||||
-	pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode,
 | 
			
		||||
-					pl->link_config.interface,
 | 
			
		||||
-					pl->link_config.advertising);
 | 
			
		||||
+	phylink_pcs_neg_mode(pl, pl->pcs, pl->link_config.interface,
 | 
			
		||||
+			     pl->link_config.advertising);
 | 
			
		||||
 
 | 
			
		||||
 	neg_mode = pl->cur_link_an_mode;
 | 
			
		||||
 	if (pl->pcs->neg_mode)
 | 
			
		||||
@ -0,0 +1,290 @@
 | 
			
		||||
From 1f92ead7e15003f632b5f138e8138095e0997d3d Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:30:52 +0000
 | 
			
		||||
Subject: [PATCH 02/13] net: phylink: split cur_link_an_mode into requested and
 | 
			
		||||
 active
 | 
			
		||||
 | 
			
		||||
There is an interdependence between the current link_an_mode and
 | 
			
		||||
pcs_neg_mode that some drivers rely upon to know whether inband or PHY
 | 
			
		||||
mode will be used.
 | 
			
		||||
 | 
			
		||||
In order to support detection of PCS and PHY inband capabilities
 | 
			
		||||
resulting in automatic selection of inband or PHY mode, we need to
 | 
			
		||||
cater for this, and support changing the MAC link_an_mode. However, we
 | 
			
		||||
end up with an inter-dependency between the current link_an_mode and
 | 
			
		||||
pcs_neg_mode.
 | 
			
		||||
 | 
			
		||||
To solve this, split the current link_an_mode into the requested
 | 
			
		||||
link_an_mode and active link_an_mode. The requested link_an_mode will
 | 
			
		||||
always be passed to phylink_pcs_neg_mode(), and the active link_an_mode
 | 
			
		||||
will be used for everything else, and only updated during
 | 
			
		||||
phylink_major_config(). This will ensure that phylink_pcs_neg_mode()'s
 | 
			
		||||
link_an_mode will not depend on the active link_an_mode that will,
 | 
			
		||||
in a future patch, depend on pcs_neg_mode.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUrU-006ITn-Ai@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phylink.c | 60 ++++++++++++++++++++-------------------
 | 
			
		||||
 1 file changed, 31 insertions(+), 29 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -56,7 +56,8 @@ struct phylink {
 | 
			
		||||
 	struct phy_device *phydev;
 | 
			
		||||
 	phy_interface_t link_interface;	/* PHY_INTERFACE_xxx */
 | 
			
		||||
 	u8 cfg_link_an_mode;		/* MLO_AN_xxx */
 | 
			
		||||
-	u8 cur_link_an_mode;
 | 
			
		||||
+	u8 req_link_an_mode;		/* Requested MLO_AN_xxx mode */
 | 
			
		||||
+	u8 act_link_an_mode;		/* Active MLO_AN_xxx mode */
 | 
			
		||||
 	u8 link_port;			/* The current non-phy ethtool port */
 | 
			
		||||
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
 | 
			
		||||
 
 | 
			
		||||
@@ -1082,13 +1083,13 @@ static void phylink_mac_config(struct ph
 | 
			
		||||
 
 | 
			
		||||
 	phylink_dbg(pl,
 | 
			
		||||
 		    "%s: mode=%s/%s/%s adv=%*pb pause=%02x\n",
 | 
			
		||||
-		    __func__, phylink_an_mode_str(pl->cur_link_an_mode),
 | 
			
		||||
+		    __func__, phylink_an_mode_str(pl->act_link_an_mode),
 | 
			
		||||
 		    phy_modes(st.interface),
 | 
			
		||||
 		    phy_rate_matching_to_str(st.rate_matching),
 | 
			
		||||
 		    __ETHTOOL_LINK_MODE_MASK_NBITS, st.advertising,
 | 
			
		||||
 		    st.pause);
 | 
			
		||||
 
 | 
			
		||||
-	pl->mac_ops->mac_config(pl->config, pl->cur_link_an_mode, &st);
 | 
			
		||||
+	pl->mac_ops->mac_config(pl->config, pl->act_link_an_mode, &st);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void phylink_pcs_an_restart(struct phylink *pl)
 | 
			
		||||
@@ -1096,7 +1097,7 @@ static void phylink_pcs_an_restart(struc
 | 
			
		||||
 	if (pl->pcs && linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
 | 
			
		||||
 					 pl->link_config.advertising) &&
 | 
			
		||||
 	    phy_interface_mode_is_8023z(pl->link_config.interface) &&
 | 
			
		||||
-	    phylink_autoneg_inband(pl->cur_link_an_mode))
 | 
			
		||||
+	    phylink_autoneg_inband(pl->act_link_an_mode))
 | 
			
		||||
 		pl->pcs->ops->pcs_an_restart(pl->pcs);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -1126,7 +1127,7 @@ static void phylink_pcs_neg_mode(struct
 | 
			
		||||
 {
 | 
			
		||||
 	unsigned int neg_mode, mode;
 | 
			
		||||
 
 | 
			
		||||
-	mode = pl->cur_link_an_mode;
 | 
			
		||||
+	mode = pl->req_link_an_mode;
 | 
			
		||||
 
 | 
			
		||||
 	switch (interface) {
 | 
			
		||||
 	case PHY_INTERFACE_MODE_SGMII:
 | 
			
		||||
@@ -1168,6 +1169,7 @@ static void phylink_pcs_neg_mode(struct
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	pl->pcs_neg_mode = neg_mode;
 | 
			
		||||
+	pl->act_link_an_mode = mode;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void phylink_major_config(struct phylink *pl, bool restart,
 | 
			
		||||
@@ -1198,7 +1200,7 @@ static void phylink_major_config(struct
 | 
			
		||||
 	phylink_pcs_poll_stop(pl);
 | 
			
		||||
 
 | 
			
		||||
 	if (pl->mac_ops->mac_prepare) {
 | 
			
		||||
-		err = pl->mac_ops->mac_prepare(pl->config, pl->cur_link_an_mode,
 | 
			
		||||
+		err = pl->mac_ops->mac_prepare(pl->config, pl->act_link_an_mode,
 | 
			
		||||
 					       state->interface);
 | 
			
		||||
 		if (err < 0) {
 | 
			
		||||
 			phylink_err(pl, "mac_prepare failed: %pe\n",
 | 
			
		||||
@@ -1232,7 +1234,7 @@ static void phylink_major_config(struct
 | 
			
		||||
 	if (pl->pcs_state == PCS_STATE_STARTING || pcs_changed)
 | 
			
		||||
 		phylink_pcs_enable(pl->pcs);
 | 
			
		||||
 
 | 
			
		||||
-	neg_mode = pl->cur_link_an_mode;
 | 
			
		||||
+	neg_mode = pl->act_link_an_mode;
 | 
			
		||||
 	if (pl->pcs && pl->pcs->neg_mode)
 | 
			
		||||
 		neg_mode = pl->pcs_neg_mode;
 | 
			
		||||
 
 | 
			
		||||
@@ -1248,7 +1250,7 @@ static void phylink_major_config(struct
 | 
			
		||||
 		phylink_pcs_an_restart(pl);
 | 
			
		||||
 
 | 
			
		||||
 	if (pl->mac_ops->mac_finish) {
 | 
			
		||||
-		err = pl->mac_ops->mac_finish(pl->config, pl->cur_link_an_mode,
 | 
			
		||||
+		err = pl->mac_ops->mac_finish(pl->config, pl->act_link_an_mode,
 | 
			
		||||
 					      state->interface);
 | 
			
		||||
 		if (err < 0)
 | 
			
		||||
 			phylink_err(pl, "mac_finish failed: %pe\n",
 | 
			
		||||
@@ -1279,7 +1281,7 @@ static int phylink_change_inband_advert(
 | 
			
		||||
 		return 0;
 | 
			
		||||
 
 | 
			
		||||
 	phylink_dbg(pl, "%s: mode=%s/%s adv=%*pb pause=%02x\n", __func__,
 | 
			
		||||
-		    phylink_an_mode_str(pl->cur_link_an_mode),
 | 
			
		||||
+		    phylink_an_mode_str(pl->req_link_an_mode),
 | 
			
		||||
 		    phy_modes(pl->link_config.interface),
 | 
			
		||||
 		    __ETHTOOL_LINK_MODE_MASK_NBITS, pl->link_config.advertising,
 | 
			
		||||
 		    pl->link_config.pause);
 | 
			
		||||
@@ -1288,7 +1290,7 @@ static int phylink_change_inband_advert(
 | 
			
		||||
 	phylink_pcs_neg_mode(pl, pl->pcs, pl->link_config.interface,
 | 
			
		||||
 			     pl->link_config.advertising);
 | 
			
		||||
 
 | 
			
		||||
-	neg_mode = pl->cur_link_an_mode;
 | 
			
		||||
+	neg_mode = pl->act_link_an_mode;
 | 
			
		||||
 	if (pl->pcs->neg_mode)
 | 
			
		||||
 		neg_mode = pl->pcs_neg_mode;
 | 
			
		||||
 
 | 
			
		||||
@@ -1353,7 +1355,7 @@ static void phylink_mac_initial_config(s
 | 
			
		||||
 {
 | 
			
		||||
 	struct phylink_link_state link_state;
 | 
			
		||||
 
 | 
			
		||||
-	switch (pl->cur_link_an_mode) {
 | 
			
		||||
+	switch (pl->req_link_an_mode) {
 | 
			
		||||
 	case MLO_AN_PHY:
 | 
			
		||||
 		link_state = pl->phy_state;
 | 
			
		||||
 		break;
 | 
			
		||||
@@ -1427,14 +1429,14 @@ static void phylink_link_up(struct phyli
 | 
			
		||||
 
 | 
			
		||||
 	pl->cur_interface = link_state.interface;
 | 
			
		||||
 
 | 
			
		||||
-	neg_mode = pl->cur_link_an_mode;
 | 
			
		||||
+	neg_mode = pl->act_link_an_mode;
 | 
			
		||||
 	if (pl->pcs && pl->pcs->neg_mode)
 | 
			
		||||
 		neg_mode = pl->pcs_neg_mode;
 | 
			
		||||
 
 | 
			
		||||
 	phylink_pcs_link_up(pl->pcs, neg_mode, pl->cur_interface, speed,
 | 
			
		||||
 			    duplex);
 | 
			
		||||
 
 | 
			
		||||
-	pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->cur_link_an_mode,
 | 
			
		||||
+	pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->act_link_an_mode,
 | 
			
		||||
 				 pl->cur_interface, speed, duplex,
 | 
			
		||||
 				 !!(link_state.pause & MLO_PAUSE_TX), rx_pause);
 | 
			
		||||
 
 | 
			
		||||
@@ -1454,7 +1456,7 @@ static void phylink_link_down(struct phy
 | 
			
		||||
 
 | 
			
		||||
 	if (ndev)
 | 
			
		||||
 		netif_carrier_off(ndev);
 | 
			
		||||
-	pl->mac_ops->mac_link_down(pl->config, pl->cur_link_an_mode,
 | 
			
		||||
+	pl->mac_ops->mac_link_down(pl->config, pl->act_link_an_mode,
 | 
			
		||||
 				   pl->cur_interface);
 | 
			
		||||
 	phylink_info(pl, "Link is Down\n");
 | 
			
		||||
 }
 | 
			
		||||
@@ -1480,10 +1482,10 @@ static void phylink_resolve(struct work_
 | 
			
		||||
 	} else if (pl->link_failed) {
 | 
			
		||||
 		link_state.link = false;
 | 
			
		||||
 		retrigger = true;
 | 
			
		||||
-	} else if (pl->cur_link_an_mode == MLO_AN_FIXED) {
 | 
			
		||||
+	} else if (pl->act_link_an_mode == MLO_AN_FIXED) {
 | 
			
		||||
 		phylink_get_fixed_state(pl, &link_state);
 | 
			
		||||
 		mac_config = link_state.link;
 | 
			
		||||
-	} else if (pl->cur_link_an_mode == MLO_AN_PHY) {
 | 
			
		||||
+	} else if (pl->act_link_an_mode == MLO_AN_PHY) {
 | 
			
		||||
 		link_state = pl->phy_state;
 | 
			
		||||
 		mac_config = link_state.link;
 | 
			
		||||
 	} else {
 | 
			
		||||
@@ -1537,7 +1539,7 @@ static void phylink_resolve(struct work_
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	if (pl->cur_link_an_mode != MLO_AN_FIXED)
 | 
			
		||||
+	if (pl->act_link_an_mode != MLO_AN_FIXED)
 | 
			
		||||
 		phylink_apply_manual_flow(pl, &link_state);
 | 
			
		||||
 
 | 
			
		||||
 	if (mac_config) {
 | 
			
		||||
@@ -1661,7 +1663,7 @@ int phylink_set_fixed_link(struct phylin
 | 
			
		||||
 	pl->link_config.an_complete = 1;
 | 
			
		||||
 
 | 
			
		||||
 	pl->cfg_link_an_mode = MLO_AN_FIXED;
 | 
			
		||||
-	pl->cur_link_an_mode = pl->cfg_link_an_mode;
 | 
			
		||||
+	pl->req_link_an_mode = pl->cfg_link_an_mode;
 | 
			
		||||
 
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
@@ -1756,7 +1758,7 @@ struct phylink *phylink_create(struct ph
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	pl->cur_link_an_mode = pl->cfg_link_an_mode;
 | 
			
		||||
+	pl->req_link_an_mode = pl->cfg_link_an_mode;
 | 
			
		||||
 
 | 
			
		||||
 	ret = phylink_register_sfp(pl, fwnode);
 | 
			
		||||
 	if (ret < 0) {
 | 
			
		||||
@@ -2213,7 +2215,7 @@ void phylink_start(struct phylink *pl)
 | 
			
		||||
 	ASSERT_RTNL();
 | 
			
		||||
 
 | 
			
		||||
 	phylink_info(pl, "configuring for %s/%s link mode\n",
 | 
			
		||||
-		     phylink_an_mode_str(pl->cur_link_an_mode),
 | 
			
		||||
+		     phylink_an_mode_str(pl->req_link_an_mode),
 | 
			
		||||
 		     phy_modes(pl->link_config.interface));
 | 
			
		||||
 
 | 
			
		||||
 	/* Always set the carrier off */
 | 
			
		||||
@@ -2472,7 +2474,7 @@ int phylink_ethtool_ksettings_get(struct
 | 
			
		||||
 
 | 
			
		||||
 	linkmode_copy(kset->link_modes.supported, pl->supported);
 | 
			
		||||
 
 | 
			
		||||
-	switch (pl->cur_link_an_mode) {
 | 
			
		||||
+	switch (pl->act_link_an_mode) {
 | 
			
		||||
 	case MLO_AN_FIXED:
 | 
			
		||||
 		/* We are using fixed settings. Report these as the
 | 
			
		||||
 		 * current link settings - and note that these also
 | 
			
		||||
@@ -2564,7 +2566,7 @@ int phylink_ethtool_ksettings_set(struct
 | 
			
		||||
 		/* If we have a fixed link, refuse to change link parameters.
 | 
			
		||||
 		 * If the link parameters match, accept them but do nothing.
 | 
			
		||||
 		 */
 | 
			
		||||
-		if (pl->cur_link_an_mode == MLO_AN_FIXED) {
 | 
			
		||||
+		if (pl->req_link_an_mode == MLO_AN_FIXED) {
 | 
			
		||||
 			if (s->speed != pl->link_config.speed ||
 | 
			
		||||
 			    s->duplex != pl->link_config.duplex)
 | 
			
		||||
 				return -EINVAL;
 | 
			
		||||
@@ -2580,7 +2582,7 @@ int phylink_ethtool_ksettings_set(struct
 | 
			
		||||
 		 * is our default case) but do not allow the advertisement to
 | 
			
		||||
 		 * be changed. If the advertisement matches, simply return.
 | 
			
		||||
 		 */
 | 
			
		||||
-		if (pl->cur_link_an_mode == MLO_AN_FIXED) {
 | 
			
		||||
+		if (pl->req_link_an_mode == MLO_AN_FIXED) {
 | 
			
		||||
 			if (!linkmode_equal(config.advertising,
 | 
			
		||||
 					    pl->link_config.advertising))
 | 
			
		||||
 				return -EINVAL;
 | 
			
		||||
@@ -2620,7 +2622,7 @@ int phylink_ethtool_ksettings_set(struct
 | 
			
		||||
 		linkmode_copy(support, pl->supported);
 | 
			
		||||
 		if (phylink_validate(pl, support, &config)) {
 | 
			
		||||
 			phylink_err(pl, "validation of %s/%s with support %*pb failed\n",
 | 
			
		||||
-				    phylink_an_mode_str(pl->cur_link_an_mode),
 | 
			
		||||
+				    phylink_an_mode_str(pl->req_link_an_mode),
 | 
			
		||||
 				    phy_modes(config.interface),
 | 
			
		||||
 				    __ETHTOOL_LINK_MODE_MASK_NBITS, support);
 | 
			
		||||
 			return -EINVAL;
 | 
			
		||||
@@ -2720,7 +2722,7 @@ int phylink_ethtool_set_pauseparam(struc
 | 
			
		||||
 
 | 
			
		||||
 	ASSERT_RTNL();
 | 
			
		||||
 
 | 
			
		||||
-	if (pl->cur_link_an_mode == MLO_AN_FIXED)
 | 
			
		||||
+	if (pl->req_link_an_mode == MLO_AN_FIXED)
 | 
			
		||||
 		return -EOPNOTSUPP;
 | 
			
		||||
 
 | 
			
		||||
 	if (!phylink_test(pl->supported, Pause) &&
 | 
			
		||||
@@ -2984,7 +2986,7 @@ static int phylink_mii_read(struct phyli
 | 
			
		||||
 	struct phylink_link_state state;
 | 
			
		||||
 	int val = 0xffff;
 | 
			
		||||
 
 | 
			
		||||
-	switch (pl->cur_link_an_mode) {
 | 
			
		||||
+	switch (pl->act_link_an_mode) {
 | 
			
		||||
 	case MLO_AN_FIXED:
 | 
			
		||||
 		if (phy_id == 0) {
 | 
			
		||||
 			phylink_get_fixed_state(pl, &state);
 | 
			
		||||
@@ -3009,7 +3011,7 @@ static int phylink_mii_read(struct phyli
 | 
			
		||||
 static int phylink_mii_write(struct phylink *pl, unsigned int phy_id,
 | 
			
		||||
 			     unsigned int reg, unsigned int val)
 | 
			
		||||
 {
 | 
			
		||||
-	switch (pl->cur_link_an_mode) {
 | 
			
		||||
+	switch (pl->act_link_an_mode) {
 | 
			
		||||
 	case MLO_AN_FIXED:
 | 
			
		||||
 		break;
 | 
			
		||||
 
 | 
			
		||||
@@ -3199,9 +3201,9 @@ static void phylink_sfp_set_config(struc
 | 
			
		||||
 		changed = true;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	if (pl->cur_link_an_mode != mode ||
 | 
			
		||||
+	if (pl->req_link_an_mode != mode ||
 | 
			
		||||
 	    pl->link_config.interface != state->interface) {
 | 
			
		||||
-		pl->cur_link_an_mode = mode;
 | 
			
		||||
+		pl->req_link_an_mode = mode;
 | 
			
		||||
 		pl->link_config.interface = state->interface;
 | 
			
		||||
 
 | 
			
		||||
 		changed = true;
 | 
			
		||||
@ -0,0 +1,66 @@
 | 
			
		||||
From 4e7d000286fe8e12f2d88032711ffab3ab658b12 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:30:57 +0000
 | 
			
		||||
Subject: [PATCH 03/13] net: phylink: add debug for phylink_major_config()
 | 
			
		||||
 | 
			
		||||
Now that we have a more complexity in phylink_major_config(), augment
 | 
			
		||||
the debugging so we can see what's going on there.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUrZ-006ITt-Fa@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phylink.c | 27 ++++++++++++++++++++++++++-
 | 
			
		||||
 1 file changed, 26 insertions(+), 1 deletion(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -176,6 +176,24 @@ static const char *phylink_an_mode_str(u
 | 
			
		||||
 	return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown";
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static const char *phylink_pcs_mode_str(unsigned int mode)
 | 
			
		||||
+{
 | 
			
		||||
+	if (!mode)
 | 
			
		||||
+		return "none";
 | 
			
		||||
+
 | 
			
		||||
+	if (mode & PHYLINK_PCS_NEG_OUTBAND)
 | 
			
		||||
+		return "outband";
 | 
			
		||||
+
 | 
			
		||||
+	if (mode & PHYLINK_PCS_NEG_INBAND) {
 | 
			
		||||
+		if (mode & PHYLINK_PCS_NEG_ENABLED)
 | 
			
		||||
+			return "inband,an-enabled";
 | 
			
		||||
+		else
 | 
			
		||||
+			return "inband,an-disabled";
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	return "unknown";
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static unsigned int phylink_interface_signal_rate(phy_interface_t interface)
 | 
			
		||||
 {
 | 
			
		||||
 	switch (interface) {
 | 
			
		||||
@@ -1181,7 +1199,9 @@ static void phylink_major_config(struct
 | 
			
		||||
 	unsigned int neg_mode;
 | 
			
		||||
 	int err;
 | 
			
		||||
 
 | 
			
		||||
-	phylink_dbg(pl, "major config %s\n", phy_modes(state->interface));
 | 
			
		||||
+	phylink_dbg(pl, "major config, requested %s/%s\n",
 | 
			
		||||
+		    phylink_an_mode_str(pl->req_link_an_mode),
 | 
			
		||||
+		    phy_modes(state->interface));
 | 
			
		||||
 
 | 
			
		||||
 	if (pl->using_mac_select_pcs) {
 | 
			
		||||
 		pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface);
 | 
			
		||||
@@ -1197,6 +1217,11 @@ static void phylink_major_config(struct
 | 
			
		||||
 
 | 
			
		||||
 	phylink_pcs_neg_mode(pl, pcs, state->interface, state->advertising);
 | 
			
		||||
 
 | 
			
		||||
+	phylink_dbg(pl, "major config, active %s/%s/%s\n",
 | 
			
		||||
+		    phylink_an_mode_str(pl->act_link_an_mode),
 | 
			
		||||
+		    phylink_pcs_mode_str(pl->pcs_neg_mode),
 | 
			
		||||
+		    phy_modes(state->interface));
 | 
			
		||||
+
 | 
			
		||||
 	phylink_pcs_poll_stop(pl);
 | 
			
		||||
 
 | 
			
		||||
 	if (pl->mac_ops->mac_prepare) {
 | 
			
		||||
@ -0,0 +1,118 @@
 | 
			
		||||
From b4c7698dd95f253c6958d8c6ac219098009bf28a Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:31:02 +0000
 | 
			
		||||
Subject: [PATCH 04/13] net: phy: add phy_inband_caps()
 | 
			
		||||
 | 
			
		||||
Add a method to query the PHY's in-band capabilities for a PHY
 | 
			
		||||
interface mode.
 | 
			
		||||
 | 
			
		||||
Where the interface mode does not have in-band capability, or the PHY
 | 
			
		||||
driver has not been updated to return this information, then
 | 
			
		||||
phy_inband_caps() should return zero. Otherwise, PHY drivers will
 | 
			
		||||
return a value consisting of the following flags:
 | 
			
		||||
 | 
			
		||||
LINK_INBAND_DISABLE indicates that the hardware does not support
 | 
			
		||||
in-band signalling, or can have in-band signalling configured via
 | 
			
		||||
software to be disabled.
 | 
			
		||||
 | 
			
		||||
LINK_INBAND_ENABLE indicates that the hardware will use in-band
 | 
			
		||||
signalling, or can have in-band signalling configured via software
 | 
			
		||||
to be enabled.
 | 
			
		||||
 | 
			
		||||
LINK_INBAND_BYPASS indicates that the hardware has the ability to
 | 
			
		||||
bypass in-band signalling when enabled after a timeout if the link
 | 
			
		||||
partner does not respond to its in-band signalling.
 | 
			
		||||
 | 
			
		||||
This reports the PHY capabilities for the particular interface mode,
 | 
			
		||||
not the current configuration.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUre-006ITz-KF@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phy.c | 21 +++++++++++++++++++++
 | 
			
		||||
 include/linux/phy.h   | 28 ++++++++++++++++++++++++++++
 | 
			
		||||
 2 files changed, 49 insertions(+)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phy.c
 | 
			
		||||
+++ b/drivers/net/phy/phy.c
 | 
			
		||||
@@ -1049,6 +1049,27 @@ static int phy_check_link_status(struct
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 /**
 | 
			
		||||
+ * phy_inband_caps - query which in-band signalling modes are supported
 | 
			
		||||
+ * @phydev: a pointer to a &struct phy_device
 | 
			
		||||
+ * @interface: the interface mode for the PHY
 | 
			
		||||
+ *
 | 
			
		||||
+ * Returns zero if it is unknown what in-band signalling is supported by the
 | 
			
		||||
+ * PHY (e.g. because the PHY driver doesn't implement the method.) Otherwise,
 | 
			
		||||
+ * returns a bit mask of the LINK_INBAND_* values from
 | 
			
		||||
+ * &enum link_inband_signalling to describe which inband modes are supported
 | 
			
		||||
+ * by the PHY for this interface mode.
 | 
			
		||||
+ */
 | 
			
		||||
+unsigned int phy_inband_caps(struct phy_device *phydev,
 | 
			
		||||
+			     phy_interface_t interface)
 | 
			
		||||
+{
 | 
			
		||||
+	if (phydev->drv && phydev->drv->inband_caps)
 | 
			
		||||
+		return phydev->drv->inband_caps(phydev, interface);
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+EXPORT_SYMBOL_GPL(phy_inband_caps);
 | 
			
		||||
+
 | 
			
		||||
+/**
 | 
			
		||||
  * _phy_start_aneg - start auto-negotiation for this PHY device
 | 
			
		||||
  * @phydev: the phy_device struct
 | 
			
		||||
  *
 | 
			
		||||
--- a/include/linux/phy.h
 | 
			
		||||
+++ b/include/linux/phy.h
 | 
			
		||||
@@ -816,6 +816,24 @@ struct phy_tdr_config {
 | 
			
		||||
 #define PHY_PAIR_ALL -1
 | 
			
		||||
 
 | 
			
		||||
 /**
 | 
			
		||||
+ * enum link_inband_signalling - in-band signalling modes that are supported
 | 
			
		||||
+ *
 | 
			
		||||
+ * @LINK_INBAND_DISABLE: in-band signalling can be disabled
 | 
			
		||||
+ * @LINK_INBAND_ENABLE: in-band signalling can be enabled without bypass
 | 
			
		||||
+ * @LINK_INBAND_BYPASS: in-band signalling can be enabled with bypass
 | 
			
		||||
+ *
 | 
			
		||||
+ * The possible and required bits can only be used if the valid bit is set.
 | 
			
		||||
+ * If possible is clear, that means inband signalling can not be used.
 | 
			
		||||
+ * Required is only valid when possible is set, and means that inband
 | 
			
		||||
+ * signalling must be used.
 | 
			
		||||
+ */
 | 
			
		||||
+enum link_inband_signalling {
 | 
			
		||||
+	LINK_INBAND_DISABLE		= BIT(0),
 | 
			
		||||
+	LINK_INBAND_ENABLE		= BIT(1),
 | 
			
		||||
+	LINK_INBAND_BYPASS		= BIT(2),
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+/**
 | 
			
		||||
  * struct phy_plca_cfg - Configuration of the PLCA (Physical Layer Collision
 | 
			
		||||
  * Avoidance) Reconciliation Sublayer.
 | 
			
		||||
  *
 | 
			
		||||
@@ -954,6 +972,14 @@ struct phy_driver {
 | 
			
		||||
 	int (*get_features)(struct phy_device *phydev);
 | 
			
		||||
 
 | 
			
		||||
 	/**
 | 
			
		||||
+	 * @inband_caps: query whether in-band is supported for the given PHY
 | 
			
		||||
+	 * interface mode. Returns a bitmask of bits defined by enum
 | 
			
		||||
+	 * link_inband_signalling.
 | 
			
		||||
+	 */
 | 
			
		||||
+	unsigned int (*inband_caps)(struct phy_device *phydev,
 | 
			
		||||
+				    phy_interface_t interface);
 | 
			
		||||
+
 | 
			
		||||
+	/**
 | 
			
		||||
 	 * @get_rate_matching: Get the supported type of rate matching for a
 | 
			
		||||
 	 * particular phy interface. This is used by phy consumers to determine
 | 
			
		||||
 	 * whether to advertise lower-speed modes for that interface. It is
 | 
			
		||||
@@ -1832,6 +1858,8 @@ int phy_config_aneg(struct phy_device *p
 | 
			
		||||
 int _phy_start_aneg(struct phy_device *phydev);
 | 
			
		||||
 int phy_start_aneg(struct phy_device *phydev);
 | 
			
		||||
 int phy_aneg_done(struct phy_device *phydev);
 | 
			
		||||
+unsigned int phy_inband_caps(struct phy_device *phydev,
 | 
			
		||||
+			     phy_interface_t interface);
 | 
			
		||||
 int phy_speed_down(struct phy_device *phydev, bool sync);
 | 
			
		||||
 int phy_speed_up(struct phy_device *phydev);
 | 
			
		||||
 bool phy_check_valid(int speed, int duplex, unsigned long *features);
 | 
			
		||||
@ -0,0 +1,41 @@
 | 
			
		||||
From c64c7fa0a774d9da72071a8517e359992baac982 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:31:07 +0000
 | 
			
		||||
Subject: [PATCH 05/13] net: phy: bcm84881: implement phy_inband_caps() method
 | 
			
		||||
 | 
			
		||||
BCM84881 has no support for inband signalling, so this is a trivial
 | 
			
		||||
implementation that returns no support for inband.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Acked-by: Florian Fainelli <florian.fainelli@broadcom.com>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUrj-006IU6-ON@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/bcm84881.c | 10 ++++++++++
 | 
			
		||||
 1 file changed, 10 insertions(+)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/bcm84881.c
 | 
			
		||||
+++ b/drivers/net/phy/bcm84881.c
 | 
			
		||||
@@ -235,11 +235,21 @@ static int bcm84881_read_status(struct p
 | 
			
		||||
 	return genphy_c45_read_mdix(phydev);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+/* The Broadcom BCM84881 in the Methode DM7052 is unable to provide a SGMII
 | 
			
		||||
+ * or 802.3z control word, so inband will not work.
 | 
			
		||||
+ */
 | 
			
		||||
+static unsigned int bcm84881_inband_caps(struct phy_device *phydev,
 | 
			
		||||
+					 phy_interface_t interface)
 | 
			
		||||
+{
 | 
			
		||||
+	return LINK_INBAND_DISABLE;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static struct phy_driver bcm84881_drivers[] = {
 | 
			
		||||
 	{
 | 
			
		||||
 		.phy_id		= 0xae025150,
 | 
			
		||||
 		.phy_id_mask	= 0xfffffff0,
 | 
			
		||||
 		.name		= "Broadcom BCM84881",
 | 
			
		||||
+		.inband_caps	= bcm84881_inband_caps,
 | 
			
		||||
 		.config_init	= bcm84881_config_init,
 | 
			
		||||
 		.probe		= bcm84881_probe,
 | 
			
		||||
 		.get_features	= bcm84881_get_features,
 | 
			
		||||
@ -0,0 +1,63 @@
 | 
			
		||||
From 1c86828dff88e28b8ade6bddeee0163a023faf91 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:31:12 +0000
 | 
			
		||||
Subject: [PATCH 06/13] net: phy: marvell: implement phy_inband_caps() method
 | 
			
		||||
 | 
			
		||||
Provide an implementation for phy_inband_caps() for Marvell PHYs used
 | 
			
		||||
on SFP modules, so that phylink knows the PHYs capabilities.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUro-006IUC-Rq@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/marvell.c | 17 +++++++++++++++++
 | 
			
		||||
 1 file changed, 17 insertions(+)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/marvell.c
 | 
			
		||||
+++ b/drivers/net/phy/marvell.c
 | 
			
		||||
@@ -716,6 +716,20 @@ static int marvell_config_aneg_fiber(str
 | 
			
		||||
 	return genphy_check_and_restart_aneg(phydev, changed);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static unsigned int m88e1111_inband_caps(struct phy_device *phydev,
 | 
			
		||||
+					 phy_interface_t interface)
 | 
			
		||||
+{
 | 
			
		||||
+	/* In 1000base-X and SGMII modes, the inband mode can be changed
 | 
			
		||||
+	 * through the Fibre page BMCR ANENABLE bit.
 | 
			
		||||
+	 */
 | 
			
		||||
+	if (interface == PHY_INTERFACE_MODE_1000BASEX ||
 | 
			
		||||
+	    interface == PHY_INTERFACE_MODE_SGMII)
 | 
			
		||||
+		return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE |
 | 
			
		||||
+		       LINK_INBAND_BYPASS;
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static int m88e1111_config_aneg(struct phy_device *phydev)
 | 
			
		||||
 {
 | 
			
		||||
 	int extsr = phy_read(phydev, MII_M1111_PHY_EXT_SR);
 | 
			
		||||
@@ -3667,6 +3681,7 @@ static struct phy_driver marvell_drivers
 | 
			
		||||
 		.name = "Marvell 88E1112",
 | 
			
		||||
 		/* PHY_GBIT_FEATURES */
 | 
			
		||||
 		.probe = marvell_probe,
 | 
			
		||||
+		.inband_caps = m88e1111_inband_caps,
 | 
			
		||||
 		.config_init = m88e1112_config_init,
 | 
			
		||||
 		.config_aneg = marvell_config_aneg,
 | 
			
		||||
 		.config_intr = marvell_config_intr,
 | 
			
		||||
@@ -3688,6 +3703,7 @@ static struct phy_driver marvell_drivers
 | 
			
		||||
 		/* PHY_GBIT_FEATURES */
 | 
			
		||||
 		.flags = PHY_POLL_CABLE_TEST,
 | 
			
		||||
 		.probe = marvell_probe,
 | 
			
		||||
+		.inband_caps = m88e1111_inband_caps,
 | 
			
		||||
 		.config_init = m88e1111gbe_config_init,
 | 
			
		||||
 		.config_aneg = m88e1111_config_aneg,
 | 
			
		||||
 		.read_status = marvell_read_status,
 | 
			
		||||
@@ -3711,6 +3727,7 @@ static struct phy_driver marvell_drivers
 | 
			
		||||
 		.name = "Marvell 88E1111 (Finisar)",
 | 
			
		||||
 		/* PHY_GBIT_FEATURES */
 | 
			
		||||
 		.probe = marvell_probe,
 | 
			
		||||
+		.inband_caps = m88e1111_inband_caps,
 | 
			
		||||
 		.config_init = m88e1111gbe_config_init,
 | 
			
		||||
 		.config_aneg = m88e1111_config_aneg,
 | 
			
		||||
 		.read_status = marvell_read_status,
 | 
			
		||||
@ -0,0 +1,79 @@
 | 
			
		||||
From 5d58a890c02770ba8d790b1f3c6e8c0e20514dc2 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:31:18 +0000
 | 
			
		||||
Subject: [PATCH 07/13] net: phy: add phy_config_inband()
 | 
			
		||||
 | 
			
		||||
Add a method to configure the PHY's in-band mode.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUru-006IUI-08@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phy.c | 32 ++++++++++++++++++++++++++++++++
 | 
			
		||||
 include/linux/phy.h   |  6 ++++++
 | 
			
		||||
 2 files changed, 38 insertions(+)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phy.c
 | 
			
		||||
+++ b/drivers/net/phy/phy.c
 | 
			
		||||
@@ -1070,6 +1070,38 @@ unsigned int phy_inband_caps(struct phy_
 | 
			
		||||
 EXPORT_SYMBOL_GPL(phy_inband_caps);
 | 
			
		||||
 
 | 
			
		||||
 /**
 | 
			
		||||
+ * phy_config_inband - configure the desired PHY in-band mode
 | 
			
		||||
+ * @phydev: the phy_device struct
 | 
			
		||||
+ * @modes: in-band modes to configure
 | 
			
		||||
+ *
 | 
			
		||||
+ * Description: disables, enables or enables-with-bypass in-band signalling
 | 
			
		||||
+ *   between the PHY and host system.
 | 
			
		||||
+ *
 | 
			
		||||
+ * Returns: zero on success, or negative errno value.
 | 
			
		||||
+ */
 | 
			
		||||
+int phy_config_inband(struct phy_device *phydev, unsigned int modes)
 | 
			
		||||
+{
 | 
			
		||||
+	int err;
 | 
			
		||||
+
 | 
			
		||||
+	if (!!(modes & LINK_INBAND_DISABLE) +
 | 
			
		||||
+	    !!(modes & LINK_INBAND_ENABLE) +
 | 
			
		||||
+	    !!(modes & LINK_INBAND_BYPASS) != 1)
 | 
			
		||||
+		return -EINVAL;
 | 
			
		||||
+
 | 
			
		||||
+	mutex_lock(&phydev->lock);
 | 
			
		||||
+	if (!phydev->drv)
 | 
			
		||||
+		err = -EIO;
 | 
			
		||||
+	else if (!phydev->drv->config_inband)
 | 
			
		||||
+		err = -EOPNOTSUPP;
 | 
			
		||||
+	else
 | 
			
		||||
+		err = phydev->drv->config_inband(phydev, modes);
 | 
			
		||||
+	mutex_unlock(&phydev->lock);
 | 
			
		||||
+
 | 
			
		||||
+	return err;
 | 
			
		||||
+}
 | 
			
		||||
+EXPORT_SYMBOL(phy_config_inband);
 | 
			
		||||
+
 | 
			
		||||
+/**
 | 
			
		||||
  * _phy_start_aneg - start auto-negotiation for this PHY device
 | 
			
		||||
  * @phydev: the phy_device struct
 | 
			
		||||
  *
 | 
			
		||||
--- a/include/linux/phy.h
 | 
			
		||||
+++ b/include/linux/phy.h
 | 
			
		||||
@@ -980,6 +980,11 @@ struct phy_driver {
 | 
			
		||||
 				    phy_interface_t interface);
 | 
			
		||||
 
 | 
			
		||||
 	/**
 | 
			
		||||
+	 * @config_inband: configure in-band mode for the PHY
 | 
			
		||||
+	 */
 | 
			
		||||
+	int (*config_inband)(struct phy_device *phydev, unsigned int modes);
 | 
			
		||||
+
 | 
			
		||||
+	/**
 | 
			
		||||
 	 * @get_rate_matching: Get the supported type of rate matching for a
 | 
			
		||||
 	 * particular phy interface. This is used by phy consumers to determine
 | 
			
		||||
 	 * whether to advertise lower-speed modes for that interface. It is
 | 
			
		||||
@@ -1860,6 +1865,7 @@ int phy_start_aneg(struct phy_device *ph
 | 
			
		||||
 int phy_aneg_done(struct phy_device *phydev);
 | 
			
		||||
 unsigned int phy_inband_caps(struct phy_device *phydev,
 | 
			
		||||
 			     phy_interface_t interface);
 | 
			
		||||
+int phy_config_inband(struct phy_device *phydev, unsigned int modes);
 | 
			
		||||
 int phy_speed_down(struct phy_device *phydev, bool sync);
 | 
			
		||||
 int phy_speed_up(struct phy_device *phydev);
 | 
			
		||||
 bool phy_check_valid(int speed, int duplex, unsigned long *features);
 | 
			
		||||
@ -0,0 +1,77 @@
 | 
			
		||||
From a219912e0fec73c346e64ef47013cb2e152f88fc Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:31:23 +0000
 | 
			
		||||
Subject: [PATCH 08/13] net: phy: marvell: implement config_inband() method
 | 
			
		||||
 | 
			
		||||
Implement the config_inband() method for Marvell 88E1112, 88E1111,
 | 
			
		||||
and Finisar's 88E1111 variant.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUrz-006IUO-3r@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/marvell.c | 31 +++++++++++++++++++++++++++++++
 | 
			
		||||
 1 file changed, 31 insertions(+)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/marvell.c
 | 
			
		||||
+++ b/drivers/net/phy/marvell.c
 | 
			
		||||
@@ -730,6 +730,34 @@ static unsigned int m88e1111_inband_caps
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static int m88e1111_config_inband(struct phy_device *phydev, unsigned int modes)
 | 
			
		||||
+{
 | 
			
		||||
+	u16 extsr, bmcr;
 | 
			
		||||
+	int err;
 | 
			
		||||
+
 | 
			
		||||
+	if (phydev->interface != PHY_INTERFACE_MODE_1000BASEX &&
 | 
			
		||||
+	    phydev->interface != PHY_INTERFACE_MODE_SGMII)
 | 
			
		||||
+		return -EINVAL;
 | 
			
		||||
+
 | 
			
		||||
+	if (modes == LINK_INBAND_BYPASS)
 | 
			
		||||
+		extsr = MII_M1111_HWCFG_SERIAL_AN_BYPASS;
 | 
			
		||||
+	else
 | 
			
		||||
+		extsr = 0;
 | 
			
		||||
+
 | 
			
		||||
+	if (modes == LINK_INBAND_DISABLE)
 | 
			
		||||
+		bmcr = 0;
 | 
			
		||||
+	else
 | 
			
		||||
+		bmcr = BMCR_ANENABLE;
 | 
			
		||||
+
 | 
			
		||||
+	err = phy_modify(phydev, MII_M1111_PHY_EXT_SR,
 | 
			
		||||
+			 MII_M1111_HWCFG_SERIAL_AN_BYPASS, extsr);
 | 
			
		||||
+	if (err < 0)
 | 
			
		||||
+		return extsr;
 | 
			
		||||
+
 | 
			
		||||
+	return phy_modify_paged(phydev, MII_MARVELL_FIBER_PAGE, MII_BMCR,
 | 
			
		||||
+				BMCR_ANENABLE, bmcr);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static int m88e1111_config_aneg(struct phy_device *phydev)
 | 
			
		||||
 {
 | 
			
		||||
 	int extsr = phy_read(phydev, MII_M1111_PHY_EXT_SR);
 | 
			
		||||
@@ -3682,6 +3710,7 @@ static struct phy_driver marvell_drivers
 | 
			
		||||
 		/* PHY_GBIT_FEATURES */
 | 
			
		||||
 		.probe = marvell_probe,
 | 
			
		||||
 		.inband_caps = m88e1111_inband_caps,
 | 
			
		||||
+		.config_inband = m88e1111_config_inband,
 | 
			
		||||
 		.config_init = m88e1112_config_init,
 | 
			
		||||
 		.config_aneg = marvell_config_aneg,
 | 
			
		||||
 		.config_intr = marvell_config_intr,
 | 
			
		||||
@@ -3704,6 +3733,7 @@ static struct phy_driver marvell_drivers
 | 
			
		||||
 		.flags = PHY_POLL_CABLE_TEST,
 | 
			
		||||
 		.probe = marvell_probe,
 | 
			
		||||
 		.inband_caps = m88e1111_inband_caps,
 | 
			
		||||
+		.config_inband = m88e1111_config_inband,
 | 
			
		||||
 		.config_init = m88e1111gbe_config_init,
 | 
			
		||||
 		.config_aneg = m88e1111_config_aneg,
 | 
			
		||||
 		.read_status = marvell_read_status,
 | 
			
		||||
@@ -3728,6 +3758,7 @@ static struct phy_driver marvell_drivers
 | 
			
		||||
 		/* PHY_GBIT_FEATURES */
 | 
			
		||||
 		.probe = marvell_probe,
 | 
			
		||||
 		.inband_caps = m88e1111_inband_caps,
 | 
			
		||||
+		.config_inband = m88e1111_config_inband,
 | 
			
		||||
 		.config_init = m88e1111gbe_config_init,
 | 
			
		||||
 		.config_aneg = m88e1111_config_aneg,
 | 
			
		||||
 		.read_status = marvell_read_status,
 | 
			
		||||
@ -0,0 +1,159 @@
 | 
			
		||||
From df874f9e52c340cc6f0a0014a97b778f67d46849 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:31:28 +0000
 | 
			
		||||
Subject: [PATCH 09/13] net: phylink: add pcs_inband_caps() method
 | 
			
		||||
 | 
			
		||||
Add a pcs_inband_caps() method to query the PCS for its inband link
 | 
			
		||||
capabilities, and use this to determine whether link modes used with
 | 
			
		||||
optical SFPs can be supported.
 | 
			
		||||
 | 
			
		||||
When a PCS does not provide a method, we allow inband negotiation to
 | 
			
		||||
be either on or off, making this a no-op until the pcs_inband_caps()
 | 
			
		||||
method is implemented by a PCS driver.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUs4-006IUU-7K@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phylink.c | 60 +++++++++++++++++++++++++++++++++++++++
 | 
			
		||||
 include/linux/phylink.h   | 17 +++++++++++
 | 
			
		||||
 2 files changed, 77 insertions(+)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -1007,6 +1007,15 @@ static void phylink_resolve_an_pause(str
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static unsigned int phylink_pcs_inband_caps(struct phylink_pcs *pcs,
 | 
			
		||||
+				    phy_interface_t interface)
 | 
			
		||||
+{
 | 
			
		||||
+	if (pcs && pcs->ops->pcs_inband_caps)
 | 
			
		||||
+		return pcs->ops->pcs_inband_caps(pcs, interface);
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static void phylink_pcs_pre_config(struct phylink_pcs *pcs,
 | 
			
		||||
 				   phy_interface_t interface)
 | 
			
		||||
 {
 | 
			
		||||
@@ -1060,6 +1069,24 @@ static void phylink_pcs_link_up(struct p
 | 
			
		||||
 		pcs->ops->pcs_link_up(pcs, neg_mode, interface, speed, duplex);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+/* Query inband for a specific interface mode, asking the MAC for the
 | 
			
		||||
+ * PCS which will be used to handle the interface mode.
 | 
			
		||||
+ */
 | 
			
		||||
+static unsigned int phylink_inband_caps(struct phylink *pl,
 | 
			
		||||
+					 phy_interface_t interface)
 | 
			
		||||
+{
 | 
			
		||||
+	struct phylink_pcs *pcs;
 | 
			
		||||
+
 | 
			
		||||
+	if (!pl->mac_ops->mac_select_pcs)
 | 
			
		||||
+		return 0;
 | 
			
		||||
+
 | 
			
		||||
+	pcs = pl->mac_ops->mac_select_pcs(pl->config, interface);
 | 
			
		||||
+	if (!pcs)
 | 
			
		||||
+		return 0;
 | 
			
		||||
+
 | 
			
		||||
+	return phylink_pcs_inband_caps(pcs, interface);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static void phylink_pcs_poll_stop(struct phylink *pl)
 | 
			
		||||
 {
 | 
			
		||||
 	if (pl->cfg_link_an_mode == MLO_AN_INBAND)
 | 
			
		||||
@@ -2530,6 +2557,26 @@ int phylink_ethtool_ksettings_get(struct
 | 
			
		||||
 }
 | 
			
		||||
 EXPORT_SYMBOL_GPL(phylink_ethtool_ksettings_get);
 | 
			
		||||
 
 | 
			
		||||
+static bool phylink_validate_pcs_inband_autoneg(struct phylink *pl,
 | 
			
		||||
+					        phy_interface_t interface,
 | 
			
		||||
+						unsigned long *adv)
 | 
			
		||||
+{
 | 
			
		||||
+	unsigned int inband = phylink_inband_caps(pl, interface);
 | 
			
		||||
+	unsigned int mask;
 | 
			
		||||
+
 | 
			
		||||
+	/* If the PCS doesn't implement inband support, be permissive. */
 | 
			
		||||
+	if (!inband)
 | 
			
		||||
+		return true;
 | 
			
		||||
+
 | 
			
		||||
+	if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, adv))
 | 
			
		||||
+		mask = LINK_INBAND_ENABLE;
 | 
			
		||||
+	else
 | 
			
		||||
+		mask = LINK_INBAND_DISABLE;
 | 
			
		||||
+
 | 
			
		||||
+	/* Check whether the PCS implements the required mode */
 | 
			
		||||
+	return !!(inband & mask);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 /**
 | 
			
		||||
  * phylink_ethtool_ksettings_set() - set the link settings
 | 
			
		||||
  * @pl: a pointer to a &struct phylink returned from phylink_create()
 | 
			
		||||
@@ -2665,6 +2712,13 @@ int phylink_ethtool_ksettings_set(struct
 | 
			
		||||
 	    phylink_is_empty_linkmode(config.advertising))
 | 
			
		||||
 		return -EINVAL;
 | 
			
		||||
 
 | 
			
		||||
+	/* Validate the autonegotiation state. We don't have a PHY in this
 | 
			
		||||
+	 * situation, so the PCS is the media-facing entity.
 | 
			
		||||
+	 */
 | 
			
		||||
+	if (!phylink_validate_pcs_inband_autoneg(pl, config.interface,
 | 
			
		||||
+						 config.advertising))
 | 
			
		||||
+		return -EINVAL;
 | 
			
		||||
+
 | 
			
		||||
 	mutex_lock(&pl->state_mutex);
 | 
			
		||||
 	pl->link_config.speed = config.speed;
 | 
			
		||||
 	pl->link_config.duplex = config.duplex;
 | 
			
		||||
@@ -3349,6 +3403,12 @@ static int phylink_sfp_config_optical(st
 | 
			
		||||
 	phylink_dbg(pl, "optical SFP: chosen %s interface\n",
 | 
			
		||||
 		    phy_modes(interface));
 | 
			
		||||
 
 | 
			
		||||
+	if (!phylink_validate_pcs_inband_autoneg(pl, interface,
 | 
			
		||||
+						 config.advertising)) {
 | 
			
		||||
+		phylink_err(pl, "autoneg setting not compatible with PCS");
 | 
			
		||||
+		return -EINVAL;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
 	config.interface = interface;
 | 
			
		||||
 
 | 
			
		||||
 	/* Ignore errors if we're expecting a PHY to attach later */
 | 
			
		||||
--- a/include/linux/phylink.h
 | 
			
		||||
+++ b/include/linux/phylink.h
 | 
			
		||||
@@ -419,6 +419,7 @@ struct phylink_pcs {
 | 
			
		||||
 /**
 | 
			
		||||
  * struct phylink_pcs_ops - MAC PCS operations structure.
 | 
			
		||||
  * @pcs_validate: validate the link configuration.
 | 
			
		||||
+ * @pcs_inband_caps: query inband support for interface mode.
 | 
			
		||||
  * @pcs_enable: enable the PCS.
 | 
			
		||||
  * @pcs_disable: disable the PCS.
 | 
			
		||||
  * @pcs_pre_config: pre-mac_config method (for errata)
 | 
			
		||||
@@ -434,6 +435,8 @@ struct phylink_pcs {
 | 
			
		||||
 struct phylink_pcs_ops {
 | 
			
		||||
 	int (*pcs_validate)(struct phylink_pcs *pcs, unsigned long *supported,
 | 
			
		||||
 			    const struct phylink_link_state *state);
 | 
			
		||||
+	unsigned int (*pcs_inband_caps)(struct phylink_pcs *pcs,
 | 
			
		||||
+					phy_interface_t interface);
 | 
			
		||||
 	int (*pcs_enable)(struct phylink_pcs *pcs);
 | 
			
		||||
 	void (*pcs_disable)(struct phylink_pcs *pcs);
 | 
			
		||||
 	void (*pcs_pre_config)(struct phylink_pcs *pcs,
 | 
			
		||||
@@ -471,6 +474,20 @@ int pcs_validate(struct phylink_pcs *pcs
 | 
			
		||||
 		 const struct phylink_link_state *state);
 | 
			
		||||
 
 | 
			
		||||
 /**
 | 
			
		||||
+ * pcs_inband_caps - query PCS in-band capabilities for interface mode.
 | 
			
		||||
+ * @pcs: a pointer to a &struct phylink_pcs.
 | 
			
		||||
+ * @interface: interface mode to be queried
 | 
			
		||||
+ *
 | 
			
		||||
+ * Returns zero if it is unknown what in-band signalling is supported by the
 | 
			
		||||
+ * PHY (e.g. because the PHY driver doesn't implement the method.) Otherwise,
 | 
			
		||||
+ * returns a bit mask of the LINK_INBAND_* values from
 | 
			
		||||
+ * &enum link_inband_signalling to describe which inband modes are supported
 | 
			
		||||
+ * for this interface mode.
 | 
			
		||||
+ */
 | 
			
		||||
+unsigned int pcs_inband_caps(struct phylink_pcs *pcs,
 | 
			
		||||
+			     phy_interface_t interface);
 | 
			
		||||
+
 | 
			
		||||
+/**
 | 
			
		||||
  * pcs_enable() - enable the PCS.
 | 
			
		||||
  * @pcs: a pointer to a &struct phylink_pcs.
 | 
			
		||||
  */
 | 
			
		||||
@ -0,0 +1,64 @@
 | 
			
		||||
From 513e8fb8fa32035b3325e2e14fb9598f8cb545e9 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:31:33 +0000
 | 
			
		||||
Subject: [PATCH 10/13] net: mvneta: implement pcs_inband_caps() method
 | 
			
		||||
 | 
			
		||||
Report the PCS in-band capabilities to phylink for Marvell NETA
 | 
			
		||||
interfaces.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUs9-006IUb-Au@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/ethernet/marvell/mvneta.c | 27 +++++++++++++++++----------
 | 
			
		||||
 1 file changed, 17 insertions(+), 10 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/ethernet/marvell/mvneta.c
 | 
			
		||||
+++ b/drivers/net/ethernet/marvell/mvneta.c
 | 
			
		||||
@@ -3960,20 +3960,27 @@ static struct mvneta_port *mvneta_pcs_to
 | 
			
		||||
 	return container_of(pcs, struct mvneta_port, phylink_pcs);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static int mvneta_pcs_validate(struct phylink_pcs *pcs,
 | 
			
		||||
-			       unsigned long *supported,
 | 
			
		||||
-			       const struct phylink_link_state *state)
 | 
			
		||||
+static unsigned int mvneta_pcs_inband_caps(struct phylink_pcs *pcs,
 | 
			
		||||
+					   phy_interface_t interface)
 | 
			
		||||
 {
 | 
			
		||||
-	/* We only support QSGMII, SGMII, 802.3z and RGMII modes.
 | 
			
		||||
-	 * When in 802.3z mode, we must have AN enabled:
 | 
			
		||||
+	/* When operating in an 802.3z mode, we must have AN enabled:
 | 
			
		||||
 	 * "Bit 2 Field InBandAnEn In-band Auto-Negotiation enable. ...
 | 
			
		||||
 	 * When <PortType> = 1 (1000BASE-X) this field must be set to 1."
 | 
			
		||||
+	 * Therefore, inband is "required".
 | 
			
		||||
 	 */
 | 
			
		||||
-	if (phy_interface_mode_is_8023z(state->interface) &&
 | 
			
		||||
-	    !phylink_test(state->advertising, Autoneg))
 | 
			
		||||
-		return -EINVAL;
 | 
			
		||||
+	if (phy_interface_mode_is_8023z(interface))
 | 
			
		||||
+		return LINK_INBAND_ENABLE;
 | 
			
		||||
 
 | 
			
		||||
-	return 0;
 | 
			
		||||
+	/* QSGMII, SGMII and RGMII can be configured to use inband
 | 
			
		||||
+	 * signalling of the AN result. Indicate these as "possible".
 | 
			
		||||
+	 */
 | 
			
		||||
+	if (interface == PHY_INTERFACE_MODE_SGMII ||
 | 
			
		||||
+	    interface == PHY_INTERFACE_MODE_QSGMII ||
 | 
			
		||||
+	    phy_interface_mode_is_rgmii(interface))
 | 
			
		||||
+		return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
 | 
			
		||||
+
 | 
			
		||||
+	/* For any other modes, indicate that inband is not supported. */
 | 
			
		||||
+	return LINK_INBAND_DISABLE;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void mvneta_pcs_get_state(struct phylink_pcs *pcs,
 | 
			
		||||
@@ -4071,7 +4078,7 @@ static void mvneta_pcs_an_restart(struct
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static const struct phylink_pcs_ops mvneta_phylink_pcs_ops = {
 | 
			
		||||
-	.pcs_validate = mvneta_pcs_validate,
 | 
			
		||||
+	.pcs_inband_caps = mvneta_pcs_inband_caps,
 | 
			
		||||
 	.pcs_get_state = mvneta_pcs_get_state,
 | 
			
		||||
 	.pcs_config = mvneta_pcs_config,
 | 
			
		||||
 	.pcs_an_restart = mvneta_pcs_an_restart,
 | 
			
		||||
@ -0,0 +1,62 @@
 | 
			
		||||
From d4169f0c7665afb8d8adb5e1b1df3db88517d0ad Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:31:38 +0000
 | 
			
		||||
Subject: [PATCH 11/13] net: mvpp2: implement pcs_inband_caps() method
 | 
			
		||||
 | 
			
		||||
Report the PCS in-band capabilities to phylink for Marvell PP2
 | 
			
		||||
interfaces.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUsE-006IUh-E7@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 .../net/ethernet/marvell/mvpp2/mvpp2_main.c   | 25 ++++++++++++-------
 | 
			
		||||
 1 file changed, 16 insertions(+), 9 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
 | 
			
		||||
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
 | 
			
		||||
@@ -6237,19 +6237,26 @@ static const struct phylink_pcs_ops mvpp
 | 
			
		||||
 	.pcs_config = mvpp2_xlg_pcs_config,
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
-static int mvpp2_gmac_pcs_validate(struct phylink_pcs *pcs,
 | 
			
		||||
-				   unsigned long *supported,
 | 
			
		||||
-				   const struct phylink_link_state *state)
 | 
			
		||||
+static unsigned int mvpp2_gmac_pcs_inband_caps(struct phylink_pcs *pcs,
 | 
			
		||||
+					       phy_interface_t interface)
 | 
			
		||||
 {
 | 
			
		||||
-	/* When in 802.3z mode, we must have AN enabled:
 | 
			
		||||
+	/* When operating in an 802.3z mode, we must have AN enabled:
 | 
			
		||||
 	 * Bit 2 Field InBandAnEn In-band Auto-Negotiation enable. ...
 | 
			
		||||
 	 * When <PortType> = 1 (1000BASE-X) this field must be set to 1.
 | 
			
		||||
+	 * Therefore, inband is "required".
 | 
			
		||||
 	 */
 | 
			
		||||
-	if (phy_interface_mode_is_8023z(state->interface) &&
 | 
			
		||||
-	    !phylink_test(state->advertising, Autoneg))
 | 
			
		||||
-		return -EINVAL;
 | 
			
		||||
+	if (phy_interface_mode_is_8023z(interface))
 | 
			
		||||
+		return LINK_INBAND_ENABLE;
 | 
			
		||||
 
 | 
			
		||||
-	return 0;
 | 
			
		||||
+	/* SGMII and RGMII can be configured to use inband signalling of the
 | 
			
		||||
+	 * AN result. Indicate these as "possible".
 | 
			
		||||
+	 */
 | 
			
		||||
+	if (interface == PHY_INTERFACE_MODE_SGMII ||
 | 
			
		||||
+	    phy_interface_mode_is_rgmii(interface))
 | 
			
		||||
+		return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
 | 
			
		||||
+
 | 
			
		||||
+	/* For any other modes, indicate that inband is not supported. */
 | 
			
		||||
+	return LINK_INBAND_DISABLE;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void mvpp2_gmac_pcs_get_state(struct phylink_pcs *pcs,
 | 
			
		||||
@@ -6356,7 +6363,7 @@ static void mvpp2_gmac_pcs_an_restart(st
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static const struct phylink_pcs_ops mvpp2_phylink_gmac_pcs_ops = {
 | 
			
		||||
-	.pcs_validate = mvpp2_gmac_pcs_validate,
 | 
			
		||||
+	.pcs_inband_caps = mvpp2_gmac_pcs_inband_caps,
 | 
			
		||||
 	.pcs_get_state = mvpp2_gmac_pcs_get_state,
 | 
			
		||||
 	.pcs_config = mvpp2_gmac_pcs_config,
 | 
			
		||||
 	.pcs_an_restart = mvpp2_gmac_pcs_an_restart,
 | 
			
		||||
@ -0,0 +1,228 @@
 | 
			
		||||
From 5fd0f1a02e750e2db4038dee60edea669ce5aab1 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:31:43 +0000
 | 
			
		||||
Subject: [PATCH 12/13] net: phylink: add negotiation of in-band capabilities
 | 
			
		||||
 | 
			
		||||
Support for in-band signalling with Serdes links is uncertain. Some
 | 
			
		||||
PHYs do not support in-band for e.g. SGMII. Some PCS do not support
 | 
			
		||||
in-band for 2500Base-X. Some PCS require in-band for Base-X protocols.
 | 
			
		||||
 | 
			
		||||
Simply using what is in DT is insufficient when we have hot-pluggable
 | 
			
		||||
PHYs e.g. in the form of SFP modules, which may not provide the
 | 
			
		||||
in-band signalling.
 | 
			
		||||
 | 
			
		||||
In order to address this, we have introduced phy_inband_caps() and
 | 
			
		||||
pcs_inband_caps() functions to allow phylink to retrieve the
 | 
			
		||||
capabilities from each end of the PCS/PHY link. This commit adds code
 | 
			
		||||
to resolve whether in-band will be used in the various scenarios that
 | 
			
		||||
we have: In-band not being used, PHY present using SGMII or Base-X,
 | 
			
		||||
PHY not present. We also deal with no capabilties provided.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUsJ-006IUn-H3@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phylink.c | 154 +++++++++++++++++++++++++++++++++++---
 | 
			
		||||
 1 file changed, 144 insertions(+), 10 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -75,6 +75,7 @@ struct phylink {
 | 
			
		||||
 
 | 
			
		||||
 	struct mutex state_mutex;
 | 
			
		||||
 	struct phylink_link_state phy_state;
 | 
			
		||||
+	unsigned int phy_ib_mode;
 | 
			
		||||
 	struct work_struct resolve;
 | 
			
		||||
 	unsigned int pcs_neg_mode;
 | 
			
		||||
 	unsigned int pcs_state;
 | 
			
		||||
@@ -1170,10 +1171,18 @@ static void phylink_pcs_neg_mode(struct
 | 
			
		||||
 				 phy_interface_t interface,
 | 
			
		||||
 				 const unsigned long *advertising)
 | 
			
		||||
 {
 | 
			
		||||
+	unsigned int pcs_ib_caps = 0;
 | 
			
		||||
+	unsigned int phy_ib_caps = 0;
 | 
			
		||||
 	unsigned int neg_mode, mode;
 | 
			
		||||
+	enum {
 | 
			
		||||
+		INBAND_CISCO_SGMII,
 | 
			
		||||
+		INBAND_BASEX,
 | 
			
		||||
+	} type;
 | 
			
		||||
 
 | 
			
		||||
 	mode = pl->req_link_an_mode;
 | 
			
		||||
 
 | 
			
		||||
+	pl->phy_ib_mode = 0;
 | 
			
		||||
+
 | 
			
		||||
 	switch (interface) {
 | 
			
		||||
 	case PHY_INTERFACE_MODE_SGMII:
 | 
			
		||||
 	case PHY_INTERFACE_MODE_QSGMII:
 | 
			
		||||
@@ -1185,10 +1194,7 @@ static void phylink_pcs_neg_mode(struct
 | 
			
		||||
 		 * inband communication. Note: there exist PHYs that run
 | 
			
		||||
 		 * with SGMII but do not send the inband data.
 | 
			
		||||
 		 */
 | 
			
		||||
-		if (!phylink_autoneg_inband(mode))
 | 
			
		||||
-			neg_mode = PHYLINK_PCS_NEG_OUTBAND;
 | 
			
		||||
-		else
 | 
			
		||||
-			neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
 | 
			
		||||
+		type = INBAND_CISCO_SGMII;
 | 
			
		||||
 		break;
 | 
			
		||||
 
 | 
			
		||||
 	case PHY_INTERFACE_MODE_1000BASEX:
 | 
			
		||||
@@ -1199,18 +1205,139 @@ static void phylink_pcs_neg_mode(struct
 | 
			
		||||
 		 * as well, but drivers may not support this, so may
 | 
			
		||||
 		 * need to override this.
 | 
			
		||||
 		 */
 | 
			
		||||
-		if (!phylink_autoneg_inband(mode))
 | 
			
		||||
+		type = INBAND_BASEX;
 | 
			
		||||
+		break;
 | 
			
		||||
+
 | 
			
		||||
+	default:
 | 
			
		||||
+		pl->pcs_neg_mode = PHYLINK_PCS_NEG_NONE;
 | 
			
		||||
+		pl->act_link_an_mode = mode;
 | 
			
		||||
+		return;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	if (pcs)
 | 
			
		||||
+		pcs_ib_caps = phylink_pcs_inband_caps(pcs, interface);
 | 
			
		||||
+
 | 
			
		||||
+	if (pl->phydev)
 | 
			
		||||
+		phy_ib_caps = phy_inband_caps(pl->phydev, interface);
 | 
			
		||||
+
 | 
			
		||||
+	phylink_dbg(pl, "interface %s inband modes: pcs=%02x phy=%02x\n",
 | 
			
		||||
+		    phy_modes(interface), pcs_ib_caps, phy_ib_caps);
 | 
			
		||||
+
 | 
			
		||||
+	if (!phylink_autoneg_inband(mode)) {
 | 
			
		||||
+		bool pcs_ib_only = false;
 | 
			
		||||
+		bool phy_ib_only = false;
 | 
			
		||||
+
 | 
			
		||||
+		if (pcs_ib_caps && pcs_ib_caps != LINK_INBAND_DISABLE) {
 | 
			
		||||
+			/* PCS supports reporting in-band capabilities, and
 | 
			
		||||
+			 * supports more than disable mode.
 | 
			
		||||
+			 */
 | 
			
		||||
+			if (pcs_ib_caps & LINK_INBAND_DISABLE)
 | 
			
		||||
+				neg_mode = PHYLINK_PCS_NEG_OUTBAND;
 | 
			
		||||
+			else if (pcs_ib_caps & LINK_INBAND_ENABLE)
 | 
			
		||||
+				pcs_ib_only = true;
 | 
			
		||||
+		}
 | 
			
		||||
+
 | 
			
		||||
+		if (phy_ib_caps && phy_ib_caps != LINK_INBAND_DISABLE) {
 | 
			
		||||
+			/* PHY supports in-band capabilities, and supports
 | 
			
		||||
+			 * more than disable mode.
 | 
			
		||||
+			 */
 | 
			
		||||
+			if (phy_ib_caps & LINK_INBAND_DISABLE)
 | 
			
		||||
+				pl->phy_ib_mode = LINK_INBAND_DISABLE;
 | 
			
		||||
+			else if (phy_ib_caps & LINK_INBAND_BYPASS)
 | 
			
		||||
+				pl->phy_ib_mode = LINK_INBAND_BYPASS;
 | 
			
		||||
+			else if (phy_ib_caps & LINK_INBAND_ENABLE)
 | 
			
		||||
+				phy_ib_only = true;
 | 
			
		||||
+		}
 | 
			
		||||
+
 | 
			
		||||
+		/* If either the PCS or PHY requires inband to be enabled,
 | 
			
		||||
+		 * this is an invalid configuration. Provide a diagnostic
 | 
			
		||||
+		 * message for this case, but don't try to force the issue.
 | 
			
		||||
+		 */
 | 
			
		||||
+		if (pcs_ib_only || phy_ib_only)
 | 
			
		||||
+			phylink_warn(pl,
 | 
			
		||||
+				     "firmware wants %s mode, but %s%s%s requires inband\n",
 | 
			
		||||
+				     phylink_an_mode_str(mode),
 | 
			
		||||
+				     pcs_ib_only ? "PCS" : "",
 | 
			
		||||
+				     pcs_ib_only && phy_ib_only ? " and " : "",
 | 
			
		||||
+				     phy_ib_only ? "PHY" : "");
 | 
			
		||||
+
 | 
			
		||||
+		neg_mode = PHYLINK_PCS_NEG_OUTBAND;
 | 
			
		||||
+	} else if (type == INBAND_CISCO_SGMII || pl->phydev) {
 | 
			
		||||
+		/* For SGMII modes which are designed to be used with PHYs, or
 | 
			
		||||
+		 * Base-X with a PHY, we try to use in-band mode where-ever
 | 
			
		||||
+		 * possible. However, there are some PHYs e.g. BCM84881 which
 | 
			
		||||
+		 * do not support in-band.
 | 
			
		||||
+		 */
 | 
			
		||||
+		const unsigned int inband_ok = LINK_INBAND_ENABLE |
 | 
			
		||||
+					       LINK_INBAND_BYPASS;
 | 
			
		||||
+		const unsigned int outband_ok = LINK_INBAND_DISABLE |
 | 
			
		||||
+						LINK_INBAND_BYPASS;
 | 
			
		||||
+		/* PCS	PHY
 | 
			
		||||
+		 * D E	D E
 | 
			
		||||
+		 * 0 0  0 0	no information			inband enabled
 | 
			
		||||
+		 * 1 0  0 0	pcs doesn't support		outband
 | 
			
		||||
+		 * 0 1  0 0	pcs required			inband enabled
 | 
			
		||||
+		 * 1 1  0 0	pcs optional			inband enabled
 | 
			
		||||
+		 * 0 0  1 0	phy doesn't support		outband
 | 
			
		||||
+		 * 1 0  1 0	pcs+phy doesn't support		outband
 | 
			
		||||
+		 * 0 1  1 0	pcs required, phy doesn't support, invalid
 | 
			
		||||
+		 * 1 1  1 0	pcs optional, phy doesn't support, outband
 | 
			
		||||
+		 * 0 0  0 1	phy required			inband enabled
 | 
			
		||||
+		 * 1 0  0 1	pcs doesn't support, phy required, invalid
 | 
			
		||||
+		 * 0 1  0 1	pcs+phy required		inband enabled
 | 
			
		||||
+		 * 1 1  0 1	pcs optional, phy required	inband enabled
 | 
			
		||||
+		 * 0 0  1 1	phy optional			inband enabled
 | 
			
		||||
+		 * 1 0  1 1	pcs doesn't support, phy optional, outband
 | 
			
		||||
+		 * 0 1  1 1	pcs required, phy optional	inband enabled
 | 
			
		||||
+		 * 1 1  1 1	pcs+phy optional		inband enabled
 | 
			
		||||
+		 */
 | 
			
		||||
+		if ((!pcs_ib_caps || pcs_ib_caps & inband_ok) &&
 | 
			
		||||
+		    (!phy_ib_caps || phy_ib_caps & inband_ok)) {
 | 
			
		||||
+			/* In-band supported or unknown at both ends. Enable
 | 
			
		||||
+			 * in-band mode with or without bypass at the PHY.
 | 
			
		||||
+			 */
 | 
			
		||||
+			if (phy_ib_caps & LINK_INBAND_ENABLE)
 | 
			
		||||
+				pl->phy_ib_mode = LINK_INBAND_ENABLE;
 | 
			
		||||
+			else if (phy_ib_caps & LINK_INBAND_BYPASS)
 | 
			
		||||
+				pl->phy_ib_mode = LINK_INBAND_BYPASS;
 | 
			
		||||
+
 | 
			
		||||
+			neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
 | 
			
		||||
+		} else if ((!pcs_ib_caps || pcs_ib_caps & outband_ok) &&
 | 
			
		||||
+			   (!phy_ib_caps || phy_ib_caps & outband_ok)) {
 | 
			
		||||
+			/* Either in-band not supported at at least one end.
 | 
			
		||||
+			 * In-band bypass at the other end is possible.
 | 
			
		||||
+			 */
 | 
			
		||||
+			if (phy_ib_caps & LINK_INBAND_DISABLE)
 | 
			
		||||
+				pl->phy_ib_mode = LINK_INBAND_DISABLE;
 | 
			
		||||
+			else if (phy_ib_caps & LINK_INBAND_BYPASS)
 | 
			
		||||
+				pl->phy_ib_mode = LINK_INBAND_BYPASS;
 | 
			
		||||
+
 | 
			
		||||
 			neg_mode = PHYLINK_PCS_NEG_OUTBAND;
 | 
			
		||||
+			if (pl->phydev)
 | 
			
		||||
+				mode = MLO_AN_PHY;
 | 
			
		||||
+		} else {
 | 
			
		||||
+			/* invalid */
 | 
			
		||||
+			phylink_warn(pl, "%s: incompatible in-band capabilities, trying in-band",
 | 
			
		||||
+				     phy_modes(interface));
 | 
			
		||||
+			neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
 | 
			
		||||
+		}
 | 
			
		||||
+	} else {
 | 
			
		||||
+		/* For Base-X without a PHY */
 | 
			
		||||
+		if (pcs_ib_caps == LINK_INBAND_DISABLE)
 | 
			
		||||
+			/* If the PCS doesn't support inband, then inband must
 | 
			
		||||
+			 * be disabled.
 | 
			
		||||
+			 */
 | 
			
		||||
+			neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED;
 | 
			
		||||
+		else if (pcs_ib_caps == LINK_INBAND_ENABLE)
 | 
			
		||||
+			/* If the PCS requires inband, then inband must always
 | 
			
		||||
+			 * be enabled.
 | 
			
		||||
+			 */
 | 
			
		||||
+			neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
 | 
			
		||||
 		else if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
 | 
			
		||||
 					   advertising))
 | 
			
		||||
 			neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
 | 
			
		||||
 		else
 | 
			
		||||
 			neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED;
 | 
			
		||||
-		break;
 | 
			
		||||
-
 | 
			
		||||
-	default:
 | 
			
		||||
-		neg_mode = PHYLINK_PCS_NEG_NONE;
 | 
			
		||||
-		break;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	pl->pcs_neg_mode = neg_mode;
 | 
			
		||||
@@ -1309,6 +1436,13 @@ static void phylink_major_config(struct
 | 
			
		||||
 				    ERR_PTR(err));
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
+	if (pl->phydev && pl->phy_ib_mode) {
 | 
			
		||||
+		err = phy_config_inband(pl->phydev, pl->phy_ib_mode);
 | 
			
		||||
+		if (err < 0)
 | 
			
		||||
+			phylink_err(pl, "phy_config_inband: %pe\n",
 | 
			
		||||
+				    ERR_PTR(err));
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
 	if (pl->sfp_bus) {
 | 
			
		||||
 		rate_kbd = phylink_interface_signal_rate(state->interface);
 | 
			
		||||
 		if (rate_kbd)
 | 
			
		||||
@ -0,0 +1,110 @@
 | 
			
		||||
From 77ac9a8b2536e0eaca6c6f21070068458bf55981 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:31:48 +0000
 | 
			
		||||
Subject: [PATCH 13/13] net: phylink: remove phylink_phy_no_inband()
 | 
			
		||||
 | 
			
		||||
Remove phylink_phy_no_inband() now that we are handling the lack of
 | 
			
		||||
inband negotiation by querying the capabilities of the PHY and PCS,
 | 
			
		||||
and the BCM84881 PHY driver provides us the information necessary to
 | 
			
		||||
make the decision.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUsO-006IUt-KN@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phylink.c | 27 ++++++---------------------
 | 
			
		||||
 1 file changed, 6 insertions(+), 21 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -3394,10 +3394,11 @@ static phy_interface_t phylink_choose_sf
 | 
			
		||||
 	return interface;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static void phylink_sfp_set_config(struct phylink *pl, u8 mode,
 | 
			
		||||
+static void phylink_sfp_set_config(struct phylink *pl,
 | 
			
		||||
 				   unsigned long *supported,
 | 
			
		||||
 				   struct phylink_link_state *state)
 | 
			
		||||
 {
 | 
			
		||||
+	u8 mode = MLO_AN_INBAND;
 | 
			
		||||
 	bool changed = false;
 | 
			
		||||
 
 | 
			
		||||
 	phylink_dbg(pl, "requesting link mode %s/%s with support %*pb\n",
 | 
			
		||||
@@ -3431,8 +3432,7 @@ static void phylink_sfp_set_config(struc
 | 
			
		||||
 		phylink_mac_initial_config(pl, false);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static int phylink_sfp_config_phy(struct phylink *pl, u8 mode,
 | 
			
		||||
-				  struct phy_device *phy)
 | 
			
		||||
+static int phylink_sfp_config_phy(struct phylink *pl, struct phy_device *phy)
 | 
			
		||||
 {
 | 
			
		||||
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(support1);
 | 
			
		||||
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(support);
 | 
			
		||||
@@ -3472,7 +3472,7 @@ static int phylink_sfp_config_phy(struct
 | 
			
		||||
 	if (ret) {
 | 
			
		||||
 		phylink_err(pl,
 | 
			
		||||
 			    "validation of %s/%s with support %*pb failed: %pe\n",
 | 
			
		||||
-			    phylink_an_mode_str(mode),
 | 
			
		||||
+			    phylink_an_mode_str(pl->req_link_an_mode),
 | 
			
		||||
 			    phy_modes(config.interface),
 | 
			
		||||
 			    __ETHTOOL_LINK_MODE_MASK_NBITS, support,
 | 
			
		||||
 			    ERR_PTR(ret));
 | 
			
		||||
@@ -3481,7 +3481,7 @@ static int phylink_sfp_config_phy(struct
 | 
			
		||||
 
 | 
			
		||||
 	pl->link_port = pl->sfp_port;
 | 
			
		||||
 
 | 
			
		||||
-	phylink_sfp_set_config(pl, mode, support, &config);
 | 
			
		||||
+	phylink_sfp_set_config(pl, support, &config);
 | 
			
		||||
 
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
@@ -3556,7 +3556,7 @@ static int phylink_sfp_config_optical(st
 | 
			
		||||
 
 | 
			
		||||
 	pl->link_port = pl->sfp_port;
 | 
			
		||||
 
 | 
			
		||||
-	phylink_sfp_set_config(pl, MLO_AN_INBAND, pl->sfp_support, &config);
 | 
			
		||||
+	phylink_sfp_set_config(pl, pl->sfp_support, &config);
 | 
			
		||||
 
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
@@ -3627,20 +3627,10 @@ static void phylink_sfp_link_up(void *up
 | 
			
		||||
 	phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_LINK);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-/* The Broadcom BCM84881 in the Methode DM7052 is unable to provide a SGMII
 | 
			
		||||
- * or 802.3z control word, so inband will not work.
 | 
			
		||||
- */
 | 
			
		||||
-static bool phylink_phy_no_inband(struct phy_device *phy)
 | 
			
		||||
-{
 | 
			
		||||
-	return phy->is_c45 && phy_id_compare(phy->c45_ids.device_ids[1],
 | 
			
		||||
-					     0xae025150, 0xfffffff0);
 | 
			
		||||
-}
 | 
			
		||||
-
 | 
			
		||||
 static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy)
 | 
			
		||||
 {
 | 
			
		||||
 	struct phylink *pl = upstream;
 | 
			
		||||
 	phy_interface_t interface;
 | 
			
		||||
-	u8 mode;
 | 
			
		||||
 	int ret;
 | 
			
		||||
 
 | 
			
		||||
 	/*
 | 
			
		||||
@@ -3652,17 +3642,12 @@ static int phylink_sfp_connect_phy(void
 | 
			
		||||
 	 */
 | 
			
		||||
 	phy_support_asym_pause(phy);
 | 
			
		||||
 
 | 
			
		||||
-	if (phylink_phy_no_inband(phy))
 | 
			
		||||
-		mode = MLO_AN_PHY;
 | 
			
		||||
-	else
 | 
			
		||||
-		mode = MLO_AN_INBAND;
 | 
			
		||||
-
 | 
			
		||||
 	/* Set the PHY's host supported interfaces */
 | 
			
		||||
 	phy_interface_and(phy->host_interfaces, phylink_sfp_interfaces,
 | 
			
		||||
 			  pl->config->supported_interfaces);
 | 
			
		||||
 
 | 
			
		||||
 	/* Do the initial configuration */
 | 
			
		||||
-	ret = phylink_sfp_config_phy(pl, mode, phy);
 | 
			
		||||
+	ret = phylink_sfp_config_phy(pl, phy);
 | 
			
		||||
 	if (ret < 0)
 | 
			
		||||
 		return ret;
 | 
			
		||||
 
 | 
			
		||||
@ -0,0 +1,53 @@
 | 
			
		||||
From 6561f0e547be221f411fda5eddfcc5bd8bb058a5 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Thu, 5 Dec 2024 09:42:24 +0000
 | 
			
		||||
Subject: [PATCH 1/3] net: pcs: pcs-lynx: implement pcs_inband_caps() method
 | 
			
		||||
 | 
			
		||||
Report the PCS in-band capabilities to phylink for the Lynx PCS.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tJ8NM-006L5J-AH@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/pcs/pcs-lynx.c | 22 ++++++++++++++++++++++
 | 
			
		||||
 1 file changed, 22 insertions(+)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/pcs/pcs-lynx.c
 | 
			
		||||
+++ b/drivers/net/pcs/pcs-lynx.c
 | 
			
		||||
@@ -35,6 +35,27 @@ enum sgmii_speed {
 | 
			
		||||
 #define phylink_pcs_to_lynx(pl_pcs) container_of((pl_pcs), struct lynx_pcs, pcs)
 | 
			
		||||
 #define lynx_to_phylink_pcs(lynx) (&(lynx)->pcs)
 | 
			
		||||
 
 | 
			
		||||
+static unsigned int lynx_pcs_inband_caps(struct phylink_pcs *pcs,
 | 
			
		||||
+					 phy_interface_t interface)
 | 
			
		||||
+{
 | 
			
		||||
+	switch (interface) {
 | 
			
		||||
+	case PHY_INTERFACE_MODE_1000BASEX:
 | 
			
		||||
+	case PHY_INTERFACE_MODE_SGMII:
 | 
			
		||||
+	case PHY_INTERFACE_MODE_QSGMII:
 | 
			
		||||
+		return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
 | 
			
		||||
+
 | 
			
		||||
+	case PHY_INTERFACE_MODE_10GBASER:
 | 
			
		||||
+	case PHY_INTERFACE_MODE_2500BASEX:
 | 
			
		||||
+		return LINK_INBAND_DISABLE;
 | 
			
		||||
+
 | 
			
		||||
+	case PHY_INTERFACE_MODE_USXGMII:
 | 
			
		||||
+		return LINK_INBAND_ENABLE;
 | 
			
		||||
+
 | 
			
		||||
+	default:
 | 
			
		||||
+		return 0;
 | 
			
		||||
+	}
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static void lynx_pcs_get_state_usxgmii(struct mdio_device *pcs,
 | 
			
		||||
 				       struct phylink_link_state *state)
 | 
			
		||||
 {
 | 
			
		||||
@@ -306,6 +327,7 @@ static void lynx_pcs_link_up(struct phyl
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static const struct phylink_pcs_ops lynx_pcs_phylink_ops = {
 | 
			
		||||
+	.pcs_inband_caps = lynx_pcs_inband_caps,
 | 
			
		||||
 	.pcs_get_state = lynx_pcs_get_state,
 | 
			
		||||
 	.pcs_config = lynx_pcs_config,
 | 
			
		||||
 	.pcs_an_restart = lynx_pcs_an_restart,
 | 
			
		||||
@ -0,0 +1,47 @@
 | 
			
		||||
From 520d29bdda86915b3caf8c72825a574bff212553 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Thu, 5 Dec 2024 09:42:29 +0000
 | 
			
		||||
Subject: [PATCH 2/3] net: pcs: pcs-mtk-lynxi: implement pcs_inband_caps()
 | 
			
		||||
 method
 | 
			
		||||
 | 
			
		||||
Report the PCS in-band capabilities to phylink for the LynxI PCS.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tJ8NR-006L5P-E3@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/pcs/pcs-mtk-lynxi.c | 16 ++++++++++++++++
 | 
			
		||||
 1 file changed, 16 insertions(+)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/pcs/pcs-mtk-lynxi.c
 | 
			
		||||
+++ b/drivers/net/pcs/pcs-mtk-lynxi.c
 | 
			
		||||
@@ -88,6 +88,21 @@ static struct mtk_pcs_lynxi *pcs_to_mtk_
 | 
			
		||||
 	return container_of(pcs, struct mtk_pcs_lynxi, pcs);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static unsigned int mtk_pcs_lynxi_inband_caps(struct phylink_pcs *pcs,
 | 
			
		||||
+					      phy_interface_t interface)
 | 
			
		||||
+{
 | 
			
		||||
+	switch (interface) {
 | 
			
		||||
+	case PHY_INTERFACE_MODE_1000BASEX:
 | 
			
		||||
+	case PHY_INTERFACE_MODE_2500BASEX:
 | 
			
		||||
+	case PHY_INTERFACE_MODE_SGMII:
 | 
			
		||||
+	case PHY_INTERFACE_MODE_QSGMII:
 | 
			
		||||
+		return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
 | 
			
		||||
+
 | 
			
		||||
+	default:
 | 
			
		||||
+		return 0;
 | 
			
		||||
+	}
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static void mtk_pcs_lynxi_get_state(struct phylink_pcs *pcs,
 | 
			
		||||
 				    struct phylink_link_state *state)
 | 
			
		||||
 {
 | 
			
		||||
@@ -241,6 +256,7 @@ static void mtk_pcs_lynxi_disable(struct
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static const struct phylink_pcs_ops mtk_pcs_lynxi_ops = {
 | 
			
		||||
+	.pcs_inband_caps = mtk_pcs_lynxi_inband_caps,
 | 
			
		||||
 	.pcs_get_state = mtk_pcs_lynxi_get_state,
 | 
			
		||||
 	.pcs_config = mtk_pcs_lynxi_config,
 | 
			
		||||
 	.pcs_an_restart = mtk_pcs_lynxi_restart_an,
 | 
			
		||||
@ -0,0 +1,58 @@
 | 
			
		||||
From 484d0170d6c6bbb5213d037664e9a551f793bacd Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Thu, 5 Dec 2024 09:42:34 +0000
 | 
			
		||||
Subject: [PATCH 3/3] net: pcs: xpcs: implement pcs_inband_caps() method
 | 
			
		||||
 | 
			
		||||
Report the PCS inband capabilities to phylink for XPCS.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tJ8NW-006L5V-I9@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/pcs/pcs-xpcs.c | 28 ++++++++++++++++++++++++++++
 | 
			
		||||
 1 file changed, 28 insertions(+)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/pcs/pcs-xpcs.c
 | 
			
		||||
+++ b/drivers/net/pcs/pcs-xpcs.c
 | 
			
		||||
@@ -608,6 +608,33 @@ static int xpcs_validate(struct phylink_
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static unsigned int xpcs_inband_caps(struct phylink_pcs *pcs,
 | 
			
		||||
+				     phy_interface_t interface)
 | 
			
		||||
+{
 | 
			
		||||
+	struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
 | 
			
		||||
+	const struct dw_xpcs_compat *compat;
 | 
			
		||||
+
 | 
			
		||||
+	compat = xpcs_find_compat(xpcs->desc, interface);
 | 
			
		||||
+	if (!compat)
 | 
			
		||||
+		return 0;
 | 
			
		||||
+
 | 
			
		||||
+	switch (compat->an_mode) {
 | 
			
		||||
+	case DW_AN_C73:
 | 
			
		||||
+		return LINK_INBAND_ENABLE;
 | 
			
		||||
+
 | 
			
		||||
+	case DW_AN_C37_SGMII:
 | 
			
		||||
+	case DW_AN_C37_1000BASEX:
 | 
			
		||||
+		return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
 | 
			
		||||
+
 | 
			
		||||
+	case DW_10GBASER:
 | 
			
		||||
+	case DW_2500BASEX:
 | 
			
		||||
+		return LINK_INBAND_DISABLE;
 | 
			
		||||
+
 | 
			
		||||
+	default:
 | 
			
		||||
+		return 0;
 | 
			
		||||
+	}
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 void xpcs_get_interfaces(struct dw_xpcs *xpcs, unsigned long *interfaces)
 | 
			
		||||
 {
 | 
			
		||||
 	int i, j;
 | 
			
		||||
@@ -1365,6 +1392,7 @@ static const struct dw_xpcs_desc xpcs_de
 | 
			
		||||
 
 | 
			
		||||
 static const struct phylink_pcs_ops xpcs_phylink_ops = {
 | 
			
		||||
 	.pcs_validate = xpcs_validate,
 | 
			
		||||
+	.pcs_inband_caps = xpcs_inband_caps,
 | 
			
		||||
 	.pcs_config = xpcs_config,
 | 
			
		||||
 	.pcs_get_state = xpcs_get_state,
 | 
			
		||||
 	.pcs_an_restart = xpcs_an_restart,
 | 
			
		||||
@ -194,7 +194,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
 	{ PHY_ID_BCM72165, 0xfffffff0, },
 | 
			
		||||
--- a/drivers/net/phy/bcm84881.c
 | 
			
		||||
+++ b/drivers/net/phy/bcm84881.c
 | 
			
		||||
@@ -252,7 +252,7 @@ static struct phy_driver bcm84881_driver
 | 
			
		||||
@@ -262,7 +262,7 @@ static struct phy_driver bcm84881_driver
 | 
			
		||||
 module_phy_driver(bcm84881_drivers);
 | 
			
		||||
 
 | 
			
		||||
 /* FIXME: module auto-loading for Clause 45 PHYs seems non-functional */
 | 
			
		||||
@ -403,7 +403,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
 };
 | 
			
		||||
--- a/drivers/net/phy/marvell.c
 | 
			
		||||
+++ b/drivers/net/phy/marvell.c
 | 
			
		||||
@@ -4133,7 +4133,7 @@ static struct phy_driver marvell_drivers
 | 
			
		||||
@@ -4181,7 +4181,7 @@ static struct phy_driver marvell_drivers
 | 
			
		||||
 
 | 
			
		||||
 module_phy_driver(marvell_drivers);
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
@ -39,7 +39,7 @@ Signed-off-by: Paolo Abeni <pabeni@redhat.com>
 | 
			
		||||
 		if (!phydev->drv->led_polarity_set)
 | 
			
		||||
--- a/include/linux/phy.h
 | 
			
		||||
+++ b/include/linux/phy.h
 | 
			
		||||
@@ -874,8 +874,9 @@ struct phy_plca_status {
 | 
			
		||||
@@ -892,8 +892,9 @@ struct phy_plca_status {
 | 
			
		||||
 
 | 
			
		||||
 /* Modes for PHY LED configuration */
 | 
			
		||||
 enum phy_led_modes {
 | 
			
		||||
 | 
			
		||||
@ -281,7 +281,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
 }
 | 
			
		||||
--- a/include/linux/phy.h
 | 
			
		||||
+++ b/include/linux/phy.h
 | 
			
		||||
@@ -1004,7 +1004,8 @@ struct phy_driver {
 | 
			
		||||
@@ -1035,7 +1035,8 @@ struct phy_driver {
 | 
			
		||||
 	 * driver for the given phydev.	 If NULL, matching is based on
 | 
			
		||||
 	 * phy_id and phy_id_mask.
 | 
			
		||||
 	 */
 | 
			
		||||
 | 
			
		||||
@ -97,7 +97,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
 static ssize_t
 | 
			
		||||
--- a/include/linux/phy.h
 | 
			
		||||
+++ b/include/linux/phy.h
 | 
			
		||||
@@ -1906,6 +1906,9 @@ char *phy_attached_info_irq(struct phy_d
 | 
			
		||||
@@ -1940,6 +1940,9 @@ char *phy_attached_info_irq(struct phy_d
 | 
			
		||||
 	__malloc;
 | 
			
		||||
 void phy_attached_info(struct phy_device *phydev);
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,41 @@
 | 
			
		||||
From 8cc5f4cb94c0b1c7c1ba8013c14fd02ffb1a25f3 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Fri, 8 Nov 2024 16:01:44 +0000
 | 
			
		||||
Subject: [PATCH 1/5] net: phylink: move manual flow control setting
 | 
			
		||||
 | 
			
		||||
Move the handling of manual flow control configuration to a common
 | 
			
		||||
location during resolve. We currently evaluate this for all but
 | 
			
		||||
fixed links.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1t9RQe-002Feh-T1@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phylink.c | 5 +++--
 | 
			
		||||
 1 file changed, 3 insertions(+), 2 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -1433,7 +1433,6 @@ static void phylink_resolve(struct work_
 | 
			
		||||
 		switch (pl->cur_link_an_mode) {
 | 
			
		||||
 		case MLO_AN_PHY:
 | 
			
		||||
 			link_state = pl->phy_state;
 | 
			
		||||
-			phylink_apply_manual_flow(pl, &link_state);
 | 
			
		||||
 			mac_config = link_state.link;
 | 
			
		||||
 			break;
 | 
			
		||||
 
 | 
			
		||||
@@ -1494,11 +1493,13 @@ static void phylink_resolve(struct work_
 | 
			
		||||
 				link_state.pause = pl->phy_state.pause;
 | 
			
		||||
 				mac_config = true;
 | 
			
		||||
 			}
 | 
			
		||||
-			phylink_apply_manual_flow(pl, &link_state);
 | 
			
		||||
 			break;
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
+	if (pl->cur_link_an_mode != MLO_AN_FIXED)
 | 
			
		||||
+		phylink_apply_manual_flow(pl, &link_state);
 | 
			
		||||
+
 | 
			
		||||
 	if (mac_config) {
 | 
			
		||||
 		if (link_state.interface != pl->link_config.interface) {
 | 
			
		||||
 			/* The interface has changed, force the link down and
 | 
			
		||||
@ -0,0 +1,42 @@
 | 
			
		||||
From 92abfcb4ced482afbe65d18980e6734fe1e62a34 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Fri, 8 Nov 2024 16:01:50 +0000
 | 
			
		||||
Subject: [PATCH 2/5] net: phylink: move MLO_AN_FIXED resolve handling to if()
 | 
			
		||||
 statement
 | 
			
		||||
 | 
			
		||||
The switch() statement doesn't sit very well with the preceeding if()
 | 
			
		||||
statements, and results in excessive indentation that spoils code
 | 
			
		||||
readability. Begin cleaning this up by converting the MLO_AN_FIXED case
 | 
			
		||||
to an if() statement.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1t9RQk-002Fen-1A@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phylink.c | 8 +++-----
 | 
			
		||||
 1 file changed, 3 insertions(+), 5 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -1429,6 +1429,9 @@ static void phylink_resolve(struct work_
 | 
			
		||||
 	} else if (pl->mac_link_dropped) {
 | 
			
		||||
 		link_state.link = false;
 | 
			
		||||
 		retrigger = true;
 | 
			
		||||
+	} else if (pl->cur_link_an_mode == MLO_AN_FIXED) {
 | 
			
		||||
+		phylink_get_fixed_state(pl, &link_state);
 | 
			
		||||
+		mac_config = link_state.link;
 | 
			
		||||
 	} else {
 | 
			
		||||
 		switch (pl->cur_link_an_mode) {
 | 
			
		||||
 		case MLO_AN_PHY:
 | 
			
		||||
@@ -1436,11 +1439,6 @@ static void phylink_resolve(struct work_
 | 
			
		||||
 			mac_config = link_state.link;
 | 
			
		||||
 			break;
 | 
			
		||||
 
 | 
			
		||||
-		case MLO_AN_FIXED:
 | 
			
		||||
-			phylink_get_fixed_state(pl, &link_state);
 | 
			
		||||
-			mac_config = link_state.link;
 | 
			
		||||
-			break;
 | 
			
		||||
-
 | 
			
		||||
 		case MLO_AN_INBAND:
 | 
			
		||||
 			phylink_mac_pcs_get_state(pl, &link_state);
 | 
			
		||||
 
 | 
			
		||||
@ -0,0 +1,37 @@
 | 
			
		||||
From f0f46c2a3d8ea9d1427298c8103a777d9e616c29 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Fri, 8 Nov 2024 16:01:55 +0000
 | 
			
		||||
Subject: [PATCH 3/5] net: phylink: move MLO_AN_PHY resolve handling to if()
 | 
			
		||||
 statement
 | 
			
		||||
 | 
			
		||||
The switch() statement doesn't sit very well with the preceeding if()
 | 
			
		||||
statements, and results in excessive indentation that spoils code
 | 
			
		||||
readability. Continue cleaning this up by converting the MLO_AN_PHY
 | 
			
		||||
case to use an if() statmeent.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1t9RQp-002Fet-5W@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phylink.c | 8 +++-----
 | 
			
		||||
 1 file changed, 3 insertions(+), 5 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -1432,13 +1432,11 @@ static void phylink_resolve(struct work_
 | 
			
		||||
 	} else if (pl->cur_link_an_mode == MLO_AN_FIXED) {
 | 
			
		||||
 		phylink_get_fixed_state(pl, &link_state);
 | 
			
		||||
 		mac_config = link_state.link;
 | 
			
		||||
+	} else if (pl->cur_link_an_mode == MLO_AN_PHY) {
 | 
			
		||||
+		link_state = pl->phy_state;
 | 
			
		||||
+		mac_config = link_state.link;
 | 
			
		||||
 	} else {
 | 
			
		||||
 		switch (pl->cur_link_an_mode) {
 | 
			
		||||
-		case MLO_AN_PHY:
 | 
			
		||||
-			link_state = pl->phy_state;
 | 
			
		||||
-			mac_config = link_state.link;
 | 
			
		||||
-			break;
 | 
			
		||||
-
 | 
			
		||||
 		case MLO_AN_INBAND:
 | 
			
		||||
 			phylink_mac_pcs_get_state(pl, &link_state);
 | 
			
		||||
 
 | 
			
		||||
@ -0,0 +1,127 @@
 | 
			
		||||
From d1a16dbbd84e02d2a6dcfcb8d5c4b8b2c0289f00 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Fri, 8 Nov 2024 16:02:00 +0000
 | 
			
		||||
Subject: [PATCH 4/5] net: phylink: remove switch() statement in resolve
 | 
			
		||||
 handling
 | 
			
		||||
 | 
			
		||||
The switch() statement doesn't sit very well with the preceeding if()
 | 
			
		||||
statements, so let's just convert everything to if()s. As a result of
 | 
			
		||||
the two preceding commits, there is now only one case in the switch()
 | 
			
		||||
statement. Remove the switch statement and reduce the code indentation.
 | 
			
		||||
Code reformatting will be in the following commit.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1t9RQu-002Fez-AA@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phylink.c | 94 +++++++++++++++++++--------------------
 | 
			
		||||
 1 file changed, 45 insertions(+), 49 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -1436,60 +1436,56 @@ static void phylink_resolve(struct work_
 | 
			
		||||
 		link_state = pl->phy_state;
 | 
			
		||||
 		mac_config = link_state.link;
 | 
			
		||||
 	} else {
 | 
			
		||||
-		switch (pl->cur_link_an_mode) {
 | 
			
		||||
-		case MLO_AN_INBAND:
 | 
			
		||||
-			phylink_mac_pcs_get_state(pl, &link_state);
 | 
			
		||||
-
 | 
			
		||||
-			/* The PCS may have a latching link-fail indicator.
 | 
			
		||||
-			 * If the link was up, bring the link down and
 | 
			
		||||
-			 * re-trigger the resolve. Otherwise, re-read the
 | 
			
		||||
-			 * PCS state to get the current status of the link.
 | 
			
		||||
+		phylink_mac_pcs_get_state(pl, &link_state);
 | 
			
		||||
+
 | 
			
		||||
+		/* The PCS may have a latching link-fail indicator.
 | 
			
		||||
+		 * If the link was up, bring the link down and
 | 
			
		||||
+		 * re-trigger the resolve. Otherwise, re-read the
 | 
			
		||||
+		 * PCS state to get the current status of the link.
 | 
			
		||||
+		 */
 | 
			
		||||
+		if (!link_state.link) {
 | 
			
		||||
+			if (cur_link_state)
 | 
			
		||||
+				retrigger = true;
 | 
			
		||||
+			else
 | 
			
		||||
+				phylink_mac_pcs_get_state(pl,
 | 
			
		||||
+							  &link_state);
 | 
			
		||||
+		}
 | 
			
		||||
+
 | 
			
		||||
+		/* If we have a phy, the "up" state is the union of
 | 
			
		||||
+		 * both the PHY and the MAC
 | 
			
		||||
+		 */
 | 
			
		||||
+		if (pl->phydev)
 | 
			
		||||
+			link_state.link &= pl->phy_state.link;
 | 
			
		||||
+
 | 
			
		||||
+		/* Only update if the PHY link is up */
 | 
			
		||||
+		if (pl->phydev && pl->phy_state.link) {
 | 
			
		||||
+			/* If the interface has changed, force a
 | 
			
		||||
+			 * link down event if the link isn't already
 | 
			
		||||
+			 * down, and re-resolve.
 | 
			
		||||
 			 */
 | 
			
		||||
-			if (!link_state.link) {
 | 
			
		||||
-				if (cur_link_state)
 | 
			
		||||
-					retrigger = true;
 | 
			
		||||
-				else
 | 
			
		||||
-					phylink_mac_pcs_get_state(pl,
 | 
			
		||||
-								  &link_state);
 | 
			
		||||
+			if (link_state.interface !=
 | 
			
		||||
+			    pl->phy_state.interface) {
 | 
			
		||||
+				retrigger = true;
 | 
			
		||||
+				link_state.link = false;
 | 
			
		||||
 			}
 | 
			
		||||
+			link_state.interface = pl->phy_state.interface;
 | 
			
		||||
 
 | 
			
		||||
-			/* If we have a phy, the "up" state is the union of
 | 
			
		||||
-			 * both the PHY and the MAC
 | 
			
		||||
+			/* If we are doing rate matching, then the
 | 
			
		||||
+			 * link speed/duplex comes from the PHY
 | 
			
		||||
 			 */
 | 
			
		||||
-			if (pl->phydev)
 | 
			
		||||
-				link_state.link &= pl->phy_state.link;
 | 
			
		||||
-
 | 
			
		||||
-			/* Only update if the PHY link is up */
 | 
			
		||||
-			if (pl->phydev && pl->phy_state.link) {
 | 
			
		||||
-				/* If the interface has changed, force a
 | 
			
		||||
-				 * link down event if the link isn't already
 | 
			
		||||
-				 * down, and re-resolve.
 | 
			
		||||
-				 */
 | 
			
		||||
-				if (link_state.interface !=
 | 
			
		||||
-				    pl->phy_state.interface) {
 | 
			
		||||
-					retrigger = true;
 | 
			
		||||
-					link_state.link = false;
 | 
			
		||||
-				}
 | 
			
		||||
-				link_state.interface = pl->phy_state.interface;
 | 
			
		||||
-
 | 
			
		||||
-				/* If we are doing rate matching, then the
 | 
			
		||||
-				 * link speed/duplex comes from the PHY
 | 
			
		||||
-				 */
 | 
			
		||||
-				if (pl->phy_state.rate_matching) {
 | 
			
		||||
-					link_state.rate_matching =
 | 
			
		||||
-						pl->phy_state.rate_matching;
 | 
			
		||||
-					link_state.speed = pl->phy_state.speed;
 | 
			
		||||
-					link_state.duplex =
 | 
			
		||||
-						pl->phy_state.duplex;
 | 
			
		||||
-				}
 | 
			
		||||
-
 | 
			
		||||
-				/* If we have a PHY, we need to update with
 | 
			
		||||
-				 * the PHY flow control bits.
 | 
			
		||||
-				 */
 | 
			
		||||
-				link_state.pause = pl->phy_state.pause;
 | 
			
		||||
-				mac_config = true;
 | 
			
		||||
+			if (pl->phy_state.rate_matching) {
 | 
			
		||||
+				link_state.rate_matching =
 | 
			
		||||
+					pl->phy_state.rate_matching;
 | 
			
		||||
+				link_state.speed = pl->phy_state.speed;
 | 
			
		||||
+				link_state.duplex =
 | 
			
		||||
+					pl->phy_state.duplex;
 | 
			
		||||
 			}
 | 
			
		||||
-			break;
 | 
			
		||||
+
 | 
			
		||||
+			/* If we have a PHY, we need to update with
 | 
			
		||||
+			 * the PHY flow control bits.
 | 
			
		||||
+			 */
 | 
			
		||||
+			link_state.pause = pl->phy_state.pause;
 | 
			
		||||
+			mac_config = true;
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
@ -0,0 +1,85 @@
 | 
			
		||||
From bc08ce37d99a3992e975a0f397503cb23404f25a Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Fri, 8 Nov 2024 16:02:05 +0000
 | 
			
		||||
Subject: [PATCH 5/5] net: phylink: clean up phylink_resolve()
 | 
			
		||||
 | 
			
		||||
Now that we have reduced the indentation level, clean up the code
 | 
			
		||||
formatting.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1t9RQz-002Ff5-EA@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phylink.c | 35 ++++++++++++++++-------------------
 | 
			
		||||
 1 file changed, 16 insertions(+), 19 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -1438,51 +1438,48 @@ static void phylink_resolve(struct work_
 | 
			
		||||
 	} else {
 | 
			
		||||
 		phylink_mac_pcs_get_state(pl, &link_state);
 | 
			
		||||
 
 | 
			
		||||
-		/* The PCS may have a latching link-fail indicator.
 | 
			
		||||
-		 * If the link was up, bring the link down and
 | 
			
		||||
-		 * re-trigger the resolve. Otherwise, re-read the
 | 
			
		||||
-		 * PCS state to get the current status of the link.
 | 
			
		||||
+		/* The PCS may have a latching link-fail indicator. If the link
 | 
			
		||||
+		 * was up, bring the link down and re-trigger the resolve.
 | 
			
		||||
+		 * Otherwise, re-read the PCS state to get the current status
 | 
			
		||||
+		 * of the link.
 | 
			
		||||
 		 */
 | 
			
		||||
 		if (!link_state.link) {
 | 
			
		||||
 			if (cur_link_state)
 | 
			
		||||
 				retrigger = true;
 | 
			
		||||
 			else
 | 
			
		||||
-				phylink_mac_pcs_get_state(pl,
 | 
			
		||||
-							  &link_state);
 | 
			
		||||
+				phylink_mac_pcs_get_state(pl, &link_state);
 | 
			
		||||
 		}
 | 
			
		||||
 
 | 
			
		||||
-		/* If we have a phy, the "up" state is the union of
 | 
			
		||||
-		 * both the PHY and the MAC
 | 
			
		||||
+		/* If we have a phy, the "up" state is the union of both the
 | 
			
		||||
+		 * PHY and the MAC
 | 
			
		||||
 		 */
 | 
			
		||||
 		if (pl->phydev)
 | 
			
		||||
 			link_state.link &= pl->phy_state.link;
 | 
			
		||||
 
 | 
			
		||||
 		/* Only update if the PHY link is up */
 | 
			
		||||
 		if (pl->phydev && pl->phy_state.link) {
 | 
			
		||||
-			/* If the interface has changed, force a
 | 
			
		||||
-			 * link down event if the link isn't already
 | 
			
		||||
-			 * down, and re-resolve.
 | 
			
		||||
+			/* If the interface has changed, force a link down
 | 
			
		||||
+			 * event if the link isn't already down, and re-resolve.
 | 
			
		||||
 			 */
 | 
			
		||||
-			if (link_state.interface !=
 | 
			
		||||
-			    pl->phy_state.interface) {
 | 
			
		||||
+			if (link_state.interface != pl->phy_state.interface) {
 | 
			
		||||
 				retrigger = true;
 | 
			
		||||
 				link_state.link = false;
 | 
			
		||||
 			}
 | 
			
		||||
+
 | 
			
		||||
 			link_state.interface = pl->phy_state.interface;
 | 
			
		||||
 
 | 
			
		||||
-			/* If we are doing rate matching, then the
 | 
			
		||||
-			 * link speed/duplex comes from the PHY
 | 
			
		||||
+			/* If we are doing rate matching, then the link
 | 
			
		||||
+			 * speed/duplex comes from the PHY
 | 
			
		||||
 			 */
 | 
			
		||||
 			if (pl->phy_state.rate_matching) {
 | 
			
		||||
 				link_state.rate_matching =
 | 
			
		||||
 					pl->phy_state.rate_matching;
 | 
			
		||||
 				link_state.speed = pl->phy_state.speed;
 | 
			
		||||
-				link_state.duplex =
 | 
			
		||||
-					pl->phy_state.duplex;
 | 
			
		||||
+				link_state.duplex = pl->phy_state.duplex;
 | 
			
		||||
 			}
 | 
			
		||||
 
 | 
			
		||||
-			/* If we have a PHY, we need to update with
 | 
			
		||||
-			 * the PHY flow control bits.
 | 
			
		||||
+			/* If we have a PHY, we need to update with the PHY
 | 
			
		||||
+			 * flow control bits.
 | 
			
		||||
 			 */
 | 
			
		||||
 			link_state.pause = pl->phy_state.pause;
 | 
			
		||||
 			mac_config = true;
 | 
			
		||||
@ -0,0 +1,166 @@
 | 
			
		||||
From 5e5401d6612ef599ad45785b941eebda7effc90f Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Thu, 4 Jan 2024 09:47:36 +0000
 | 
			
		||||
Subject: [PATCH] net: phylink: move phylink_pcs_neg_mode() into phylink.c
 | 
			
		||||
 | 
			
		||||
Move phylink_pcs_neg_mode() from the header file into the .c file since
 | 
			
		||||
nothing should be using it.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: David S. Miller <davem@davemloft.net>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phylink.c | 66 +++++++++++++++++++++++++++++++++++++++
 | 
			
		||||
 include/linux/phylink.h   | 66 ---------------------------------------
 | 
			
		||||
 2 files changed, 66 insertions(+), 66 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -1116,6 +1116,72 @@ static void phylink_pcs_an_restart(struc
 | 
			
		||||
 		pl->pcs->ops->pcs_an_restart(pl->pcs);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+/**
 | 
			
		||||
+ * phylink_pcs_neg_mode() - helper to determine PCS inband mode
 | 
			
		||||
+ * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND.
 | 
			
		||||
+ * @interface: interface mode to be used
 | 
			
		||||
+ * @advertising: adertisement ethtool link mode mask
 | 
			
		||||
+ *
 | 
			
		||||
+ * Determines the negotiation mode to be used by the PCS, and returns
 | 
			
		||||
+ * one of:
 | 
			
		||||
+ *
 | 
			
		||||
+ * - %PHYLINK_PCS_NEG_NONE: interface mode does not support inband
 | 
			
		||||
+ * - %PHYLINK_PCS_NEG_OUTBAND: an out of band mode (e.g. reading the PHY)
 | 
			
		||||
+ *   will be used.
 | 
			
		||||
+ * - %PHYLINK_PCS_NEG_INBAND_DISABLED: inband mode selected but autoneg
 | 
			
		||||
+ *   disabled
 | 
			
		||||
+ * - %PHYLINK_PCS_NEG_INBAND_ENABLED: inband mode selected and autoneg enabled
 | 
			
		||||
+ *
 | 
			
		||||
+ * Note: this is for cases where the PCS itself is involved in negotiation
 | 
			
		||||
+ * (e.g. Clause 37, SGMII and similar) not Clause 73.
 | 
			
		||||
+ */
 | 
			
		||||
+static unsigned int phylink_pcs_neg_mode(unsigned int mode,
 | 
			
		||||
+					 phy_interface_t interface,
 | 
			
		||||
+					 const unsigned long *advertising)
 | 
			
		||||
+{
 | 
			
		||||
+	unsigned int neg_mode;
 | 
			
		||||
+
 | 
			
		||||
+	switch (interface) {
 | 
			
		||||
+	case PHY_INTERFACE_MODE_SGMII:
 | 
			
		||||
+	case PHY_INTERFACE_MODE_QSGMII:
 | 
			
		||||
+	case PHY_INTERFACE_MODE_QUSGMII:
 | 
			
		||||
+	case PHY_INTERFACE_MODE_USXGMII:
 | 
			
		||||
+		/* These protocols are designed for use with a PHY which
 | 
			
		||||
+		 * communicates its negotiation result back to the MAC via
 | 
			
		||||
+		 * inband communication. Note: there exist PHYs that run
 | 
			
		||||
+		 * with SGMII but do not send the inband data.
 | 
			
		||||
+		 */
 | 
			
		||||
+		if (!phylink_autoneg_inband(mode))
 | 
			
		||||
+			neg_mode = PHYLINK_PCS_NEG_OUTBAND;
 | 
			
		||||
+		else
 | 
			
		||||
+			neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
 | 
			
		||||
+		break;
 | 
			
		||||
+
 | 
			
		||||
+	case PHY_INTERFACE_MODE_1000BASEX:
 | 
			
		||||
+	case PHY_INTERFACE_MODE_2500BASEX:
 | 
			
		||||
+		/* 1000base-X is designed for use media-side for Fibre
 | 
			
		||||
+		 * connections, and thus the Autoneg bit needs to be
 | 
			
		||||
+		 * taken into account. We also do this for 2500base-X
 | 
			
		||||
+		 * as well, but drivers may not support this, so may
 | 
			
		||||
+		 * need to override this.
 | 
			
		||||
+		 */
 | 
			
		||||
+		if (!phylink_autoneg_inband(mode))
 | 
			
		||||
+			neg_mode = PHYLINK_PCS_NEG_OUTBAND;
 | 
			
		||||
+		else if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
 | 
			
		||||
+					   advertising))
 | 
			
		||||
+			neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
 | 
			
		||||
+		else
 | 
			
		||||
+			neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED;
 | 
			
		||||
+		break;
 | 
			
		||||
+
 | 
			
		||||
+	default:
 | 
			
		||||
+		neg_mode = PHYLINK_PCS_NEG_NONE;
 | 
			
		||||
+		break;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	return neg_mode;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static void phylink_major_config(struct phylink *pl, bool restart,
 | 
			
		||||
 				  const struct phylink_link_state *state)
 | 
			
		||||
 {
 | 
			
		||||
--- a/include/linux/phylink.h
 | 
			
		||||
+++ b/include/linux/phylink.h
 | 
			
		||||
@@ -99,72 +99,6 @@ static inline bool phylink_autoneg_inban
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 /**
 | 
			
		||||
- * phylink_pcs_neg_mode() - helper to determine PCS inband mode
 | 
			
		||||
- * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND.
 | 
			
		||||
- * @interface: interface mode to be used
 | 
			
		||||
- * @advertising: adertisement ethtool link mode mask
 | 
			
		||||
- *
 | 
			
		||||
- * Determines the negotiation mode to be used by the PCS, and returns
 | 
			
		||||
- * one of:
 | 
			
		||||
- *
 | 
			
		||||
- * - %PHYLINK_PCS_NEG_NONE: interface mode does not support inband
 | 
			
		||||
- * - %PHYLINK_PCS_NEG_OUTBAND: an out of band mode (e.g. reading the PHY)
 | 
			
		||||
- *   will be used.
 | 
			
		||||
- * - %PHYLINK_PCS_NEG_INBAND_DISABLED: inband mode selected but autoneg
 | 
			
		||||
- *   disabled
 | 
			
		||||
- * - %PHYLINK_PCS_NEG_INBAND_ENABLED: inband mode selected and autoneg enabled
 | 
			
		||||
- *
 | 
			
		||||
- * Note: this is for cases where the PCS itself is involved in negotiation
 | 
			
		||||
- * (e.g. Clause 37, SGMII and similar) not Clause 73.
 | 
			
		||||
- */
 | 
			
		||||
-static inline unsigned int phylink_pcs_neg_mode(unsigned int mode,
 | 
			
		||||
-						phy_interface_t interface,
 | 
			
		||||
-						const unsigned long *advertising)
 | 
			
		||||
-{
 | 
			
		||||
-	unsigned int neg_mode;
 | 
			
		||||
-
 | 
			
		||||
-	switch (interface) {
 | 
			
		||||
-	case PHY_INTERFACE_MODE_SGMII:
 | 
			
		||||
-	case PHY_INTERFACE_MODE_QSGMII:
 | 
			
		||||
-	case PHY_INTERFACE_MODE_QUSGMII:
 | 
			
		||||
-	case PHY_INTERFACE_MODE_USXGMII:
 | 
			
		||||
-		/* These protocols are designed for use with a PHY which
 | 
			
		||||
-		 * communicates its negotiation result back to the MAC via
 | 
			
		||||
-		 * inband communication. Note: there exist PHYs that run
 | 
			
		||||
-		 * with SGMII but do not send the inband data.
 | 
			
		||||
-		 */
 | 
			
		||||
-		if (!phylink_autoneg_inband(mode))
 | 
			
		||||
-			neg_mode = PHYLINK_PCS_NEG_OUTBAND;
 | 
			
		||||
-		else
 | 
			
		||||
-			neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
 | 
			
		||||
-		break;
 | 
			
		||||
-
 | 
			
		||||
-	case PHY_INTERFACE_MODE_1000BASEX:
 | 
			
		||||
-	case PHY_INTERFACE_MODE_2500BASEX:
 | 
			
		||||
-		/* 1000base-X is designed for use media-side for Fibre
 | 
			
		||||
-		 * connections, and thus the Autoneg bit needs to be
 | 
			
		||||
-		 * taken into account. We also do this for 2500base-X
 | 
			
		||||
-		 * as well, but drivers may not support this, so may
 | 
			
		||||
-		 * need to override this.
 | 
			
		||||
-		 */
 | 
			
		||||
-		if (!phylink_autoneg_inband(mode))
 | 
			
		||||
-			neg_mode = PHYLINK_PCS_NEG_OUTBAND;
 | 
			
		||||
-		else if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
 | 
			
		||||
-					   advertising))
 | 
			
		||||
-			neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
 | 
			
		||||
-		else
 | 
			
		||||
-			neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED;
 | 
			
		||||
-		break;
 | 
			
		||||
-
 | 
			
		||||
-	default:
 | 
			
		||||
-		neg_mode = PHYLINK_PCS_NEG_NONE;
 | 
			
		||||
-		break;
 | 
			
		||||
-	}
 | 
			
		||||
-
 | 
			
		||||
-	return neg_mode;
 | 
			
		||||
-}
 | 
			
		||||
-
 | 
			
		||||
-/**
 | 
			
		||||
  * struct phylink_link_state - link state structure
 | 
			
		||||
  * @advertising: ethtool bitmask containing advertised link modes
 | 
			
		||||
  * @lp_advertising: ethtool bitmask containing link partner advertised link
 | 
			
		||||
@ -0,0 +1,95 @@
 | 
			
		||||
From 17ed1911f9c8d4f9af8e13b2c95103ee06dadc0f Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:30:47 +0000
 | 
			
		||||
Subject: [PATCH 01/13] net: phylink: pass phylink and pcs into
 | 
			
		||||
 phylink_pcs_neg_mode()
 | 
			
		||||
 | 
			
		||||
Move the call to phylink_pcs_neg_mode() in phylink_major_config() after
 | 
			
		||||
we have selected the appropriate PCS to allow the PCS to be passed in.
 | 
			
		||||
 | 
			
		||||
Add struct phylink and struct phylink_pcs pointers to
 | 
			
		||||
phylink_pcs_neg_mode() and pass in the appropriate structures. Set
 | 
			
		||||
pl->pcs_neg_mode before returning, and remove the return value.
 | 
			
		||||
 | 
			
		||||
This will allow the capabilities of the PCS and any PHY to be used when
 | 
			
		||||
deciding which pcs_neg_mode should be used.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUrP-006ITh-6u@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phylink.c | 26 +++++++++++++-------------
 | 
			
		||||
 1 file changed, 13 insertions(+), 13 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -1118,7 +1118,8 @@ static void phylink_pcs_an_restart(struc
 | 
			
		||||
 
 | 
			
		||||
 /**
 | 
			
		||||
  * phylink_pcs_neg_mode() - helper to determine PCS inband mode
 | 
			
		||||
- * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND.
 | 
			
		||||
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
 | 
			
		||||
+ * @pcs: a pointer to &struct phylink_pcs
 | 
			
		||||
  * @interface: interface mode to be used
 | 
			
		||||
  * @advertising: adertisement ethtool link mode mask
 | 
			
		||||
  *
 | 
			
		||||
@@ -1135,11 +1136,13 @@ static void phylink_pcs_an_restart(struc
 | 
			
		||||
  * Note: this is for cases where the PCS itself is involved in negotiation
 | 
			
		||||
  * (e.g. Clause 37, SGMII and similar) not Clause 73.
 | 
			
		||||
  */
 | 
			
		||||
-static unsigned int phylink_pcs_neg_mode(unsigned int mode,
 | 
			
		||||
-					 phy_interface_t interface,
 | 
			
		||||
-					 const unsigned long *advertising)
 | 
			
		||||
+static void phylink_pcs_neg_mode(struct phylink *pl, struct phylink_pcs *pcs,
 | 
			
		||||
+				 phy_interface_t interface,
 | 
			
		||||
+				 const unsigned long *advertising)
 | 
			
		||||
 {
 | 
			
		||||
-	unsigned int neg_mode;
 | 
			
		||||
+	unsigned int neg_mode, mode;
 | 
			
		||||
+
 | 
			
		||||
+	mode = pl->cur_link_an_mode;
 | 
			
		||||
 
 | 
			
		||||
 	switch (interface) {
 | 
			
		||||
 	case PHY_INTERFACE_MODE_SGMII:
 | 
			
		||||
@@ -1179,7 +1182,7 @@ static unsigned int phylink_pcs_neg_mode
 | 
			
		||||
 		break;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	return neg_mode;
 | 
			
		||||
+	pl->pcs_neg_mode = neg_mode;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void phylink_major_config(struct phylink *pl, bool restart,
 | 
			
		||||
@@ -1193,10 +1196,6 @@ static void phylink_major_config(struct
 | 
			
		||||
 
 | 
			
		||||
 	phylink_dbg(pl, "major config %s\n", phy_modes(state->interface));
 | 
			
		||||
 
 | 
			
		||||
-	pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode,
 | 
			
		||||
-						state->interface,
 | 
			
		||||
-						state->advertising);
 | 
			
		||||
-
 | 
			
		||||
 	if (pl->using_mac_select_pcs) {
 | 
			
		||||
 		pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface);
 | 
			
		||||
 		if (IS_ERR(pcs)) {
 | 
			
		||||
@@ -1209,6 +1208,8 @@ static void phylink_major_config(struct
 | 
			
		||||
 		pcs_changed = pcs && pl->pcs != pcs;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
+	phylink_pcs_neg_mode(pl, pcs, state->interface, state->advertising);
 | 
			
		||||
+
 | 
			
		||||
 	phylink_pcs_poll_stop(pl);
 | 
			
		||||
 
 | 
			
		||||
 	if (pl->mac_ops->mac_prepare) {
 | 
			
		||||
@@ -1299,9 +1300,8 @@ static int phylink_change_inband_advert(
 | 
			
		||||
 		    pl->link_config.pause);
 | 
			
		||||
 
 | 
			
		||||
 	/* Recompute the PCS neg mode */
 | 
			
		||||
-	pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode,
 | 
			
		||||
-					pl->link_config.interface,
 | 
			
		||||
-					pl->link_config.advertising);
 | 
			
		||||
+	phylink_pcs_neg_mode(pl, pl->pcs, pl->link_config.interface,
 | 
			
		||||
+			     pl->link_config.advertising);
 | 
			
		||||
 
 | 
			
		||||
 	neg_mode = pl->cur_link_an_mode;
 | 
			
		||||
 	if (pl->pcs->neg_mode)
 | 
			
		||||
@ -0,0 +1,281 @@
 | 
			
		||||
From 1f92ead7e15003f632b5f138e8138095e0997d3d Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:30:52 +0000
 | 
			
		||||
Subject: [PATCH 02/13] net: phylink: split cur_link_an_mode into requested and
 | 
			
		||||
 active
 | 
			
		||||
 | 
			
		||||
There is an interdependence between the current link_an_mode and
 | 
			
		||||
pcs_neg_mode that some drivers rely upon to know whether inband or PHY
 | 
			
		||||
mode will be used.
 | 
			
		||||
 | 
			
		||||
In order to support detection of PCS and PHY inband capabilities
 | 
			
		||||
resulting in automatic selection of inband or PHY mode, we need to
 | 
			
		||||
cater for this, and support changing the MAC link_an_mode. However, we
 | 
			
		||||
end up with an inter-dependency between the current link_an_mode and
 | 
			
		||||
pcs_neg_mode.
 | 
			
		||||
 | 
			
		||||
To solve this, split the current link_an_mode into the requested
 | 
			
		||||
link_an_mode and active link_an_mode. The requested link_an_mode will
 | 
			
		||||
always be passed to phylink_pcs_neg_mode(), and the active link_an_mode
 | 
			
		||||
will be used for everything else, and only updated during
 | 
			
		||||
phylink_major_config(). This will ensure that phylink_pcs_neg_mode()'s
 | 
			
		||||
link_an_mode will not depend on the active link_an_mode that will,
 | 
			
		||||
in a future patch, depend on pcs_neg_mode.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUrU-006ITn-Ai@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phylink.c | 60 ++++++++++++++++++++-------------------
 | 
			
		||||
 1 file changed, 31 insertions(+), 29 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -56,7 +56,8 @@ struct phylink {
 | 
			
		||||
 	struct phy_device *phydev;
 | 
			
		||||
 	phy_interface_t link_interface;	/* PHY_INTERFACE_xxx */
 | 
			
		||||
 	u8 cfg_link_an_mode;		/* MLO_AN_xxx */
 | 
			
		||||
-	u8 cur_link_an_mode;
 | 
			
		||||
+	u8 req_link_an_mode;		/* Requested MLO_AN_xxx mode */
 | 
			
		||||
+	u8 act_link_an_mode;		/* Active MLO_AN_xxx mode */
 | 
			
		||||
 	u8 link_port;			/* The current non-phy ethtool port */
 | 
			
		||||
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
 | 
			
		||||
 
 | 
			
		||||
@@ -1098,13 +1099,13 @@ static void phylink_mac_config(struct ph
 | 
			
		||||
 
 | 
			
		||||
 	phylink_dbg(pl,
 | 
			
		||||
 		    "%s: mode=%s/%s/%s adv=%*pb pause=%02x\n",
 | 
			
		||||
-		    __func__, phylink_an_mode_str(pl->cur_link_an_mode),
 | 
			
		||||
+		    __func__, phylink_an_mode_str(pl->act_link_an_mode),
 | 
			
		||||
 		    phy_modes(st.interface),
 | 
			
		||||
 		    phy_rate_matching_to_str(st.rate_matching),
 | 
			
		||||
 		    __ETHTOOL_LINK_MODE_MASK_NBITS, st.advertising,
 | 
			
		||||
 		    st.pause);
 | 
			
		||||
 
 | 
			
		||||
-	pl->mac_ops->mac_config(pl->config, pl->cur_link_an_mode, &st);
 | 
			
		||||
+	pl->mac_ops->mac_config(pl->config, pl->act_link_an_mode, &st);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void phylink_pcs_an_restart(struct phylink *pl)
 | 
			
		||||
@@ -1112,7 +1113,7 @@ static void phylink_pcs_an_restart(struc
 | 
			
		||||
 	if (pl->pcs && linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
 | 
			
		||||
 					 pl->link_config.advertising) &&
 | 
			
		||||
 	    phy_interface_mode_is_8023z(pl->link_config.interface) &&
 | 
			
		||||
-	    phylink_autoneg_inband(pl->cur_link_an_mode))
 | 
			
		||||
+	    phylink_autoneg_inband(pl->act_link_an_mode))
 | 
			
		||||
 		pl->pcs->ops->pcs_an_restart(pl->pcs);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -1142,7 +1143,7 @@ static void phylink_pcs_neg_mode(struct
 | 
			
		||||
 {
 | 
			
		||||
 	unsigned int neg_mode, mode;
 | 
			
		||||
 
 | 
			
		||||
-	mode = pl->cur_link_an_mode;
 | 
			
		||||
+	mode = pl->req_link_an_mode;
 | 
			
		||||
 
 | 
			
		||||
 	switch (interface) {
 | 
			
		||||
 	case PHY_INTERFACE_MODE_SGMII:
 | 
			
		||||
@@ -1183,6 +1184,7 @@ static void phylink_pcs_neg_mode(struct
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	pl->pcs_neg_mode = neg_mode;
 | 
			
		||||
+	pl->act_link_an_mode = mode;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void phylink_major_config(struct phylink *pl, bool restart,
 | 
			
		||||
@@ -1213,7 +1215,7 @@ static void phylink_major_config(struct
 | 
			
		||||
 	phylink_pcs_poll_stop(pl);
 | 
			
		||||
 
 | 
			
		||||
 	if (pl->mac_ops->mac_prepare) {
 | 
			
		||||
-		err = pl->mac_ops->mac_prepare(pl->config, pl->cur_link_an_mode,
 | 
			
		||||
+		err = pl->mac_ops->mac_prepare(pl->config, pl->act_link_an_mode,
 | 
			
		||||
 					       state->interface);
 | 
			
		||||
 		if (err < 0) {
 | 
			
		||||
 			phylink_err(pl, "mac_prepare failed: %pe\n",
 | 
			
		||||
@@ -1247,7 +1249,7 @@ static void phylink_major_config(struct
 | 
			
		||||
 	if (pl->pcs_state == PCS_STATE_STARTING || pcs_changed)
 | 
			
		||||
 		phylink_pcs_enable(pl->pcs);
 | 
			
		||||
 
 | 
			
		||||
-	neg_mode = pl->cur_link_an_mode;
 | 
			
		||||
+	neg_mode = pl->act_link_an_mode;
 | 
			
		||||
 	if (pl->pcs && pl->pcs->neg_mode)
 | 
			
		||||
 		neg_mode = pl->pcs_neg_mode;
 | 
			
		||||
 
 | 
			
		||||
@@ -1263,7 +1265,7 @@ static void phylink_major_config(struct
 | 
			
		||||
 		phylink_pcs_an_restart(pl);
 | 
			
		||||
 
 | 
			
		||||
 	if (pl->mac_ops->mac_finish) {
 | 
			
		||||
-		err = pl->mac_ops->mac_finish(pl->config, pl->cur_link_an_mode,
 | 
			
		||||
+		err = pl->mac_ops->mac_finish(pl->config, pl->act_link_an_mode,
 | 
			
		||||
 					      state->interface);
 | 
			
		||||
 		if (err < 0)
 | 
			
		||||
 			phylink_err(pl, "mac_finish failed: %pe\n",
 | 
			
		||||
@@ -1294,7 +1296,7 @@ static int phylink_change_inband_advert(
 | 
			
		||||
 		return 0;
 | 
			
		||||
 
 | 
			
		||||
 	phylink_dbg(pl, "%s: mode=%s/%s adv=%*pb pause=%02x\n", __func__,
 | 
			
		||||
-		    phylink_an_mode_str(pl->cur_link_an_mode),
 | 
			
		||||
+		    phylink_an_mode_str(pl->req_link_an_mode),
 | 
			
		||||
 		    phy_modes(pl->link_config.interface),
 | 
			
		||||
 		    __ETHTOOL_LINK_MODE_MASK_NBITS, pl->link_config.advertising,
 | 
			
		||||
 		    pl->link_config.pause);
 | 
			
		||||
@@ -1303,7 +1305,7 @@ static int phylink_change_inband_advert(
 | 
			
		||||
 	phylink_pcs_neg_mode(pl, pl->pcs, pl->link_config.interface,
 | 
			
		||||
 			     pl->link_config.advertising);
 | 
			
		||||
 
 | 
			
		||||
-	neg_mode = pl->cur_link_an_mode;
 | 
			
		||||
+	neg_mode = pl->act_link_an_mode;
 | 
			
		||||
 	if (pl->pcs->neg_mode)
 | 
			
		||||
 		neg_mode = pl->pcs_neg_mode;
 | 
			
		||||
 
 | 
			
		||||
@@ -1368,7 +1370,7 @@ static void phylink_mac_initial_config(s
 | 
			
		||||
 {
 | 
			
		||||
 	struct phylink_link_state link_state;
 | 
			
		||||
 
 | 
			
		||||
-	switch (pl->cur_link_an_mode) {
 | 
			
		||||
+	switch (pl->req_link_an_mode) {
 | 
			
		||||
 	case MLO_AN_PHY:
 | 
			
		||||
 		link_state = pl->phy_state;
 | 
			
		||||
 		break;
 | 
			
		||||
@@ -1442,14 +1444,14 @@ static void phylink_link_up(struct phyli
 | 
			
		||||
 
 | 
			
		||||
 	pl->cur_interface = link_state.interface;
 | 
			
		||||
 
 | 
			
		||||
-	neg_mode = pl->cur_link_an_mode;
 | 
			
		||||
+	neg_mode = pl->act_link_an_mode;
 | 
			
		||||
 	if (pl->pcs && pl->pcs->neg_mode)
 | 
			
		||||
 		neg_mode = pl->pcs_neg_mode;
 | 
			
		||||
 
 | 
			
		||||
 	phylink_pcs_link_up(pl->pcs, neg_mode, pl->cur_interface, speed,
 | 
			
		||||
 			    duplex);
 | 
			
		||||
 
 | 
			
		||||
-	pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->cur_link_an_mode,
 | 
			
		||||
+	pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->act_link_an_mode,
 | 
			
		||||
 				 pl->cur_interface, speed, duplex,
 | 
			
		||||
 				 !!(link_state.pause & MLO_PAUSE_TX), rx_pause);
 | 
			
		||||
 
 | 
			
		||||
@@ -1469,7 +1471,7 @@ static void phylink_link_down(struct phy
 | 
			
		||||
 
 | 
			
		||||
 	if (ndev)
 | 
			
		||||
 		netif_carrier_off(ndev);
 | 
			
		||||
-	pl->mac_ops->mac_link_down(pl->config, pl->cur_link_an_mode,
 | 
			
		||||
+	pl->mac_ops->mac_link_down(pl->config, pl->act_link_an_mode,
 | 
			
		||||
 				   pl->cur_interface);
 | 
			
		||||
 	phylink_info(pl, "Link is Down\n");
 | 
			
		||||
 }
 | 
			
		||||
@@ -1495,10 +1497,10 @@ static void phylink_resolve(struct work_
 | 
			
		||||
 	} else if (pl->mac_link_dropped) {
 | 
			
		||||
 		link_state.link = false;
 | 
			
		||||
 		retrigger = true;
 | 
			
		||||
-	} else if (pl->cur_link_an_mode == MLO_AN_FIXED) {
 | 
			
		||||
+	} else if (pl->act_link_an_mode == MLO_AN_FIXED) {
 | 
			
		||||
 		phylink_get_fixed_state(pl, &link_state);
 | 
			
		||||
 		mac_config = link_state.link;
 | 
			
		||||
-	} else if (pl->cur_link_an_mode == MLO_AN_PHY) {
 | 
			
		||||
+	} else if (pl->act_link_an_mode == MLO_AN_PHY) {
 | 
			
		||||
 		link_state = pl->phy_state;
 | 
			
		||||
 		mac_config = link_state.link;
 | 
			
		||||
 	} else {
 | 
			
		||||
@@ -1552,7 +1554,7 @@ static void phylink_resolve(struct work_
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	if (pl->cur_link_an_mode != MLO_AN_FIXED)
 | 
			
		||||
+	if (pl->act_link_an_mode != MLO_AN_FIXED)
 | 
			
		||||
 		phylink_apply_manual_flow(pl, &link_state);
 | 
			
		||||
 
 | 
			
		||||
 	if (mac_config) {
 | 
			
		||||
@@ -1729,7 +1731,7 @@ struct phylink *phylink_create(struct ph
 | 
			
		||||
 		}
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	pl->cur_link_an_mode = pl->cfg_link_an_mode;
 | 
			
		||||
+	pl->req_link_an_mode = pl->cfg_link_an_mode;
 | 
			
		||||
 
 | 
			
		||||
 	ret = phylink_register_sfp(pl, fwnode);
 | 
			
		||||
 	if (ret < 0) {
 | 
			
		||||
@@ -2126,7 +2128,7 @@ void phylink_start(struct phylink *pl)
 | 
			
		||||
 	ASSERT_RTNL();
 | 
			
		||||
 
 | 
			
		||||
 	phylink_info(pl, "configuring for %s/%s link mode\n",
 | 
			
		||||
-		     phylink_an_mode_str(pl->cur_link_an_mode),
 | 
			
		||||
+		     phylink_an_mode_str(pl->req_link_an_mode),
 | 
			
		||||
 		     phy_modes(pl->link_config.interface));
 | 
			
		||||
 
 | 
			
		||||
 	/* Always set the carrier off */
 | 
			
		||||
@@ -2385,7 +2387,7 @@ int phylink_ethtool_ksettings_get(struct
 | 
			
		||||
 
 | 
			
		||||
 	linkmode_copy(kset->link_modes.supported, pl->supported);
 | 
			
		||||
 
 | 
			
		||||
-	switch (pl->cur_link_an_mode) {
 | 
			
		||||
+	switch (pl->act_link_an_mode) {
 | 
			
		||||
 	case MLO_AN_FIXED:
 | 
			
		||||
 		/* We are using fixed settings. Report these as the
 | 
			
		||||
 		 * current link settings - and note that these also
 | 
			
		||||
@@ -2477,7 +2479,7 @@ int phylink_ethtool_ksettings_set(struct
 | 
			
		||||
 		/* If we have a fixed link, refuse to change link parameters.
 | 
			
		||||
 		 * If the link parameters match, accept them but do nothing.
 | 
			
		||||
 		 */
 | 
			
		||||
-		if (pl->cur_link_an_mode == MLO_AN_FIXED) {
 | 
			
		||||
+		if (pl->req_link_an_mode == MLO_AN_FIXED) {
 | 
			
		||||
 			if (s->speed != pl->link_config.speed ||
 | 
			
		||||
 			    s->duplex != pl->link_config.duplex)
 | 
			
		||||
 				return -EINVAL;
 | 
			
		||||
@@ -2493,7 +2495,7 @@ int phylink_ethtool_ksettings_set(struct
 | 
			
		||||
 		 * is our default case) but do not allow the advertisement to
 | 
			
		||||
 		 * be changed. If the advertisement matches, simply return.
 | 
			
		||||
 		 */
 | 
			
		||||
-		if (pl->cur_link_an_mode == MLO_AN_FIXED) {
 | 
			
		||||
+		if (pl->req_link_an_mode == MLO_AN_FIXED) {
 | 
			
		||||
 			if (!linkmode_equal(config.advertising,
 | 
			
		||||
 					    pl->link_config.advertising))
 | 
			
		||||
 				return -EINVAL;
 | 
			
		||||
@@ -2533,7 +2535,7 @@ int phylink_ethtool_ksettings_set(struct
 | 
			
		||||
 		linkmode_copy(support, pl->supported);
 | 
			
		||||
 		if (phylink_validate(pl, support, &config)) {
 | 
			
		||||
 			phylink_err(pl, "validation of %s/%s with support %*pb failed\n",
 | 
			
		||||
-				    phylink_an_mode_str(pl->cur_link_an_mode),
 | 
			
		||||
+				    phylink_an_mode_str(pl->req_link_an_mode),
 | 
			
		||||
 				    phy_modes(config.interface),
 | 
			
		||||
 				    __ETHTOOL_LINK_MODE_MASK_NBITS, support);
 | 
			
		||||
 			return -EINVAL;
 | 
			
		||||
@@ -2633,7 +2635,7 @@ int phylink_ethtool_set_pauseparam(struc
 | 
			
		||||
 
 | 
			
		||||
 	ASSERT_RTNL();
 | 
			
		||||
 
 | 
			
		||||
-	if (pl->cur_link_an_mode == MLO_AN_FIXED)
 | 
			
		||||
+	if (pl->req_link_an_mode == MLO_AN_FIXED)
 | 
			
		||||
 		return -EOPNOTSUPP;
 | 
			
		||||
 
 | 
			
		||||
 	if (!phylink_test(pl->supported, Pause) &&
 | 
			
		||||
@@ -2897,7 +2899,7 @@ static int phylink_mii_read(struct phyli
 | 
			
		||||
 	struct phylink_link_state state;
 | 
			
		||||
 	int val = 0xffff;
 | 
			
		||||
 
 | 
			
		||||
-	switch (pl->cur_link_an_mode) {
 | 
			
		||||
+	switch (pl->act_link_an_mode) {
 | 
			
		||||
 	case MLO_AN_FIXED:
 | 
			
		||||
 		if (phy_id == 0) {
 | 
			
		||||
 			phylink_get_fixed_state(pl, &state);
 | 
			
		||||
@@ -2922,7 +2924,7 @@ static int phylink_mii_read(struct phyli
 | 
			
		||||
 static int phylink_mii_write(struct phylink *pl, unsigned int phy_id,
 | 
			
		||||
 			     unsigned int reg, unsigned int val)
 | 
			
		||||
 {
 | 
			
		||||
-	switch (pl->cur_link_an_mode) {
 | 
			
		||||
+	switch (pl->act_link_an_mode) {
 | 
			
		||||
 	case MLO_AN_FIXED:
 | 
			
		||||
 		break;
 | 
			
		||||
 
 | 
			
		||||
@@ -3125,9 +3127,9 @@ static void phylink_sfp_set_config(struc
 | 
			
		||||
 		changed = true;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	if (pl->cur_link_an_mode != mode ||
 | 
			
		||||
+	if (pl->req_link_an_mode != mode ||
 | 
			
		||||
 	    pl->link_config.interface != state->interface) {
 | 
			
		||||
-		pl->cur_link_an_mode = mode;
 | 
			
		||||
+		pl->req_link_an_mode = mode;
 | 
			
		||||
 		pl->link_config.interface = state->interface;
 | 
			
		||||
 
 | 
			
		||||
 		changed = true;
 | 
			
		||||
@ -0,0 +1,66 @@
 | 
			
		||||
From 4e7d000286fe8e12f2d88032711ffab3ab658b12 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:30:57 +0000
 | 
			
		||||
Subject: [PATCH 03/13] net: phylink: add debug for phylink_major_config()
 | 
			
		||||
 | 
			
		||||
Now that we have a more complexity in phylink_major_config(), augment
 | 
			
		||||
the debugging so we can see what's going on there.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUrZ-006ITt-Fa@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phylink.c | 27 ++++++++++++++++++++++++++-
 | 
			
		||||
 1 file changed, 26 insertions(+), 1 deletion(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -163,6 +163,24 @@ static const char *phylink_an_mode_str(u
 | 
			
		||||
 	return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown";
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static const char *phylink_pcs_mode_str(unsigned int mode)
 | 
			
		||||
+{
 | 
			
		||||
+	if (!mode)
 | 
			
		||||
+		return "none";
 | 
			
		||||
+
 | 
			
		||||
+	if (mode & PHYLINK_PCS_NEG_OUTBAND)
 | 
			
		||||
+		return "outband";
 | 
			
		||||
+
 | 
			
		||||
+	if (mode & PHYLINK_PCS_NEG_INBAND) {
 | 
			
		||||
+		if (mode & PHYLINK_PCS_NEG_ENABLED)
 | 
			
		||||
+			return "inband,an-enabled";
 | 
			
		||||
+		else
 | 
			
		||||
+			return "inband,an-disabled";
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	return "unknown";
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static unsigned int phylink_interface_signal_rate(phy_interface_t interface)
 | 
			
		||||
 {
 | 
			
		||||
 	switch (interface) {
 | 
			
		||||
@@ -1196,7 +1214,9 @@ static void phylink_major_config(struct
 | 
			
		||||
 	unsigned int neg_mode;
 | 
			
		||||
 	int err;
 | 
			
		||||
 
 | 
			
		||||
-	phylink_dbg(pl, "major config %s\n", phy_modes(state->interface));
 | 
			
		||||
+	phylink_dbg(pl, "major config, requested %s/%s\n",
 | 
			
		||||
+		    phylink_an_mode_str(pl->req_link_an_mode),
 | 
			
		||||
+		    phy_modes(state->interface));
 | 
			
		||||
 
 | 
			
		||||
 	if (pl->using_mac_select_pcs) {
 | 
			
		||||
 		pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface);
 | 
			
		||||
@@ -1212,6 +1232,11 @@ static void phylink_major_config(struct
 | 
			
		||||
 
 | 
			
		||||
 	phylink_pcs_neg_mode(pl, pcs, state->interface, state->advertising);
 | 
			
		||||
 
 | 
			
		||||
+	phylink_dbg(pl, "major config, active %s/%s/%s\n",
 | 
			
		||||
+		    phylink_an_mode_str(pl->act_link_an_mode),
 | 
			
		||||
+		    phylink_pcs_mode_str(pl->pcs_neg_mode),
 | 
			
		||||
+		    phy_modes(state->interface));
 | 
			
		||||
+
 | 
			
		||||
 	phylink_pcs_poll_stop(pl);
 | 
			
		||||
 
 | 
			
		||||
 	if (pl->mac_ops->mac_prepare) {
 | 
			
		||||
@ -0,0 +1,118 @@
 | 
			
		||||
From b4c7698dd95f253c6958d8c6ac219098009bf28a Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:31:02 +0000
 | 
			
		||||
Subject: [PATCH 04/13] net: phy: add phy_inband_caps()
 | 
			
		||||
 | 
			
		||||
Add a method to query the PHY's in-band capabilities for a PHY
 | 
			
		||||
interface mode.
 | 
			
		||||
 | 
			
		||||
Where the interface mode does not have in-band capability, or the PHY
 | 
			
		||||
driver has not been updated to return this information, then
 | 
			
		||||
phy_inband_caps() should return zero. Otherwise, PHY drivers will
 | 
			
		||||
return a value consisting of the following flags:
 | 
			
		||||
 | 
			
		||||
LINK_INBAND_DISABLE indicates that the hardware does not support
 | 
			
		||||
in-band signalling, or can have in-band signalling configured via
 | 
			
		||||
software to be disabled.
 | 
			
		||||
 | 
			
		||||
LINK_INBAND_ENABLE indicates that the hardware will use in-band
 | 
			
		||||
signalling, or can have in-band signalling configured via software
 | 
			
		||||
to be enabled.
 | 
			
		||||
 | 
			
		||||
LINK_INBAND_BYPASS indicates that the hardware has the ability to
 | 
			
		||||
bypass in-band signalling when enabled after a timeout if the link
 | 
			
		||||
partner does not respond to its in-band signalling.
 | 
			
		||||
 | 
			
		||||
This reports the PHY capabilities for the particular interface mode,
 | 
			
		||||
not the current configuration.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUre-006ITz-KF@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phy.c | 21 +++++++++++++++++++++
 | 
			
		||||
 include/linux/phy.h   | 28 ++++++++++++++++++++++++++++
 | 
			
		||||
 2 files changed, 49 insertions(+)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phy.c
 | 
			
		||||
+++ b/drivers/net/phy/phy.c
 | 
			
		||||
@@ -973,6 +973,27 @@ static int phy_check_link_status(struct
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 /**
 | 
			
		||||
+ * phy_inband_caps - query which in-band signalling modes are supported
 | 
			
		||||
+ * @phydev: a pointer to a &struct phy_device
 | 
			
		||||
+ * @interface: the interface mode for the PHY
 | 
			
		||||
+ *
 | 
			
		||||
+ * Returns zero if it is unknown what in-band signalling is supported by the
 | 
			
		||||
+ * PHY (e.g. because the PHY driver doesn't implement the method.) Otherwise,
 | 
			
		||||
+ * returns a bit mask of the LINK_INBAND_* values from
 | 
			
		||||
+ * &enum link_inband_signalling to describe which inband modes are supported
 | 
			
		||||
+ * by the PHY for this interface mode.
 | 
			
		||||
+ */
 | 
			
		||||
+unsigned int phy_inband_caps(struct phy_device *phydev,
 | 
			
		||||
+			     phy_interface_t interface)
 | 
			
		||||
+{
 | 
			
		||||
+	if (phydev->drv && phydev->drv->inband_caps)
 | 
			
		||||
+		return phydev->drv->inband_caps(phydev, interface);
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+EXPORT_SYMBOL_GPL(phy_inband_caps);
 | 
			
		||||
+
 | 
			
		||||
+/**
 | 
			
		||||
  * _phy_start_aneg - start auto-negotiation for this PHY device
 | 
			
		||||
  * @phydev: the phy_device struct
 | 
			
		||||
  *
 | 
			
		||||
--- a/include/linux/phy.h
 | 
			
		||||
+++ b/include/linux/phy.h
 | 
			
		||||
@@ -790,6 +790,24 @@ struct phy_tdr_config {
 | 
			
		||||
 #define PHY_PAIR_ALL -1
 | 
			
		||||
 
 | 
			
		||||
 /**
 | 
			
		||||
+ * enum link_inband_signalling - in-band signalling modes that are supported
 | 
			
		||||
+ *
 | 
			
		||||
+ * @LINK_INBAND_DISABLE: in-band signalling can be disabled
 | 
			
		||||
+ * @LINK_INBAND_ENABLE: in-band signalling can be enabled without bypass
 | 
			
		||||
+ * @LINK_INBAND_BYPASS: in-band signalling can be enabled with bypass
 | 
			
		||||
+ *
 | 
			
		||||
+ * The possible and required bits can only be used if the valid bit is set.
 | 
			
		||||
+ * If possible is clear, that means inband signalling can not be used.
 | 
			
		||||
+ * Required is only valid when possible is set, and means that inband
 | 
			
		||||
+ * signalling must be used.
 | 
			
		||||
+ */
 | 
			
		||||
+enum link_inband_signalling {
 | 
			
		||||
+	LINK_INBAND_DISABLE		= BIT(0),
 | 
			
		||||
+	LINK_INBAND_ENABLE		= BIT(1),
 | 
			
		||||
+	LINK_INBAND_BYPASS		= BIT(2),
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
+/**
 | 
			
		||||
  * struct phy_plca_cfg - Configuration of the PLCA (Physical Layer Collision
 | 
			
		||||
  * Avoidance) Reconciliation Sublayer.
 | 
			
		||||
  *
 | 
			
		||||
@@ -919,6 +937,14 @@ struct phy_driver {
 | 
			
		||||
 	int (*get_features)(struct phy_device *phydev);
 | 
			
		||||
 
 | 
			
		||||
 	/**
 | 
			
		||||
+	 * @inband_caps: query whether in-band is supported for the given PHY
 | 
			
		||||
+	 * interface mode. Returns a bitmask of bits defined by enum
 | 
			
		||||
+	 * link_inband_signalling.
 | 
			
		||||
+	 */
 | 
			
		||||
+	unsigned int (*inband_caps)(struct phy_device *phydev,
 | 
			
		||||
+				    phy_interface_t interface);
 | 
			
		||||
+
 | 
			
		||||
+	/**
 | 
			
		||||
 	 * @get_rate_matching: Get the supported type of rate matching for a
 | 
			
		||||
 	 * particular phy interface. This is used by phy consumers to determine
 | 
			
		||||
 	 * whether to advertise lower-speed modes for that interface. It is
 | 
			
		||||
@@ -1735,6 +1761,8 @@ void phy_stop(struct phy_device *phydev)
 | 
			
		||||
 int phy_config_aneg(struct phy_device *phydev);
 | 
			
		||||
 int phy_start_aneg(struct phy_device *phydev);
 | 
			
		||||
 int phy_aneg_done(struct phy_device *phydev);
 | 
			
		||||
+unsigned int phy_inband_caps(struct phy_device *phydev,
 | 
			
		||||
+			     phy_interface_t interface);
 | 
			
		||||
 int phy_speed_down(struct phy_device *phydev, bool sync);
 | 
			
		||||
 int phy_speed_up(struct phy_device *phydev);
 | 
			
		||||
 bool phy_check_valid(int speed, int duplex, unsigned long *features);
 | 
			
		||||
@ -0,0 +1,41 @@
 | 
			
		||||
From c64c7fa0a774d9da72071a8517e359992baac982 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:31:07 +0000
 | 
			
		||||
Subject: [PATCH 05/13] net: phy: bcm84881: implement phy_inband_caps() method
 | 
			
		||||
 | 
			
		||||
BCM84881 has no support for inband signalling, so this is a trivial
 | 
			
		||||
implementation that returns no support for inband.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Acked-by: Florian Fainelli <florian.fainelli@broadcom.com>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUrj-006IU6-ON@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/bcm84881.c | 10 ++++++++++
 | 
			
		||||
 1 file changed, 10 insertions(+)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/bcm84881.c
 | 
			
		||||
+++ b/drivers/net/phy/bcm84881.c
 | 
			
		||||
@@ -223,11 +223,21 @@ static int bcm84881_read_status(struct p
 | 
			
		||||
 	return genphy_c45_read_mdix(phydev);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+/* The Broadcom BCM84881 in the Methode DM7052 is unable to provide a SGMII
 | 
			
		||||
+ * or 802.3z control word, so inband will not work.
 | 
			
		||||
+ */
 | 
			
		||||
+static unsigned int bcm84881_inband_caps(struct phy_device *phydev,
 | 
			
		||||
+					 phy_interface_t interface)
 | 
			
		||||
+{
 | 
			
		||||
+	return LINK_INBAND_DISABLE;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static struct phy_driver bcm84881_drivers[] = {
 | 
			
		||||
 	{
 | 
			
		||||
 		.phy_id		= 0xae025150,
 | 
			
		||||
 		.phy_id_mask	= 0xfffffff0,
 | 
			
		||||
 		.name		= "Broadcom BCM84881",
 | 
			
		||||
+		.inband_caps	= bcm84881_inband_caps,
 | 
			
		||||
 		.config_init	= bcm84881_config_init,
 | 
			
		||||
 		.probe		= bcm84881_probe,
 | 
			
		||||
 		.get_features	= bcm84881_get_features,
 | 
			
		||||
@ -0,0 +1,63 @@
 | 
			
		||||
From 1c86828dff88e28b8ade6bddeee0163a023faf91 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:31:12 +0000
 | 
			
		||||
Subject: [PATCH 06/13] net: phy: marvell: implement phy_inband_caps() method
 | 
			
		||||
 | 
			
		||||
Provide an implementation for phy_inband_caps() for Marvell PHYs used
 | 
			
		||||
on SFP modules, so that phylink knows the PHYs capabilities.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUro-006IUC-Rq@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/marvell.c | 17 +++++++++++++++++
 | 
			
		||||
 1 file changed, 17 insertions(+)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/marvell.c
 | 
			
		||||
+++ b/drivers/net/phy/marvell.c
 | 
			
		||||
@@ -673,6 +673,20 @@ static int marvell_config_aneg_fiber(str
 | 
			
		||||
 	return genphy_check_and_restart_aneg(phydev, changed);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static unsigned int m88e1111_inband_caps(struct phy_device *phydev,
 | 
			
		||||
+					 phy_interface_t interface)
 | 
			
		||||
+{
 | 
			
		||||
+	/* In 1000base-X and SGMII modes, the inband mode can be changed
 | 
			
		||||
+	 * through the Fibre page BMCR ANENABLE bit.
 | 
			
		||||
+	 */
 | 
			
		||||
+	if (interface == PHY_INTERFACE_MODE_1000BASEX ||
 | 
			
		||||
+	    interface == PHY_INTERFACE_MODE_SGMII)
 | 
			
		||||
+		return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE |
 | 
			
		||||
+		       LINK_INBAND_BYPASS;
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static int m88e1111_config_aneg(struct phy_device *phydev)
 | 
			
		||||
 {
 | 
			
		||||
 	int extsr = phy_read(phydev, MII_M1111_PHY_EXT_SR);
 | 
			
		||||
@@ -3292,6 +3306,7 @@ static struct phy_driver marvell_drivers
 | 
			
		||||
 		.name = "Marvell 88E1112",
 | 
			
		||||
 		/* PHY_GBIT_FEATURES */
 | 
			
		||||
 		.probe = marvell_probe,
 | 
			
		||||
+		.inband_caps = m88e1111_inband_caps,
 | 
			
		||||
 		.config_init = m88e1112_config_init,
 | 
			
		||||
 		.config_aneg = marvell_config_aneg,
 | 
			
		||||
 		.config_intr = marvell_config_intr,
 | 
			
		||||
@@ -3312,6 +3327,7 @@ static struct phy_driver marvell_drivers
 | 
			
		||||
 		.name = "Marvell 88E1111",
 | 
			
		||||
 		/* PHY_GBIT_FEATURES */
 | 
			
		||||
 		.probe = marvell_probe,
 | 
			
		||||
+		.inband_caps = m88e1111_inband_caps,
 | 
			
		||||
 		.config_init = m88e1111gbe_config_init,
 | 
			
		||||
 		.config_aneg = m88e1111_config_aneg,
 | 
			
		||||
 		.read_status = marvell_read_status,
 | 
			
		||||
@@ -3333,6 +3349,7 @@ static struct phy_driver marvell_drivers
 | 
			
		||||
 		.name = "Marvell 88E1111 (Finisar)",
 | 
			
		||||
 		/* PHY_GBIT_FEATURES */
 | 
			
		||||
 		.probe = marvell_probe,
 | 
			
		||||
+		.inband_caps = m88e1111_inband_caps,
 | 
			
		||||
 		.config_init = m88e1111gbe_config_init,
 | 
			
		||||
 		.config_aneg = m88e1111_config_aneg,
 | 
			
		||||
 		.read_status = marvell_read_status,
 | 
			
		||||
@ -0,0 +1,79 @@
 | 
			
		||||
From 5d58a890c02770ba8d790b1f3c6e8c0e20514dc2 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:31:18 +0000
 | 
			
		||||
Subject: [PATCH 07/13] net: phy: add phy_config_inband()
 | 
			
		||||
 | 
			
		||||
Add a method to configure the PHY's in-band mode.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUru-006IUI-08@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phy.c | 32 ++++++++++++++++++++++++++++++++
 | 
			
		||||
 include/linux/phy.h   |  6 ++++++
 | 
			
		||||
 2 files changed, 38 insertions(+)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phy.c
 | 
			
		||||
+++ b/drivers/net/phy/phy.c
 | 
			
		||||
@@ -994,6 +994,38 @@ unsigned int phy_inband_caps(struct phy_
 | 
			
		||||
 EXPORT_SYMBOL_GPL(phy_inband_caps);
 | 
			
		||||
 
 | 
			
		||||
 /**
 | 
			
		||||
+ * phy_config_inband - configure the desired PHY in-band mode
 | 
			
		||||
+ * @phydev: the phy_device struct
 | 
			
		||||
+ * @modes: in-band modes to configure
 | 
			
		||||
+ *
 | 
			
		||||
+ * Description: disables, enables or enables-with-bypass in-band signalling
 | 
			
		||||
+ *   between the PHY and host system.
 | 
			
		||||
+ *
 | 
			
		||||
+ * Returns: zero on success, or negative errno value.
 | 
			
		||||
+ */
 | 
			
		||||
+int phy_config_inband(struct phy_device *phydev, unsigned int modes)
 | 
			
		||||
+{
 | 
			
		||||
+	int err;
 | 
			
		||||
+
 | 
			
		||||
+	if (!!(modes & LINK_INBAND_DISABLE) +
 | 
			
		||||
+	    !!(modes & LINK_INBAND_ENABLE) +
 | 
			
		||||
+	    !!(modes & LINK_INBAND_BYPASS) != 1)
 | 
			
		||||
+		return -EINVAL;
 | 
			
		||||
+
 | 
			
		||||
+	mutex_lock(&phydev->lock);
 | 
			
		||||
+	if (!phydev->drv)
 | 
			
		||||
+		err = -EIO;
 | 
			
		||||
+	else if (!phydev->drv->config_inband)
 | 
			
		||||
+		err = -EOPNOTSUPP;
 | 
			
		||||
+	else
 | 
			
		||||
+		err = phydev->drv->config_inband(phydev, modes);
 | 
			
		||||
+	mutex_unlock(&phydev->lock);
 | 
			
		||||
+
 | 
			
		||||
+	return err;
 | 
			
		||||
+}
 | 
			
		||||
+EXPORT_SYMBOL(phy_config_inband);
 | 
			
		||||
+
 | 
			
		||||
+/**
 | 
			
		||||
  * _phy_start_aneg - start auto-negotiation for this PHY device
 | 
			
		||||
  * @phydev: the phy_device struct
 | 
			
		||||
  *
 | 
			
		||||
--- a/include/linux/phy.h
 | 
			
		||||
+++ b/include/linux/phy.h
 | 
			
		||||
@@ -945,6 +945,11 @@ struct phy_driver {
 | 
			
		||||
 				    phy_interface_t interface);
 | 
			
		||||
 
 | 
			
		||||
 	/**
 | 
			
		||||
+	 * @config_inband: configure in-band mode for the PHY
 | 
			
		||||
+	 */
 | 
			
		||||
+	int (*config_inband)(struct phy_device *phydev, unsigned int modes);
 | 
			
		||||
+
 | 
			
		||||
+	/**
 | 
			
		||||
 	 * @get_rate_matching: Get the supported type of rate matching for a
 | 
			
		||||
 	 * particular phy interface. This is used by phy consumers to determine
 | 
			
		||||
 	 * whether to advertise lower-speed modes for that interface. It is
 | 
			
		||||
@@ -1763,6 +1768,7 @@ int phy_start_aneg(struct phy_device *ph
 | 
			
		||||
 int phy_aneg_done(struct phy_device *phydev);
 | 
			
		||||
 unsigned int phy_inband_caps(struct phy_device *phydev,
 | 
			
		||||
 			     phy_interface_t interface);
 | 
			
		||||
+int phy_config_inband(struct phy_device *phydev, unsigned int modes);
 | 
			
		||||
 int phy_speed_down(struct phy_device *phydev, bool sync);
 | 
			
		||||
 int phy_speed_up(struct phy_device *phydev);
 | 
			
		||||
 bool phy_check_valid(int speed, int duplex, unsigned long *features);
 | 
			
		||||
@ -0,0 +1,77 @@
 | 
			
		||||
From a219912e0fec73c346e64ef47013cb2e152f88fc Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:31:23 +0000
 | 
			
		||||
Subject: [PATCH 08/13] net: phy: marvell: implement config_inband() method
 | 
			
		||||
 | 
			
		||||
Implement the config_inband() method for Marvell 88E1112, 88E1111,
 | 
			
		||||
and Finisar's 88E1111 variant.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUrz-006IUO-3r@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/marvell.c | 31 +++++++++++++++++++++++++++++++
 | 
			
		||||
 1 file changed, 31 insertions(+)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/marvell.c
 | 
			
		||||
+++ b/drivers/net/phy/marvell.c
 | 
			
		||||
@@ -687,6 +687,34 @@ static unsigned int m88e1111_inband_caps
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static int m88e1111_config_inband(struct phy_device *phydev, unsigned int modes)
 | 
			
		||||
+{
 | 
			
		||||
+	u16 extsr, bmcr;
 | 
			
		||||
+	int err;
 | 
			
		||||
+
 | 
			
		||||
+	if (phydev->interface != PHY_INTERFACE_MODE_1000BASEX &&
 | 
			
		||||
+	    phydev->interface != PHY_INTERFACE_MODE_SGMII)
 | 
			
		||||
+		return -EINVAL;
 | 
			
		||||
+
 | 
			
		||||
+	if (modes == LINK_INBAND_BYPASS)
 | 
			
		||||
+		extsr = MII_M1111_HWCFG_SERIAL_AN_BYPASS;
 | 
			
		||||
+	else
 | 
			
		||||
+		extsr = 0;
 | 
			
		||||
+
 | 
			
		||||
+	if (modes == LINK_INBAND_DISABLE)
 | 
			
		||||
+		bmcr = 0;
 | 
			
		||||
+	else
 | 
			
		||||
+		bmcr = BMCR_ANENABLE;
 | 
			
		||||
+
 | 
			
		||||
+	err = phy_modify(phydev, MII_M1111_PHY_EXT_SR,
 | 
			
		||||
+			 MII_M1111_HWCFG_SERIAL_AN_BYPASS, extsr);
 | 
			
		||||
+	if (err < 0)
 | 
			
		||||
+		return extsr;
 | 
			
		||||
+
 | 
			
		||||
+	return phy_modify_paged(phydev, MII_MARVELL_FIBER_PAGE, MII_BMCR,
 | 
			
		||||
+				BMCR_ANENABLE, bmcr);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static int m88e1111_config_aneg(struct phy_device *phydev)
 | 
			
		||||
 {
 | 
			
		||||
 	int extsr = phy_read(phydev, MII_M1111_PHY_EXT_SR);
 | 
			
		||||
@@ -3307,6 +3335,7 @@ static struct phy_driver marvell_drivers
 | 
			
		||||
 		/* PHY_GBIT_FEATURES */
 | 
			
		||||
 		.probe = marvell_probe,
 | 
			
		||||
 		.inband_caps = m88e1111_inband_caps,
 | 
			
		||||
+		.config_inband = m88e1111_config_inband,
 | 
			
		||||
 		.config_init = m88e1112_config_init,
 | 
			
		||||
 		.config_aneg = marvell_config_aneg,
 | 
			
		||||
 		.config_intr = marvell_config_intr,
 | 
			
		||||
@@ -3328,6 +3357,7 @@ static struct phy_driver marvell_drivers
 | 
			
		||||
 		/* PHY_GBIT_FEATURES */
 | 
			
		||||
 		.probe = marvell_probe,
 | 
			
		||||
 		.inband_caps = m88e1111_inband_caps,
 | 
			
		||||
+		.config_inband = m88e1111_config_inband,
 | 
			
		||||
 		.config_init = m88e1111gbe_config_init,
 | 
			
		||||
 		.config_aneg = m88e1111_config_aneg,
 | 
			
		||||
 		.read_status = marvell_read_status,
 | 
			
		||||
@@ -3350,6 +3380,7 @@ static struct phy_driver marvell_drivers
 | 
			
		||||
 		/* PHY_GBIT_FEATURES */
 | 
			
		||||
 		.probe = marvell_probe,
 | 
			
		||||
 		.inband_caps = m88e1111_inband_caps,
 | 
			
		||||
+		.config_inband = m88e1111_config_inband,
 | 
			
		||||
 		.config_init = m88e1111gbe_config_init,
 | 
			
		||||
 		.config_aneg = m88e1111_config_aneg,
 | 
			
		||||
 		.read_status = marvell_read_status,
 | 
			
		||||
@ -0,0 +1,159 @@
 | 
			
		||||
From df874f9e52c340cc6f0a0014a97b778f67d46849 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:31:28 +0000
 | 
			
		||||
Subject: [PATCH 09/13] net: phylink: add pcs_inband_caps() method
 | 
			
		||||
 | 
			
		||||
Add a pcs_inband_caps() method to query the PCS for its inband link
 | 
			
		||||
capabilities, and use this to determine whether link modes used with
 | 
			
		||||
optical SFPs can be supported.
 | 
			
		||||
 | 
			
		||||
When a PCS does not provide a method, we allow inband negotiation to
 | 
			
		||||
be either on or off, making this a no-op until the pcs_inband_caps()
 | 
			
		||||
method is implemented by a PCS driver.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUs4-006IUU-7K@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phylink.c | 60 +++++++++++++++++++++++++++++++++++++++
 | 
			
		||||
 include/linux/phylink.h   | 17 +++++++++++
 | 
			
		||||
 2 files changed, 77 insertions(+)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -1038,6 +1038,15 @@ static void phylink_resolve_an_pause(str
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static unsigned int phylink_pcs_inband_caps(struct phylink_pcs *pcs,
 | 
			
		||||
+				    phy_interface_t interface)
 | 
			
		||||
+{
 | 
			
		||||
+	if (pcs && pcs->ops->pcs_inband_caps)
 | 
			
		||||
+		return pcs->ops->pcs_inband_caps(pcs, interface);
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static void phylink_pcs_pre_config(struct phylink_pcs *pcs,
 | 
			
		||||
 				   phy_interface_t interface)
 | 
			
		||||
 {
 | 
			
		||||
@@ -1091,6 +1100,24 @@ static void phylink_pcs_link_up(struct p
 | 
			
		||||
 		pcs->ops->pcs_link_up(pcs, neg_mode, interface, speed, duplex);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+/* Query inband for a specific interface mode, asking the MAC for the
 | 
			
		||||
+ * PCS which will be used to handle the interface mode.
 | 
			
		||||
+ */
 | 
			
		||||
+static unsigned int phylink_inband_caps(struct phylink *pl,
 | 
			
		||||
+					 phy_interface_t interface)
 | 
			
		||||
+{
 | 
			
		||||
+	struct phylink_pcs *pcs;
 | 
			
		||||
+
 | 
			
		||||
+	if (!pl->mac_ops->mac_select_pcs)
 | 
			
		||||
+		return 0;
 | 
			
		||||
+
 | 
			
		||||
+	pcs = pl->mac_ops->mac_select_pcs(pl->config, interface);
 | 
			
		||||
+	if (!pcs)
 | 
			
		||||
+		return 0;
 | 
			
		||||
+
 | 
			
		||||
+	return phylink_pcs_inband_caps(pcs, interface);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static void phylink_pcs_poll_stop(struct phylink *pl)
 | 
			
		||||
 {
 | 
			
		||||
 	if (pl->cfg_link_an_mode == MLO_AN_INBAND)
 | 
			
		||||
@@ -2443,6 +2470,26 @@ int phylink_ethtool_ksettings_get(struct
 | 
			
		||||
 }
 | 
			
		||||
 EXPORT_SYMBOL_GPL(phylink_ethtool_ksettings_get);
 | 
			
		||||
 
 | 
			
		||||
+static bool phylink_validate_pcs_inband_autoneg(struct phylink *pl,
 | 
			
		||||
+					        phy_interface_t interface,
 | 
			
		||||
+						unsigned long *adv)
 | 
			
		||||
+{
 | 
			
		||||
+	unsigned int inband = phylink_inband_caps(pl, interface);
 | 
			
		||||
+	unsigned int mask;
 | 
			
		||||
+
 | 
			
		||||
+	/* If the PCS doesn't implement inband support, be permissive. */
 | 
			
		||||
+	if (!inband)
 | 
			
		||||
+		return true;
 | 
			
		||||
+
 | 
			
		||||
+	if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, adv))
 | 
			
		||||
+		mask = LINK_INBAND_ENABLE;
 | 
			
		||||
+	else
 | 
			
		||||
+		mask = LINK_INBAND_DISABLE;
 | 
			
		||||
+
 | 
			
		||||
+	/* Check whether the PCS implements the required mode */
 | 
			
		||||
+	return !!(inband & mask);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 /**
 | 
			
		||||
  * phylink_ethtool_ksettings_set() - set the link settings
 | 
			
		||||
  * @pl: a pointer to a &struct phylink returned from phylink_create()
 | 
			
		||||
@@ -2578,6 +2625,13 @@ int phylink_ethtool_ksettings_set(struct
 | 
			
		||||
 	    phylink_is_empty_linkmode(config.advertising))
 | 
			
		||||
 		return -EINVAL;
 | 
			
		||||
 
 | 
			
		||||
+	/* Validate the autonegotiation state. We don't have a PHY in this
 | 
			
		||||
+	 * situation, so the PCS is the media-facing entity.
 | 
			
		||||
+	 */
 | 
			
		||||
+	if (!phylink_validate_pcs_inband_autoneg(pl, config.interface,
 | 
			
		||||
+						 config.advertising))
 | 
			
		||||
+		return -EINVAL;
 | 
			
		||||
+
 | 
			
		||||
 	mutex_lock(&pl->state_mutex);
 | 
			
		||||
 	pl->link_config.speed = config.speed;
 | 
			
		||||
 	pl->link_config.duplex = config.duplex;
 | 
			
		||||
@@ -3274,6 +3328,12 @@ static int phylink_sfp_config_optical(st
 | 
			
		||||
 	phylink_dbg(pl, "optical SFP: chosen %s interface\n",
 | 
			
		||||
 		    phy_modes(interface));
 | 
			
		||||
 
 | 
			
		||||
+	if (!phylink_validate_pcs_inband_autoneg(pl, interface,
 | 
			
		||||
+						 config.advertising)) {
 | 
			
		||||
+		phylink_err(pl, "autoneg setting not compatible with PCS");
 | 
			
		||||
+		return -EINVAL;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
 	config.interface = interface;
 | 
			
		||||
 
 | 
			
		||||
 	/* Ignore errors if we're expecting a PHY to attach later */
 | 
			
		||||
--- a/include/linux/phylink.h
 | 
			
		||||
+++ b/include/linux/phylink.h
 | 
			
		||||
@@ -432,6 +432,7 @@ struct phylink_pcs {
 | 
			
		||||
 /**
 | 
			
		||||
  * struct phylink_pcs_ops - MAC PCS operations structure.
 | 
			
		||||
  * @pcs_validate: validate the link configuration.
 | 
			
		||||
+ * @pcs_inband_caps: query inband support for interface mode.
 | 
			
		||||
  * @pcs_enable: enable the PCS.
 | 
			
		||||
  * @pcs_disable: disable the PCS.
 | 
			
		||||
  * @pcs_pre_config: pre-mac_config method (for errata)
 | 
			
		||||
@@ -445,6 +446,8 @@ struct phylink_pcs {
 | 
			
		||||
 struct phylink_pcs_ops {
 | 
			
		||||
 	int (*pcs_validate)(struct phylink_pcs *pcs, unsigned long *supported,
 | 
			
		||||
 			    const struct phylink_link_state *state);
 | 
			
		||||
+	unsigned int (*pcs_inband_caps)(struct phylink_pcs *pcs,
 | 
			
		||||
+					phy_interface_t interface);
 | 
			
		||||
 	int (*pcs_enable)(struct phylink_pcs *pcs);
 | 
			
		||||
 	void (*pcs_disable)(struct phylink_pcs *pcs);
 | 
			
		||||
 	void (*pcs_pre_config)(struct phylink_pcs *pcs,
 | 
			
		||||
@@ -481,6 +484,20 @@ int pcs_validate(struct phylink_pcs *pcs
 | 
			
		||||
 		 const struct phylink_link_state *state);
 | 
			
		||||
 
 | 
			
		||||
 /**
 | 
			
		||||
+ * pcs_inband_caps - query PCS in-band capabilities for interface mode.
 | 
			
		||||
+ * @pcs: a pointer to a &struct phylink_pcs.
 | 
			
		||||
+ * @interface: interface mode to be queried
 | 
			
		||||
+ *
 | 
			
		||||
+ * Returns zero if it is unknown what in-band signalling is supported by the
 | 
			
		||||
+ * PHY (e.g. because the PHY driver doesn't implement the method.) Otherwise,
 | 
			
		||||
+ * returns a bit mask of the LINK_INBAND_* values from
 | 
			
		||||
+ * &enum link_inband_signalling to describe which inband modes are supported
 | 
			
		||||
+ * for this interface mode.
 | 
			
		||||
+ */
 | 
			
		||||
+unsigned int pcs_inband_caps(struct phylink_pcs *pcs,
 | 
			
		||||
+			     phy_interface_t interface);
 | 
			
		||||
+
 | 
			
		||||
+/**
 | 
			
		||||
  * pcs_enable() - enable the PCS.
 | 
			
		||||
  * @pcs: a pointer to a &struct phylink_pcs.
 | 
			
		||||
  */
 | 
			
		||||
@ -0,0 +1,64 @@
 | 
			
		||||
From 513e8fb8fa32035b3325e2e14fb9598f8cb545e9 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:31:33 +0000
 | 
			
		||||
Subject: [PATCH 10/13] net: mvneta: implement pcs_inband_caps() method
 | 
			
		||||
 | 
			
		||||
Report the PCS in-band capabilities to phylink for Marvell NETA
 | 
			
		||||
interfaces.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUs9-006IUb-Au@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/ethernet/marvell/mvneta.c | 27 +++++++++++++++++----------
 | 
			
		||||
 1 file changed, 17 insertions(+), 10 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/ethernet/marvell/mvneta.c
 | 
			
		||||
+++ b/drivers/net/ethernet/marvell/mvneta.c
 | 
			
		||||
@@ -3959,20 +3959,27 @@ static struct mvneta_port *mvneta_pcs_to
 | 
			
		||||
 	return container_of(pcs, struct mvneta_port, phylink_pcs);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static int mvneta_pcs_validate(struct phylink_pcs *pcs,
 | 
			
		||||
-			       unsigned long *supported,
 | 
			
		||||
-			       const struct phylink_link_state *state)
 | 
			
		||||
+static unsigned int mvneta_pcs_inband_caps(struct phylink_pcs *pcs,
 | 
			
		||||
+					   phy_interface_t interface)
 | 
			
		||||
 {
 | 
			
		||||
-	/* We only support QSGMII, SGMII, 802.3z and RGMII modes.
 | 
			
		||||
-	 * When in 802.3z mode, we must have AN enabled:
 | 
			
		||||
+	/* When operating in an 802.3z mode, we must have AN enabled:
 | 
			
		||||
 	 * "Bit 2 Field InBandAnEn In-band Auto-Negotiation enable. ...
 | 
			
		||||
 	 * When <PortType> = 1 (1000BASE-X) this field must be set to 1."
 | 
			
		||||
+	 * Therefore, inband is "required".
 | 
			
		||||
 	 */
 | 
			
		||||
-	if (phy_interface_mode_is_8023z(state->interface) &&
 | 
			
		||||
-	    !phylink_test(state->advertising, Autoneg))
 | 
			
		||||
-		return -EINVAL;
 | 
			
		||||
+	if (phy_interface_mode_is_8023z(interface))
 | 
			
		||||
+		return LINK_INBAND_ENABLE;
 | 
			
		||||
 
 | 
			
		||||
-	return 0;
 | 
			
		||||
+	/* QSGMII, SGMII and RGMII can be configured to use inband
 | 
			
		||||
+	 * signalling of the AN result. Indicate these as "possible".
 | 
			
		||||
+	 */
 | 
			
		||||
+	if (interface == PHY_INTERFACE_MODE_SGMII ||
 | 
			
		||||
+	    interface == PHY_INTERFACE_MODE_QSGMII ||
 | 
			
		||||
+	    phy_interface_mode_is_rgmii(interface))
 | 
			
		||||
+		return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
 | 
			
		||||
+
 | 
			
		||||
+	/* For any other modes, indicate that inband is not supported. */
 | 
			
		||||
+	return LINK_INBAND_DISABLE;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void mvneta_pcs_get_state(struct phylink_pcs *pcs,
 | 
			
		||||
@@ -4070,7 +4077,7 @@ static void mvneta_pcs_an_restart(struct
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static const struct phylink_pcs_ops mvneta_phylink_pcs_ops = {
 | 
			
		||||
-	.pcs_validate = mvneta_pcs_validate,
 | 
			
		||||
+	.pcs_inband_caps = mvneta_pcs_inband_caps,
 | 
			
		||||
 	.pcs_get_state = mvneta_pcs_get_state,
 | 
			
		||||
 	.pcs_config = mvneta_pcs_config,
 | 
			
		||||
 	.pcs_an_restart = mvneta_pcs_an_restart,
 | 
			
		||||
@ -0,0 +1,62 @@
 | 
			
		||||
From d4169f0c7665afb8d8adb5e1b1df3db88517d0ad Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:31:38 +0000
 | 
			
		||||
Subject: [PATCH 11/13] net: mvpp2: implement pcs_inband_caps() method
 | 
			
		||||
 | 
			
		||||
Report the PCS in-band capabilities to phylink for Marvell PP2
 | 
			
		||||
interfaces.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUsE-006IUh-E7@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 .../net/ethernet/marvell/mvpp2/mvpp2_main.c   | 25 ++++++++++++-------
 | 
			
		||||
 1 file changed, 16 insertions(+), 9 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
 | 
			
		||||
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
 | 
			
		||||
@@ -6214,19 +6214,26 @@ static const struct phylink_pcs_ops mvpp
 | 
			
		||||
 	.pcs_config = mvpp2_xlg_pcs_config,
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
-static int mvpp2_gmac_pcs_validate(struct phylink_pcs *pcs,
 | 
			
		||||
-				   unsigned long *supported,
 | 
			
		||||
-				   const struct phylink_link_state *state)
 | 
			
		||||
+static unsigned int mvpp2_gmac_pcs_inband_caps(struct phylink_pcs *pcs,
 | 
			
		||||
+					       phy_interface_t interface)
 | 
			
		||||
 {
 | 
			
		||||
-	/* When in 802.3z mode, we must have AN enabled:
 | 
			
		||||
+	/* When operating in an 802.3z mode, we must have AN enabled:
 | 
			
		||||
 	 * Bit 2 Field InBandAnEn In-band Auto-Negotiation enable. ...
 | 
			
		||||
 	 * When <PortType> = 1 (1000BASE-X) this field must be set to 1.
 | 
			
		||||
+	 * Therefore, inband is "required".
 | 
			
		||||
 	 */
 | 
			
		||||
-	if (phy_interface_mode_is_8023z(state->interface) &&
 | 
			
		||||
-	    !phylink_test(state->advertising, Autoneg))
 | 
			
		||||
-		return -EINVAL;
 | 
			
		||||
+	if (phy_interface_mode_is_8023z(interface))
 | 
			
		||||
+		return LINK_INBAND_ENABLE;
 | 
			
		||||
 
 | 
			
		||||
-	return 0;
 | 
			
		||||
+	/* SGMII and RGMII can be configured to use inband signalling of the
 | 
			
		||||
+	 * AN result. Indicate these as "possible".
 | 
			
		||||
+	 */
 | 
			
		||||
+	if (interface == PHY_INTERFACE_MODE_SGMII ||
 | 
			
		||||
+	    phy_interface_mode_is_rgmii(interface))
 | 
			
		||||
+		return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
 | 
			
		||||
+
 | 
			
		||||
+	/* For any other modes, indicate that inband is not supported. */
 | 
			
		||||
+	return LINK_INBAND_DISABLE;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void mvpp2_gmac_pcs_get_state(struct phylink_pcs *pcs,
 | 
			
		||||
@@ -6333,7 +6340,7 @@ static void mvpp2_gmac_pcs_an_restart(st
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static const struct phylink_pcs_ops mvpp2_phylink_gmac_pcs_ops = {
 | 
			
		||||
-	.pcs_validate = mvpp2_gmac_pcs_validate,
 | 
			
		||||
+	.pcs_inband_caps = mvpp2_gmac_pcs_inband_caps,
 | 
			
		||||
 	.pcs_get_state = mvpp2_gmac_pcs_get_state,
 | 
			
		||||
 	.pcs_config = mvpp2_gmac_pcs_config,
 | 
			
		||||
 	.pcs_an_restart = mvpp2_gmac_pcs_an_restart,
 | 
			
		||||
@ -0,0 +1,228 @@
 | 
			
		||||
From 5fd0f1a02e750e2db4038dee60edea669ce5aab1 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:31:43 +0000
 | 
			
		||||
Subject: [PATCH 12/13] net: phylink: add negotiation of in-band capabilities
 | 
			
		||||
 | 
			
		||||
Support for in-band signalling with Serdes links is uncertain. Some
 | 
			
		||||
PHYs do not support in-band for e.g. SGMII. Some PCS do not support
 | 
			
		||||
in-band for 2500Base-X. Some PCS require in-band for Base-X protocols.
 | 
			
		||||
 | 
			
		||||
Simply using what is in DT is insufficient when we have hot-pluggable
 | 
			
		||||
PHYs e.g. in the form of SFP modules, which may not provide the
 | 
			
		||||
in-band signalling.
 | 
			
		||||
 | 
			
		||||
In order to address this, we have introduced phy_inband_caps() and
 | 
			
		||||
pcs_inband_caps() functions to allow phylink to retrieve the
 | 
			
		||||
capabilities from each end of the PCS/PHY link. This commit adds code
 | 
			
		||||
to resolve whether in-band will be used in the various scenarios that
 | 
			
		||||
we have: In-band not being used, PHY present using SGMII or Base-X,
 | 
			
		||||
PHY not present. We also deal with no capabilties provided.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUsJ-006IUn-H3@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phylink.c | 154 +++++++++++++++++++++++++++++++++++---
 | 
			
		||||
 1 file changed, 144 insertions(+), 10 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -75,6 +75,7 @@ struct phylink {
 | 
			
		||||
 
 | 
			
		||||
 	struct mutex state_mutex;
 | 
			
		||||
 	struct phylink_link_state phy_state;
 | 
			
		||||
+	unsigned int phy_ib_mode;
 | 
			
		||||
 	struct work_struct resolve;
 | 
			
		||||
 	unsigned int pcs_neg_mode;
 | 
			
		||||
 	unsigned int pcs_state;
 | 
			
		||||
@@ -1186,10 +1187,18 @@ static void phylink_pcs_neg_mode(struct
 | 
			
		||||
 				 phy_interface_t interface,
 | 
			
		||||
 				 const unsigned long *advertising)
 | 
			
		||||
 {
 | 
			
		||||
+	unsigned int pcs_ib_caps = 0;
 | 
			
		||||
+	unsigned int phy_ib_caps = 0;
 | 
			
		||||
 	unsigned int neg_mode, mode;
 | 
			
		||||
+	enum {
 | 
			
		||||
+		INBAND_CISCO_SGMII,
 | 
			
		||||
+		INBAND_BASEX,
 | 
			
		||||
+	} type;
 | 
			
		||||
 
 | 
			
		||||
 	mode = pl->req_link_an_mode;
 | 
			
		||||
 
 | 
			
		||||
+	pl->phy_ib_mode = 0;
 | 
			
		||||
+
 | 
			
		||||
 	switch (interface) {
 | 
			
		||||
 	case PHY_INTERFACE_MODE_SGMII:
 | 
			
		||||
 	case PHY_INTERFACE_MODE_QSGMII:
 | 
			
		||||
@@ -1200,10 +1209,7 @@ static void phylink_pcs_neg_mode(struct
 | 
			
		||||
 		 * inband communication. Note: there exist PHYs that run
 | 
			
		||||
 		 * with SGMII but do not send the inband data.
 | 
			
		||||
 		 */
 | 
			
		||||
-		if (!phylink_autoneg_inband(mode))
 | 
			
		||||
-			neg_mode = PHYLINK_PCS_NEG_OUTBAND;
 | 
			
		||||
-		else
 | 
			
		||||
-			neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
 | 
			
		||||
+		type = INBAND_CISCO_SGMII;
 | 
			
		||||
 		break;
 | 
			
		||||
 
 | 
			
		||||
 	case PHY_INTERFACE_MODE_1000BASEX:
 | 
			
		||||
@@ -1214,18 +1220,139 @@ static void phylink_pcs_neg_mode(struct
 | 
			
		||||
 		 * as well, but drivers may not support this, so may
 | 
			
		||||
 		 * need to override this.
 | 
			
		||||
 		 */
 | 
			
		||||
-		if (!phylink_autoneg_inband(mode))
 | 
			
		||||
+		type = INBAND_BASEX;
 | 
			
		||||
+		break;
 | 
			
		||||
+
 | 
			
		||||
+	default:
 | 
			
		||||
+		pl->pcs_neg_mode = PHYLINK_PCS_NEG_NONE;
 | 
			
		||||
+		pl->act_link_an_mode = mode;
 | 
			
		||||
+		return;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	if (pcs)
 | 
			
		||||
+		pcs_ib_caps = phylink_pcs_inband_caps(pcs, interface);
 | 
			
		||||
+
 | 
			
		||||
+	if (pl->phydev)
 | 
			
		||||
+		phy_ib_caps = phy_inband_caps(pl->phydev, interface);
 | 
			
		||||
+
 | 
			
		||||
+	phylink_dbg(pl, "interface %s inband modes: pcs=%02x phy=%02x\n",
 | 
			
		||||
+		    phy_modes(interface), pcs_ib_caps, phy_ib_caps);
 | 
			
		||||
+
 | 
			
		||||
+	if (!phylink_autoneg_inband(mode)) {
 | 
			
		||||
+		bool pcs_ib_only = false;
 | 
			
		||||
+		bool phy_ib_only = false;
 | 
			
		||||
+
 | 
			
		||||
+		if (pcs_ib_caps && pcs_ib_caps != LINK_INBAND_DISABLE) {
 | 
			
		||||
+			/* PCS supports reporting in-band capabilities, and
 | 
			
		||||
+			 * supports more than disable mode.
 | 
			
		||||
+			 */
 | 
			
		||||
+			if (pcs_ib_caps & LINK_INBAND_DISABLE)
 | 
			
		||||
+				neg_mode = PHYLINK_PCS_NEG_OUTBAND;
 | 
			
		||||
+			else if (pcs_ib_caps & LINK_INBAND_ENABLE)
 | 
			
		||||
+				pcs_ib_only = true;
 | 
			
		||||
+		}
 | 
			
		||||
+
 | 
			
		||||
+		if (phy_ib_caps && phy_ib_caps != LINK_INBAND_DISABLE) {
 | 
			
		||||
+			/* PHY supports in-band capabilities, and supports
 | 
			
		||||
+			 * more than disable mode.
 | 
			
		||||
+			 */
 | 
			
		||||
+			if (phy_ib_caps & LINK_INBAND_DISABLE)
 | 
			
		||||
+				pl->phy_ib_mode = LINK_INBAND_DISABLE;
 | 
			
		||||
+			else if (phy_ib_caps & LINK_INBAND_BYPASS)
 | 
			
		||||
+				pl->phy_ib_mode = LINK_INBAND_BYPASS;
 | 
			
		||||
+			else if (phy_ib_caps & LINK_INBAND_ENABLE)
 | 
			
		||||
+				phy_ib_only = true;
 | 
			
		||||
+		}
 | 
			
		||||
+
 | 
			
		||||
+		/* If either the PCS or PHY requires inband to be enabled,
 | 
			
		||||
+		 * this is an invalid configuration. Provide a diagnostic
 | 
			
		||||
+		 * message for this case, but don't try to force the issue.
 | 
			
		||||
+		 */
 | 
			
		||||
+		if (pcs_ib_only || phy_ib_only)
 | 
			
		||||
+			phylink_warn(pl,
 | 
			
		||||
+				     "firmware wants %s mode, but %s%s%s requires inband\n",
 | 
			
		||||
+				     phylink_an_mode_str(mode),
 | 
			
		||||
+				     pcs_ib_only ? "PCS" : "",
 | 
			
		||||
+				     pcs_ib_only && phy_ib_only ? " and " : "",
 | 
			
		||||
+				     phy_ib_only ? "PHY" : "");
 | 
			
		||||
+
 | 
			
		||||
+		neg_mode = PHYLINK_PCS_NEG_OUTBAND;
 | 
			
		||||
+	} else if (type == INBAND_CISCO_SGMII || pl->phydev) {
 | 
			
		||||
+		/* For SGMII modes which are designed to be used with PHYs, or
 | 
			
		||||
+		 * Base-X with a PHY, we try to use in-band mode where-ever
 | 
			
		||||
+		 * possible. However, there are some PHYs e.g. BCM84881 which
 | 
			
		||||
+		 * do not support in-band.
 | 
			
		||||
+		 */
 | 
			
		||||
+		const unsigned int inband_ok = LINK_INBAND_ENABLE |
 | 
			
		||||
+					       LINK_INBAND_BYPASS;
 | 
			
		||||
+		const unsigned int outband_ok = LINK_INBAND_DISABLE |
 | 
			
		||||
+						LINK_INBAND_BYPASS;
 | 
			
		||||
+		/* PCS	PHY
 | 
			
		||||
+		 * D E	D E
 | 
			
		||||
+		 * 0 0  0 0	no information			inband enabled
 | 
			
		||||
+		 * 1 0  0 0	pcs doesn't support		outband
 | 
			
		||||
+		 * 0 1  0 0	pcs required			inband enabled
 | 
			
		||||
+		 * 1 1  0 0	pcs optional			inband enabled
 | 
			
		||||
+		 * 0 0  1 0	phy doesn't support		outband
 | 
			
		||||
+		 * 1 0  1 0	pcs+phy doesn't support		outband
 | 
			
		||||
+		 * 0 1  1 0	pcs required, phy doesn't support, invalid
 | 
			
		||||
+		 * 1 1  1 0	pcs optional, phy doesn't support, outband
 | 
			
		||||
+		 * 0 0  0 1	phy required			inband enabled
 | 
			
		||||
+		 * 1 0  0 1	pcs doesn't support, phy required, invalid
 | 
			
		||||
+		 * 0 1  0 1	pcs+phy required		inband enabled
 | 
			
		||||
+		 * 1 1  0 1	pcs optional, phy required	inband enabled
 | 
			
		||||
+		 * 0 0  1 1	phy optional			inband enabled
 | 
			
		||||
+		 * 1 0  1 1	pcs doesn't support, phy optional, outband
 | 
			
		||||
+		 * 0 1  1 1	pcs required, phy optional	inband enabled
 | 
			
		||||
+		 * 1 1  1 1	pcs+phy optional		inband enabled
 | 
			
		||||
+		 */
 | 
			
		||||
+		if ((!pcs_ib_caps || pcs_ib_caps & inband_ok) &&
 | 
			
		||||
+		    (!phy_ib_caps || phy_ib_caps & inband_ok)) {
 | 
			
		||||
+			/* In-band supported or unknown at both ends. Enable
 | 
			
		||||
+			 * in-band mode with or without bypass at the PHY.
 | 
			
		||||
+			 */
 | 
			
		||||
+			if (phy_ib_caps & LINK_INBAND_ENABLE)
 | 
			
		||||
+				pl->phy_ib_mode = LINK_INBAND_ENABLE;
 | 
			
		||||
+			else if (phy_ib_caps & LINK_INBAND_BYPASS)
 | 
			
		||||
+				pl->phy_ib_mode = LINK_INBAND_BYPASS;
 | 
			
		||||
+
 | 
			
		||||
+			neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
 | 
			
		||||
+		} else if ((!pcs_ib_caps || pcs_ib_caps & outband_ok) &&
 | 
			
		||||
+			   (!phy_ib_caps || phy_ib_caps & outband_ok)) {
 | 
			
		||||
+			/* Either in-band not supported at at least one end.
 | 
			
		||||
+			 * In-band bypass at the other end is possible.
 | 
			
		||||
+			 */
 | 
			
		||||
+			if (phy_ib_caps & LINK_INBAND_DISABLE)
 | 
			
		||||
+				pl->phy_ib_mode = LINK_INBAND_DISABLE;
 | 
			
		||||
+			else if (phy_ib_caps & LINK_INBAND_BYPASS)
 | 
			
		||||
+				pl->phy_ib_mode = LINK_INBAND_BYPASS;
 | 
			
		||||
+
 | 
			
		||||
 			neg_mode = PHYLINK_PCS_NEG_OUTBAND;
 | 
			
		||||
+			if (pl->phydev)
 | 
			
		||||
+				mode = MLO_AN_PHY;
 | 
			
		||||
+		} else {
 | 
			
		||||
+			/* invalid */
 | 
			
		||||
+			phylink_warn(pl, "%s: incompatible in-band capabilities, trying in-band",
 | 
			
		||||
+				     phy_modes(interface));
 | 
			
		||||
+			neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
 | 
			
		||||
+		}
 | 
			
		||||
+	} else {
 | 
			
		||||
+		/* For Base-X without a PHY */
 | 
			
		||||
+		if (pcs_ib_caps == LINK_INBAND_DISABLE)
 | 
			
		||||
+			/* If the PCS doesn't support inband, then inband must
 | 
			
		||||
+			 * be disabled.
 | 
			
		||||
+			 */
 | 
			
		||||
+			neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED;
 | 
			
		||||
+		else if (pcs_ib_caps == LINK_INBAND_ENABLE)
 | 
			
		||||
+			/* If the PCS requires inband, then inband must always
 | 
			
		||||
+			 * be enabled.
 | 
			
		||||
+			 */
 | 
			
		||||
+			neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
 | 
			
		||||
 		else if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
 | 
			
		||||
 					   advertising))
 | 
			
		||||
 			neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
 | 
			
		||||
 		else
 | 
			
		||||
 			neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED;
 | 
			
		||||
-		break;
 | 
			
		||||
-
 | 
			
		||||
-	default:
 | 
			
		||||
-		neg_mode = PHYLINK_PCS_NEG_NONE;
 | 
			
		||||
-		break;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	pl->pcs_neg_mode = neg_mode;
 | 
			
		||||
@@ -1324,6 +1451,13 @@ static void phylink_major_config(struct
 | 
			
		||||
 				    ERR_PTR(err));
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
+	if (pl->phydev && pl->phy_ib_mode) {
 | 
			
		||||
+		err = phy_config_inband(pl->phydev, pl->phy_ib_mode);
 | 
			
		||||
+		if (err < 0)
 | 
			
		||||
+			phylink_err(pl, "phy_config_inband: %pe\n",
 | 
			
		||||
+				    ERR_PTR(err));
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
 	if (pl->sfp_bus) {
 | 
			
		||||
 		rate_kbd = phylink_interface_signal_rate(state->interface);
 | 
			
		||||
 		if (rate_kbd)
 | 
			
		||||
@ -0,0 +1,110 @@
 | 
			
		||||
From 77ac9a8b2536e0eaca6c6f21070068458bf55981 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 3 Dec 2024 15:31:48 +0000
 | 
			
		||||
Subject: [PATCH 13/13] net: phylink: remove phylink_phy_no_inband()
 | 
			
		||||
 | 
			
		||||
Remove phylink_phy_no_inband() now that we are handling the lack of
 | 
			
		||||
inband negotiation by querying the capabilities of the PHY and PCS,
 | 
			
		||||
and the BCM84881 PHY driver provides us the information necessary to
 | 
			
		||||
make the decision.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tIUsO-006IUt-KN@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phylink.c | 27 ++++++---------------------
 | 
			
		||||
 1 file changed, 6 insertions(+), 21 deletions(-)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -3320,10 +3320,11 @@ static phy_interface_t phylink_choose_sf
 | 
			
		||||
 	return interface;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static void phylink_sfp_set_config(struct phylink *pl, u8 mode,
 | 
			
		||||
+static void phylink_sfp_set_config(struct phylink *pl,
 | 
			
		||||
 				   unsigned long *supported,
 | 
			
		||||
 				   struct phylink_link_state *state)
 | 
			
		||||
 {
 | 
			
		||||
+	u8 mode = MLO_AN_INBAND;
 | 
			
		||||
 	bool changed = false;
 | 
			
		||||
 
 | 
			
		||||
 	phylink_dbg(pl, "requesting link mode %s/%s with support %*pb\n",
 | 
			
		||||
@@ -3357,8 +3358,7 @@ static void phylink_sfp_set_config(struc
 | 
			
		||||
 		phylink_mac_initial_config(pl, false);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static int phylink_sfp_config_phy(struct phylink *pl, u8 mode,
 | 
			
		||||
-				  struct phy_device *phy)
 | 
			
		||||
+static int phylink_sfp_config_phy(struct phylink *pl, struct phy_device *phy)
 | 
			
		||||
 {
 | 
			
		||||
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(support1);
 | 
			
		||||
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(support);
 | 
			
		||||
@@ -3398,7 +3398,7 @@ static int phylink_sfp_config_phy(struct
 | 
			
		||||
 	if (ret) {
 | 
			
		||||
 		phylink_err(pl,
 | 
			
		||||
 			    "validation of %s/%s with support %*pb failed: %pe\n",
 | 
			
		||||
-			    phylink_an_mode_str(mode),
 | 
			
		||||
+			    phylink_an_mode_str(pl->req_link_an_mode),
 | 
			
		||||
 			    phy_modes(config.interface),
 | 
			
		||||
 			    __ETHTOOL_LINK_MODE_MASK_NBITS, support,
 | 
			
		||||
 			    ERR_PTR(ret));
 | 
			
		||||
@@ -3407,7 +3407,7 @@ static int phylink_sfp_config_phy(struct
 | 
			
		||||
 
 | 
			
		||||
 	pl->link_port = pl->sfp_port;
 | 
			
		||||
 
 | 
			
		||||
-	phylink_sfp_set_config(pl, mode, support, &config);
 | 
			
		||||
+	phylink_sfp_set_config(pl, support, &config);
 | 
			
		||||
 
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
@@ -3481,7 +3481,7 @@ static int phylink_sfp_config_optical(st
 | 
			
		||||
 
 | 
			
		||||
 	pl->link_port = pl->sfp_port;
 | 
			
		||||
 
 | 
			
		||||
-	phylink_sfp_set_config(pl, MLO_AN_INBAND, pl->sfp_support, &config);
 | 
			
		||||
+	phylink_sfp_set_config(pl, pl->sfp_support, &config);
 | 
			
		||||
 
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
@@ -3552,20 +3552,10 @@ static void phylink_sfp_link_up(void *up
 | 
			
		||||
 	phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_LINK);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-/* The Broadcom BCM84881 in the Methode DM7052 is unable to provide a SGMII
 | 
			
		||||
- * or 802.3z control word, so inband will not work.
 | 
			
		||||
- */
 | 
			
		||||
-static bool phylink_phy_no_inband(struct phy_device *phy)
 | 
			
		||||
-{
 | 
			
		||||
-	return phy->is_c45 && phy_id_compare(phy->c45_ids.device_ids[1],
 | 
			
		||||
-					     0xae025150, 0xfffffff0);
 | 
			
		||||
-}
 | 
			
		||||
-
 | 
			
		||||
 static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy)
 | 
			
		||||
 {
 | 
			
		||||
 	struct phylink *pl = upstream;
 | 
			
		||||
 	phy_interface_t interface;
 | 
			
		||||
-	u8 mode;
 | 
			
		||||
 	int ret;
 | 
			
		||||
 
 | 
			
		||||
 	/*
 | 
			
		||||
@@ -3577,17 +3567,12 @@ static int phylink_sfp_connect_phy(void
 | 
			
		||||
 	 */
 | 
			
		||||
 	phy_support_asym_pause(phy);
 | 
			
		||||
 
 | 
			
		||||
-	if (phylink_phy_no_inband(phy))
 | 
			
		||||
-		mode = MLO_AN_PHY;
 | 
			
		||||
-	else
 | 
			
		||||
-		mode = MLO_AN_INBAND;
 | 
			
		||||
-
 | 
			
		||||
 	/* Set the PHY's host supported interfaces */
 | 
			
		||||
 	phy_interface_and(phy->host_interfaces, phylink_sfp_interfaces,
 | 
			
		||||
 			  pl->config->supported_interfaces);
 | 
			
		||||
 
 | 
			
		||||
 	/* Do the initial configuration */
 | 
			
		||||
-	ret = phylink_sfp_config_phy(pl, mode, phy);
 | 
			
		||||
+	ret = phylink_sfp_config_phy(pl, phy);
 | 
			
		||||
 	if (ret < 0)
 | 
			
		||||
 		return ret;
 | 
			
		||||
 
 | 
			
		||||
@ -0,0 +1,53 @@
 | 
			
		||||
From 6561f0e547be221f411fda5eddfcc5bd8bb058a5 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Thu, 5 Dec 2024 09:42:24 +0000
 | 
			
		||||
Subject: [PATCH 1/3] net: pcs: pcs-lynx: implement pcs_inband_caps() method
 | 
			
		||||
 | 
			
		||||
Report the PCS in-band capabilities to phylink for the Lynx PCS.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tJ8NM-006L5J-AH@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/pcs/pcs-lynx.c | 22 ++++++++++++++++++++++
 | 
			
		||||
 1 file changed, 22 insertions(+)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/pcs/pcs-lynx.c
 | 
			
		||||
+++ b/drivers/net/pcs/pcs-lynx.c
 | 
			
		||||
@@ -35,6 +35,27 @@ enum sgmii_speed {
 | 
			
		||||
 #define phylink_pcs_to_lynx(pl_pcs) container_of((pl_pcs), struct lynx_pcs, pcs)
 | 
			
		||||
 #define lynx_to_phylink_pcs(lynx) (&(lynx)->pcs)
 | 
			
		||||
 
 | 
			
		||||
+static unsigned int lynx_pcs_inband_caps(struct phylink_pcs *pcs,
 | 
			
		||||
+					 phy_interface_t interface)
 | 
			
		||||
+{
 | 
			
		||||
+	switch (interface) {
 | 
			
		||||
+	case PHY_INTERFACE_MODE_1000BASEX:
 | 
			
		||||
+	case PHY_INTERFACE_MODE_SGMII:
 | 
			
		||||
+	case PHY_INTERFACE_MODE_QSGMII:
 | 
			
		||||
+		return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
 | 
			
		||||
+
 | 
			
		||||
+	case PHY_INTERFACE_MODE_10GBASER:
 | 
			
		||||
+	case PHY_INTERFACE_MODE_2500BASEX:
 | 
			
		||||
+		return LINK_INBAND_DISABLE;
 | 
			
		||||
+
 | 
			
		||||
+	case PHY_INTERFACE_MODE_USXGMII:
 | 
			
		||||
+		return LINK_INBAND_ENABLE;
 | 
			
		||||
+
 | 
			
		||||
+	default:
 | 
			
		||||
+		return 0;
 | 
			
		||||
+	}
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static void lynx_pcs_get_state_usxgmii(struct mdio_device *pcs,
 | 
			
		||||
 				       struct phylink_link_state *state)
 | 
			
		||||
 {
 | 
			
		||||
@@ -307,6 +328,7 @@ static void lynx_pcs_link_up(struct phyl
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static const struct phylink_pcs_ops lynx_pcs_phylink_ops = {
 | 
			
		||||
+	.pcs_inband_caps = lynx_pcs_inband_caps,
 | 
			
		||||
 	.pcs_get_state = lynx_pcs_get_state,
 | 
			
		||||
 	.pcs_config = lynx_pcs_config,
 | 
			
		||||
 	.pcs_an_restart = lynx_pcs_an_restart,
 | 
			
		||||
@ -0,0 +1,47 @@
 | 
			
		||||
From 520d29bdda86915b3caf8c72825a574bff212553 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Thu, 5 Dec 2024 09:42:29 +0000
 | 
			
		||||
Subject: [PATCH 2/3] net: pcs: pcs-mtk-lynxi: implement pcs_inband_caps()
 | 
			
		||||
 method
 | 
			
		||||
 | 
			
		||||
Report the PCS in-band capabilities to phylink for the LynxI PCS.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tJ8NR-006L5P-E3@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/pcs/pcs-mtk-lynxi.c | 16 ++++++++++++++++
 | 
			
		||||
 1 file changed, 16 insertions(+)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/pcs/pcs-mtk-lynxi.c
 | 
			
		||||
+++ b/drivers/net/pcs/pcs-mtk-lynxi.c
 | 
			
		||||
@@ -88,6 +88,21 @@ static struct mtk_pcs_lynxi *pcs_to_mtk_
 | 
			
		||||
 	return container_of(pcs, struct mtk_pcs_lynxi, pcs);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static unsigned int mtk_pcs_lynxi_inband_caps(struct phylink_pcs *pcs,
 | 
			
		||||
+					      phy_interface_t interface)
 | 
			
		||||
+{
 | 
			
		||||
+	switch (interface) {
 | 
			
		||||
+	case PHY_INTERFACE_MODE_1000BASEX:
 | 
			
		||||
+	case PHY_INTERFACE_MODE_2500BASEX:
 | 
			
		||||
+	case PHY_INTERFACE_MODE_SGMII:
 | 
			
		||||
+	case PHY_INTERFACE_MODE_QSGMII:
 | 
			
		||||
+		return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
 | 
			
		||||
+
 | 
			
		||||
+	default:
 | 
			
		||||
+		return 0;
 | 
			
		||||
+	}
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static void mtk_pcs_lynxi_get_state(struct phylink_pcs *pcs,
 | 
			
		||||
 				    struct phylink_link_state *state)
 | 
			
		||||
 {
 | 
			
		||||
@@ -241,6 +256,7 @@ static void mtk_pcs_lynxi_disable(struct
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static const struct phylink_pcs_ops mtk_pcs_lynxi_ops = {
 | 
			
		||||
+	.pcs_inband_caps = mtk_pcs_lynxi_inband_caps,
 | 
			
		||||
 	.pcs_get_state = mtk_pcs_lynxi_get_state,
 | 
			
		||||
 	.pcs_config = mtk_pcs_lynxi_config,
 | 
			
		||||
 	.pcs_an_restart = mtk_pcs_lynxi_restart_an,
 | 
			
		||||
@ -0,0 +1,58 @@
 | 
			
		||||
From 484d0170d6c6bbb5213d037664e9a551f793bacd Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Thu, 5 Dec 2024 09:42:34 +0000
 | 
			
		||||
Subject: [PATCH 3/3] net: pcs: xpcs: implement pcs_inband_caps() method
 | 
			
		||||
 | 
			
		||||
Report the PCS inband capabilities to phylink for XPCS.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Link: https://patch.msgid.link/E1tJ8NW-006L5V-I9@rmk-PC.armlinux.org.uk
 | 
			
		||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/pcs/pcs-xpcs.c | 28 ++++++++++++++++++++++++++++
 | 
			
		||||
 1 file changed, 28 insertions(+)
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/pcs/pcs-xpcs.c
 | 
			
		||||
+++ b/drivers/net/pcs/pcs-xpcs.c
 | 
			
		||||
@@ -628,6 +628,33 @@ static int xpcs_validate(struct phylink_
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static unsigned int xpcs_inband_caps(struct phylink_pcs *pcs,
 | 
			
		||||
+				     phy_interface_t interface)
 | 
			
		||||
+{
 | 
			
		||||
+	struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
 | 
			
		||||
+	const struct xpcs_compat *compat;
 | 
			
		||||
+
 | 
			
		||||
+	compat = xpcs_find_compat(xpcs->id, interface);
 | 
			
		||||
+	if (!compat)
 | 
			
		||||
+		return 0;
 | 
			
		||||
+
 | 
			
		||||
+	switch (compat->an_mode) {
 | 
			
		||||
+	case DW_AN_C73:
 | 
			
		||||
+		return LINK_INBAND_ENABLE;
 | 
			
		||||
+
 | 
			
		||||
+	case DW_AN_C37_SGMII:
 | 
			
		||||
+	case DW_AN_C37_1000BASEX:
 | 
			
		||||
+		return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
 | 
			
		||||
+
 | 
			
		||||
+	case DW_10GBASER:
 | 
			
		||||
+	case DW_2500BASEX:
 | 
			
		||||
+		return LINK_INBAND_DISABLE;
 | 
			
		||||
+
 | 
			
		||||
+	default:
 | 
			
		||||
+		return 0;
 | 
			
		||||
+	}
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 void xpcs_get_interfaces(struct dw_xpcs *xpcs, unsigned long *interfaces)
 | 
			
		||||
 {
 | 
			
		||||
 	int i, j;
 | 
			
		||||
@@ -1331,6 +1358,7 @@ static const struct xpcs_id xpcs_id_list
 | 
			
		||||
 
 | 
			
		||||
 static const struct phylink_pcs_ops xpcs_phylink_ops = {
 | 
			
		||||
 	.pcs_validate = xpcs_validate,
 | 
			
		||||
+	.pcs_inband_caps = xpcs_inband_caps,
 | 
			
		||||
 	.pcs_config = xpcs_config,
 | 
			
		||||
 	.pcs_get_state = xpcs_get_state,
 | 
			
		||||
 	.pcs_an_restart = xpcs_an_restart,
 | 
			
		||||
@ -242,7 +242,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
 | 
			
		||||
 	refcount_t refcnt;
 | 
			
		||||
 	unsigned long flags;
 | 
			
		||||
 	size_t priv_size;
 | 
			
		||||
@@ -1966,10 +1967,10 @@ int phy_ethtool_get_link_ksettings(struc
 | 
			
		||||
@@ -2000,10 +2001,10 @@ int phy_ethtool_get_link_ksettings(struc
 | 
			
		||||
 int phy_ethtool_set_link_ksettings(struct net_device *ndev,
 | 
			
		||||
 				   const struct ethtool_link_ksettings *cmd);
 | 
			
		||||
 int phy_ethtool_nway_reset(struct net_device *ndev);
 | 
			
		||||
@ -255,7 +255,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
 | 
			
		||||
 
 | 
			
		||||
 int __init mdio_bus_init(void);
 | 
			
		||||
 void mdio_bus_exit(void);
 | 
			
		||||
@@ -1992,46 +1993,65 @@ int __phy_hwtstamp_set(struct phy_device
 | 
			
		||||
@@ -2026,46 +2027,65 @@ int __phy_hwtstamp_set(struct phy_device
 | 
			
		||||
 		       struct kernel_hwtstamp_config *config,
 | 
			
		||||
 		       struct netlink_ext_ack *extack);
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
@ -171,7 +171,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
 | 
			
		||||
  * @regnum: register number to modify
 | 
			
		||||
--- a/include/linux/phy.h
 | 
			
		||||
+++ b/include/linux/phy.h
 | 
			
		||||
@@ -2054,6 +2054,22 @@ static inline int __phy_package_write(st
 | 
			
		||||
@@ -2088,6 +2088,22 @@ static inline int __phy_package_write(st
 | 
			
		||||
 	return __mdiobus_write(phydev->mdio.bus, addr, regnum, val);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
@ -170,7 +170,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
 | 
			
		||||
 	refcount_t refcnt;
 | 
			
		||||
 	unsigned long flags;
 | 
			
		||||
 	size_t priv_size;
 | 
			
		||||
@@ -1968,9 +1971,12 @@ int phy_ethtool_set_link_ksettings(struc
 | 
			
		||||
@@ -2002,9 +2005,12 @@ int phy_ethtool_set_link_ksettings(struc
 | 
			
		||||
 				   const struct ethtool_link_ksettings *cmd);
 | 
			
		||||
 int phy_ethtool_nway_reset(struct net_device *ndev);
 | 
			
		||||
 int phy_package_join(struct phy_device *phydev, int base_addr, size_t priv_size);
 | 
			
		||||
 | 
			
		||||
@ -89,7 +89,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
 | 
			
		||||
 }
 | 
			
		||||
--- a/include/linux/phy.h
 | 
			
		||||
+++ b/include/linux/phy.h
 | 
			
		||||
@@ -1846,7 +1846,7 @@ int genphy_write_mmd_unsupported(struct
 | 
			
		||||
@@ -1880,7 +1880,7 @@ int genphy_write_mmd_unsupported(struct
 | 
			
		||||
 
 | 
			
		||||
 /* Clause 37 */
 | 
			
		||||
 int genphy_c37_config_aneg(struct phy_device *phydev);
 | 
			
		||||
 | 
			
		||||
@ -261,7 +261,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
 }
 | 
			
		||||
--- a/include/linux/phy.h
 | 
			
		||||
+++ b/include/linux/phy.h
 | 
			
		||||
@@ -972,7 +972,8 @@ struct phy_driver {
 | 
			
		||||
@@ -1003,7 +1003,8 @@ struct phy_driver {
 | 
			
		||||
 	 * driver for the given phydev.	 If NULL, matching is based on
 | 
			
		||||
 	 * phy_id and phy_id_mask.
 | 
			
		||||
 	 */
 | 
			
		||||
 | 
			
		||||
@ -97,7 +97,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
 static ssize_t
 | 
			
		||||
--- a/include/linux/phy.h
 | 
			
		||||
+++ b/include/linux/phy.h
 | 
			
		||||
@@ -1812,6 +1812,9 @@ char *phy_attached_info_irq(struct phy_d
 | 
			
		||||
@@ -1846,6 +1846,9 @@ char *phy_attached_info_irq(struct phy_d
 | 
			
		||||
 	__malloc;
 | 
			
		||||
 void phy_attached_info(struct phy_device *phydev);
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
@ -60,7 +60,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
 		cdev->brightness_set_blocking = phy_led_set_brightness;
 | 
			
		||||
--- a/include/linux/phy.h
 | 
			
		||||
+++ b/include/linux/phy.h
 | 
			
		||||
@@ -867,6 +867,15 @@ struct phy_led {
 | 
			
		||||
@@ -885,6 +885,15 @@ struct phy_led {
 | 
			
		||||
 
 | 
			
		||||
 #define to_phy_led(d) container_of(d, struct phy_led, led_cdev)
 | 
			
		||||
 
 | 
			
		||||
@ -76,7 +76,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
 /**
 | 
			
		||||
  * struct phy_driver - Driver structure for a particular PHY type
 | 
			
		||||
  *
 | 
			
		||||
@@ -1144,6 +1153,19 @@ struct phy_driver {
 | 
			
		||||
@@ -1175,6 +1184,19 @@ struct phy_driver {
 | 
			
		||||
 	int (*led_hw_control_get)(struct phy_device *dev, u8 index,
 | 
			
		||||
 				  unsigned long *rules);
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
@ -39,7 +39,7 @@ Signed-off-by: Paolo Abeni <pabeni@redhat.com>
 | 
			
		||||
 		if (!phydev->drv->led_polarity_set)
 | 
			
		||||
--- a/include/linux/phy.h
 | 
			
		||||
+++ b/include/linux/phy.h
 | 
			
		||||
@@ -869,8 +869,9 @@ struct phy_led {
 | 
			
		||||
@@ -887,8 +887,9 @@ struct phy_led {
 | 
			
		||||
 
 | 
			
		||||
 /* Modes for PHY LED configuration */
 | 
			
		||||
 enum phy_led_modes {
 | 
			
		||||
 | 
			
		||||
@ -17,7 +17,7 @@ Signed-off-by: Paolo Abeni <pabeni@redhat.com>
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -712,18 +712,16 @@ static int phylink_validate_mask(struct
 | 
			
		||||
@@ -732,18 +732,16 @@ static int phylink_validate_mask(struct
 | 
			
		||||
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(all_s) = { 0, };
 | 
			
		||||
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(s);
 | 
			
		||||
 	struct phylink_link_state t;
 | 
			
		||||
 | 
			
		||||
@ -17,7 +17,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -704,26 +704,44 @@ static int phylink_validate_mac_and_pcs(
 | 
			
		||||
@@ -724,26 +724,44 @@ static int phylink_validate_mac_and_pcs(
 | 
			
		||||
 	return phylink_is_empty_linkmode(supported) ? -EINVAL : 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
@ -17,7 +17,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -704,7 +704,7 @@ static int phylink_validate_mac_and_pcs(
 | 
			
		||||
@@ -724,7 +724,7 @@ static int phylink_validate_mac_and_pcs(
 | 
			
		||||
 	return phylink_is_empty_linkmode(supported) ? -EINVAL : 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@ -26,7 +26,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
 				 const unsigned long *supported,
 | 
			
		||||
 				 const struct phylink_link_state *state,
 | 
			
		||||
 				 phy_interface_t interface,
 | 
			
		||||
@@ -719,6 +719,9 @@ static void phylink_validate_one(struct
 | 
			
		||||
@@ -739,6 +739,9 @@ static void phylink_validate_one(struct
 | 
			
		||||
 	tmp_state = *state;
 | 
			
		||||
 	tmp_state.interface = interface;
 | 
			
		||||
 
 | 
			
		||||
@ -36,7 +36,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
 	if (!phylink_validate_mac_and_pcs(pl, tmp_supported, &tmp_state)) {
 | 
			
		||||
 		phylink_dbg(pl, " interface %u (%s) rate match %s supports %*pbl\n",
 | 
			
		||||
 			    interface, phy_modes(interface),
 | 
			
		||||
@@ -740,7 +743,7 @@ static int phylink_validate_mask(struct
 | 
			
		||||
@@ -760,7 +763,7 @@ static int phylink_validate_mask(struct
 | 
			
		||||
 	int interface;
 | 
			
		||||
 
 | 
			
		||||
 	for_each_set_bit(interface, interfaces, PHY_INTERFACE_MODE_MAX)
 | 
			
		||||
 | 
			
		||||
@ -17,7 +17,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -734,7 +734,8 @@ static void phylink_validate_one(struct
 | 
			
		||||
@@ -754,7 +754,8 @@ static void phylink_validate_one(struct
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@ -27,7 +27,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
 				 struct phylink_link_state *state,
 | 
			
		||||
 				 const unsigned long *interfaces)
 | 
			
		||||
 {
 | 
			
		||||
@@ -743,7 +744,7 @@ static int phylink_validate_mask(struct
 | 
			
		||||
@@ -763,7 +764,7 @@ static int phylink_validate_mask(struct
 | 
			
		||||
 	int interface;
 | 
			
		||||
 
 | 
			
		||||
 	for_each_set_bit(interface, interfaces, PHY_INTERFACE_MODE_MAX)
 | 
			
		||||
@ -36,7 +36,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
 				     all_s, all_adv);
 | 
			
		||||
 
 | 
			
		||||
 	linkmode_copy(supported, all_s);
 | 
			
		||||
@@ -758,7 +759,8 @@ static int phylink_validate(struct phyli
 | 
			
		||||
@@ -778,7 +779,8 @@ static int phylink_validate(struct phyli
 | 
			
		||||
 	const unsigned long *interfaces = pl->config->supported_interfaces;
 | 
			
		||||
 
 | 
			
		||||
 	if (state->interface == PHY_INTERFACE_MODE_NA)
 | 
			
		||||
@ -46,7 +46,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
 
 | 
			
		||||
 	if (!test_bit(state->interface, interfaces))
 | 
			
		||||
 		return -EINVAL;
 | 
			
		||||
@@ -3194,7 +3196,8 @@ static int phylink_sfp_config_optical(st
 | 
			
		||||
@@ -3465,7 +3467,8 @@ static int phylink_sfp_config_optical(st
 | 
			
		||||
 	/* For all the interfaces that are supported, reduce the sfp_support
 | 
			
		||||
 	 * mask to only those link modes that can be supported.
 | 
			
		||||
 	 */
 | 
			
		||||
 | 
			
		||||
@ -22,7 +22,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -1775,6 +1775,35 @@ static void phylink_phy_change(struct ph
 | 
			
		||||
@@ -2019,6 +2019,35 @@ static void phylink_phy_change(struct ph
 | 
			
		||||
 		    phylink_pause_to_str(pl->phy_state.pause));
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@ -58,7 +58,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
 static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy,
 | 
			
		||||
 			       phy_interface_t interface)
 | 
			
		||||
 {
 | 
			
		||||
@@ -1795,32 +1824,9 @@ static int phylink_bringup_phy(struct ph
 | 
			
		||||
@@ -2039,32 +2068,9 @@ static int phylink_bringup_phy(struct ph
 | 
			
		||||
 	memset(&config, 0, sizeof(config));
 | 
			
		||||
 	linkmode_copy(supported, phy->supported);
 | 
			
		||||
 	linkmode_copy(config.advertising, phy->advertising);
 | 
			
		||||
 | 
			
		||||
@ -40,7 +40,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -121,6 +121,19 @@ do {									\
 | 
			
		||||
@@ -123,6 +123,19 @@ do {									\
 | 
			
		||||
 })
 | 
			
		||||
 #endif
 | 
			
		||||
 
 | 
			
		||||
@ -60,7 +60,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
 /**
 | 
			
		||||
  * phylink_set_port_modes() - set the port type modes in the ethtool mask
 | 
			
		||||
  * @mask: ethtool link mode mask
 | 
			
		||||
@@ -1779,6 +1792,47 @@ static int phylink_validate_phy(struct p
 | 
			
		||||
@@ -2023,6 +2036,47 @@ static int phylink_validate_phy(struct p
 | 
			
		||||
 				unsigned long *supported,
 | 
			
		||||
 				struct phylink_link_state *state)
 | 
			
		||||
 {
 | 
			
		||||
@ -108,7 +108,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
 	/* Check whether we would use rate matching for the proposed interface
 | 
			
		||||
 	 * mode.
 | 
			
		||||
 	 */
 | 
			
		||||
@@ -3047,19 +3101,6 @@ static void phylink_sfp_detach(void *ups
 | 
			
		||||
@@ -3318,19 +3372,6 @@ static void phylink_sfp_detach(void *ups
 | 
			
		||||
 	pl->netdev->sfp_bus = NULL;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
@ -13,7 +13,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/pcs/pcs-mtk-lynxi.c
 | 
			
		||||
+++ b/drivers/net/pcs/pcs-mtk-lynxi.c
 | 
			
		||||
@@ -114,14 +114,23 @@ static void mtk_pcs_lynxi_get_state(stru
 | 
			
		||||
@@ -129,14 +129,23 @@ static void mtk_pcs_lynxi_get_state(stru
 | 
			
		||||
 				    struct phylink_link_state *state)
 | 
			
		||||
 {
 | 
			
		||||
 	struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs);
 | 
			
		||||
@ -41,7 +41,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void mtk_sgmii_reset(struct mtk_pcs_lynxi *mpcs)
 | 
			
		||||
@@ -142,7 +151,7 @@ static int mtk_pcs_lynxi_config(struct p
 | 
			
		||||
@@ -157,7 +166,7 @@ static int mtk_pcs_lynxi_config(struct p
 | 
			
		||||
 {
 | 
			
		||||
 	struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs);
 | 
			
		||||
 	bool mode_changed = false, changed;
 | 
			
		||||
@ -50,7 +50,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
			
		||||
 	int advertise, link_timer;
 | 
			
		||||
 
 | 
			
		||||
 	advertise = phylink_mii_c22_pcs_encode_advertisement(interface,
 | 
			
		||||
@@ -165,9 +174,8 @@ static int mtk_pcs_lynxi_config(struct p
 | 
			
		||||
@@ -180,9 +189,8 @@ static int mtk_pcs_lynxi_config(struct p
 | 
			
		||||
 	if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
 | 
			
		||||
 		if (interface == PHY_INTERFACE_MODE_SGMII)
 | 
			
		||||
 			sgm_mode |= SGMII_SPEED_DUPLEX_AN;
 | 
			
		||||
 | 
			
		||||
@ -13,7 +13,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/pcs/pcs-mtk-lynxi.c
 | 
			
		||||
+++ b/drivers/net/pcs/pcs-mtk-lynxi.c
 | 
			
		||||
@@ -114,14 +114,23 @@ static void mtk_pcs_lynxi_get_state(stru
 | 
			
		||||
@@ -129,14 +129,23 @@ static void mtk_pcs_lynxi_get_state(stru
 | 
			
		||||
 				    struct phylink_link_state *state)
 | 
			
		||||
 {
 | 
			
		||||
 	struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs);
 | 
			
		||||
@ -41,7 +41,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 static void mtk_sgmii_reset(struct mtk_pcs_lynxi *mpcs)
 | 
			
		||||
@@ -142,7 +151,7 @@ static int mtk_pcs_lynxi_config(struct p
 | 
			
		||||
@@ -157,7 +166,7 @@ static int mtk_pcs_lynxi_config(struct p
 | 
			
		||||
 {
 | 
			
		||||
 	struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs);
 | 
			
		||||
 	bool mode_changed = false, changed;
 | 
			
		||||
@ -50,7 +50,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
			
		||||
 	int advertise, link_timer;
 | 
			
		||||
 
 | 
			
		||||
 	advertise = phylink_mii_c22_pcs_encode_advertisement(interface,
 | 
			
		||||
@@ -165,9 +174,8 @@ static int mtk_pcs_lynxi_config(struct p
 | 
			
		||||
@@ -180,9 +189,8 @@ static int mtk_pcs_lynxi_config(struct p
 | 
			
		||||
 	if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
 | 
			
		||||
 		if (interface == PHY_INTERFACE_MODE_SGMII)
 | 
			
		||||
 			sgm_mode |= SGMII_SPEED_DUPLEX_AN;
 | 
			
		||||
 | 
			
		||||
@ -23,7 +23,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
 | 
			
		||||
 			sysfs_remove_link(&dev->dev.kobj, "phydev");
 | 
			
		||||
--- a/include/linux/phy.h
 | 
			
		||||
+++ b/include/linux/phy.h
 | 
			
		||||
@@ -996,6 +996,12 @@ struct phy_driver {
 | 
			
		||||
@@ -1027,6 +1027,12 @@ struct phy_driver {
 | 
			
		||||
 	/** @handle_interrupt: Override default interrupt handling */
 | 
			
		||||
 	irqreturn_t (*handle_interrupt)(struct phy_device *phydev);
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
@ -20,7 +20,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -2086,7 +2086,7 @@ int phylink_fwnode_phy_connect(struct ph
 | 
			
		||||
@@ -2264,7 +2264,7 @@ int phylink_fwnode_phy_connect(struct ph
 | 
			
		||||
 {
 | 
			
		||||
 	struct fwnode_handle *phy_fwnode;
 | 
			
		||||
 	struct phy_device *phy_dev;
 | 
			
		||||
@ -29,7 +29,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
			
		||||
 
 | 
			
		||||
 	/* Fixed links and 802.3z are handled without needing a PHY */
 | 
			
		||||
 	if (pl->cfg_link_an_mode == MLO_AN_FIXED ||
 | 
			
		||||
@@ -2116,6 +2116,25 @@ int phylink_fwnode_phy_connect(struct ph
 | 
			
		||||
@@ -2294,6 +2294,25 @@ int phylink_fwnode_phy_connect(struct ph
 | 
			
		||||
 	if (pl->config->mac_requires_rxc)
 | 
			
		||||
 		flags |= PHY_F_RXC_ALWAYS_ON;
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
@ -79,7 +79,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
			
		||||
 static struct mtk_pcs_lynxi *pcs_to_mtk_pcs_lynxi(struct phylink_pcs *pcs)
 | 
			
		||||
 {
 | 
			
		||||
 	return container_of(pcs, struct mtk_pcs_lynxi, pcs);
 | 
			
		||||
@@ -102,6 +124,17 @@ static void mtk_pcs_lynxi_get_state(stru
 | 
			
		||||
@@ -117,6 +139,17 @@ static void mtk_pcs_lynxi_get_state(stru
 | 
			
		||||
 					 FIELD_GET(SGMII_LPA, adv));
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@ -97,7 +97,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
			
		||||
 static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int neg_mode,
 | 
			
		||||
 				phy_interface_t interface,
 | 
			
		||||
 				const unsigned long *advertising,
 | 
			
		||||
@@ -147,6 +180,7 @@ static int mtk_pcs_lynxi_config(struct p
 | 
			
		||||
@@ -162,6 +195,7 @@ static int mtk_pcs_lynxi_config(struct p
 | 
			
		||||
 				SGMII_PHYA_PWD);
 | 
			
		||||
 
 | 
			
		||||
 		/* Reset SGMII PCS state */
 | 
			
		||||
@ -105,7 +105,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
			
		||||
 		regmap_set_bits(mpcs->regmap, SGMSYS_RESERVED_0,
 | 
			
		||||
 				SGMII_SW_RESET);
 | 
			
		||||
 
 | 
			
		||||
@@ -233,10 +267,29 @@ static void mtk_pcs_lynxi_link_up(struct
 | 
			
		||||
@@ -248,10 +282,29 @@ static void mtk_pcs_lynxi_link_up(struct
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@ -135,7 +135,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
			
		||||
 	mpcs->interface = PHY_INTERFACE_MODE_NA;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -246,11 +299,12 @@ static const struct phylink_pcs_ops mtk_
 | 
			
		||||
@@ -262,11 +315,12 @@ static const struct phylink_pcs_ops mtk_
 | 
			
		||||
 	.pcs_an_restart = mtk_pcs_lynxi_restart_an,
 | 
			
		||||
 	.pcs_link_up = mtk_pcs_lynxi_link_up,
 | 
			
		||||
 	.pcs_disable = mtk_pcs_lynxi_disable,
 | 
			
		||||
@ -151,7 +151,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
			
		||||
 {
 | 
			
		||||
 	struct mtk_pcs_lynxi *mpcs;
 | 
			
		||||
 	u32 id, ver;
 | 
			
		||||
@@ -258,29 +312,33 @@ struct phylink_pcs *mtk_pcs_lynxi_create
 | 
			
		||||
@@ -274,29 +328,33 @@ struct phylink_pcs *mtk_pcs_lynxi_create
 | 
			
		||||
 
 | 
			
		||||
 	ret = regmap_read(regmap, SGMSYS_PCS_DEVICE_ID, &id);
 | 
			
		||||
 	if (ret < 0)
 | 
			
		||||
@ -192,7 +192,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
			
		||||
 
 | 
			
		||||
 	mpcs->ana_rgc3 = ana_rgc3;
 | 
			
		||||
 	mpcs->regmap = regmap;
 | 
			
		||||
@@ -291,6 +349,13 @@ struct phylink_pcs *mtk_pcs_lynxi_create
 | 
			
		||||
@@ -307,6 +365,13 @@ struct phylink_pcs *mtk_pcs_lynxi_create
 | 
			
		||||
 	mpcs->interface = PHY_INTERFACE_MODE_NA;
 | 
			
		||||
 
 | 
			
		||||
 	return &mpcs->pcs;
 | 
			
		||||
@ -206,7 +206,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
			
		||||
 }
 | 
			
		||||
 EXPORT_SYMBOL(mtk_pcs_lynxi_create);
 | 
			
		||||
 
 | 
			
		||||
@@ -303,5 +368,142 @@ void mtk_pcs_lynxi_destroy(struct phylin
 | 
			
		||||
@@ -319,5 +384,142 @@ void mtk_pcs_lynxi_destroy(struct phylin
 | 
			
		||||
 }
 | 
			
		||||
 EXPORT_SYMBOL(mtk_pcs_lynxi_destroy);
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
@ -23,7 +23,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
 | 
			
		||||
 			sysfs_remove_link(&dev->dev.kobj, "phydev");
 | 
			
		||||
--- a/include/linux/phy.h
 | 
			
		||||
+++ b/include/linux/phy.h
 | 
			
		||||
@@ -977,6 +977,12 @@ struct phy_driver {
 | 
			
		||||
@@ -1008,6 +1008,12 @@ struct phy_driver {
 | 
			
		||||
 	/** @handle_interrupt: Override default interrupt handling */
 | 
			
		||||
 	irqreturn_t (*handle_interrupt)(struct phy_device *phydev);
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
@ -20,7 +20,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
			
		||||
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -2017,7 +2017,7 @@ int phylink_fwnode_phy_connect(struct ph
 | 
			
		||||
@@ -2261,7 +2261,7 @@ int phylink_fwnode_phy_connect(struct ph
 | 
			
		||||
 {
 | 
			
		||||
 	struct fwnode_handle *phy_fwnode;
 | 
			
		||||
 	struct phy_device *phy_dev;
 | 
			
		||||
@ -29,7 +29,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
			
		||||
 
 | 
			
		||||
 	/* Fixed links and 802.3z are handled without needing a PHY */
 | 
			
		||||
 	if (pl->cfg_link_an_mode == MLO_AN_FIXED ||
 | 
			
		||||
@@ -2044,6 +2044,25 @@ int phylink_fwnode_phy_connect(struct ph
 | 
			
		||||
@@ -2288,6 +2288,25 @@ int phylink_fwnode_phy_connect(struct ph
 | 
			
		||||
 		pl->link_config.interface = pl->link_interface;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
@ -79,7 +79,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
			
		||||
 static struct mtk_pcs_lynxi *pcs_to_mtk_pcs_lynxi(struct phylink_pcs *pcs)
 | 
			
		||||
 {
 | 
			
		||||
 	return container_of(pcs, struct mtk_pcs_lynxi, pcs);
 | 
			
		||||
@@ -102,6 +124,17 @@ static void mtk_pcs_lynxi_get_state(stru
 | 
			
		||||
@@ -117,6 +139,17 @@ static void mtk_pcs_lynxi_get_state(stru
 | 
			
		||||
 					 FIELD_GET(SGMII_LPA, adv));
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@ -97,7 +97,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
			
		||||
 static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int neg_mode,
 | 
			
		||||
 				phy_interface_t interface,
 | 
			
		||||
 				const unsigned long *advertising,
 | 
			
		||||
@@ -147,6 +180,7 @@ static int mtk_pcs_lynxi_config(struct p
 | 
			
		||||
@@ -162,6 +195,7 @@ static int mtk_pcs_lynxi_config(struct p
 | 
			
		||||
 				SGMII_PHYA_PWD);
 | 
			
		||||
 
 | 
			
		||||
 		/* Reset SGMII PCS state */
 | 
			
		||||
@ -105,7 +105,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
			
		||||
 		regmap_set_bits(mpcs->regmap, SGMSYS_RESERVED_0,
 | 
			
		||||
 				SGMII_SW_RESET);
 | 
			
		||||
 
 | 
			
		||||
@@ -233,10 +267,29 @@ static void mtk_pcs_lynxi_link_up(struct
 | 
			
		||||
@@ -248,10 +282,29 @@ static void mtk_pcs_lynxi_link_up(struct
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@ -135,7 +135,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
			
		||||
 	mpcs->interface = PHY_INTERFACE_MODE_NA;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -246,11 +299,12 @@ static const struct phylink_pcs_ops mtk_
 | 
			
		||||
@@ -262,11 +315,12 @@ static const struct phylink_pcs_ops mtk_
 | 
			
		||||
 	.pcs_an_restart = mtk_pcs_lynxi_restart_an,
 | 
			
		||||
 	.pcs_link_up = mtk_pcs_lynxi_link_up,
 | 
			
		||||
 	.pcs_disable = mtk_pcs_lynxi_disable,
 | 
			
		||||
@ -151,7 +151,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
			
		||||
 {
 | 
			
		||||
 	struct mtk_pcs_lynxi *mpcs;
 | 
			
		||||
 	u32 id, ver;
 | 
			
		||||
@@ -258,29 +312,33 @@ struct phylink_pcs *mtk_pcs_lynxi_create
 | 
			
		||||
@@ -274,29 +328,33 @@ struct phylink_pcs *mtk_pcs_lynxi_create
 | 
			
		||||
 
 | 
			
		||||
 	ret = regmap_read(regmap, SGMSYS_PCS_DEVICE_ID, &id);
 | 
			
		||||
 	if (ret < 0)
 | 
			
		||||
@ -192,7 +192,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
			
		||||
 
 | 
			
		||||
 	mpcs->ana_rgc3 = ana_rgc3;
 | 
			
		||||
 	mpcs->regmap = regmap;
 | 
			
		||||
@@ -291,6 +349,13 @@ struct phylink_pcs *mtk_pcs_lynxi_create
 | 
			
		||||
@@ -307,6 +365,13 @@ struct phylink_pcs *mtk_pcs_lynxi_create
 | 
			
		||||
 	mpcs->interface = PHY_INTERFACE_MODE_NA;
 | 
			
		||||
 
 | 
			
		||||
 	return &mpcs->pcs;
 | 
			
		||||
@ -206,7 +206,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
			
		||||
 }
 | 
			
		||||
 EXPORT_SYMBOL(mtk_pcs_lynxi_create);
 | 
			
		||||
 
 | 
			
		||||
@@ -303,4 +368,142 @@ void mtk_pcs_lynxi_destroy(struct phylin
 | 
			
		||||
@@ -319,4 +384,142 @@ void mtk_pcs_lynxi_destroy(struct phylin
 | 
			
		||||
 }
 | 
			
		||||
 EXPORT_SYMBOL(mtk_pcs_lynxi_destroy);
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
@ -36,7 +36,7 @@ Signed-off-by: Bhaskar Upadhaya <Bhaskar.Upadhaya@nxp.com>
 | 
			
		||||
 	case PHY_INTERFACE_MODE_QUSGMII:
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -230,6 +230,7 @@ static int phylink_interface_max_speed(p
 | 
			
		||||
@@ -250,6 +250,7 @@ static int phylink_interface_max_speed(p
 | 
			
		||||
 	case PHY_INTERFACE_MODE_GMII:
 | 
			
		||||
 		return SPEED_1000;
 | 
			
		||||
 
 | 
			
		||||
@ -44,7 +44,7 @@ Signed-off-by: Bhaskar Upadhaya <Bhaskar.Upadhaya@nxp.com>
 | 
			
		||||
 	case PHY_INTERFACE_MODE_2500BASEX:
 | 
			
		||||
 	case PHY_INTERFACE_MODE_10G_QXGMII:
 | 
			
		||||
 		return SPEED_2500;
 | 
			
		||||
@@ -544,6 +545,7 @@ static unsigned long phylink_get_capabil
 | 
			
		||||
@@ -564,6 +565,7 @@ static unsigned long phylink_get_capabil
 | 
			
		||||
 		break;
 | 
			
		||||
 
 | 
			
		||||
 	case PHY_INTERFACE_MODE_2500BASEX:
 | 
			
		||||
 | 
			
		||||
@ -25,7 +25,7 @@ Signed-off-by: Bhaskar Upadhaya <Bhaskar.Upadhaya@nxp.com>
 | 
			
		||||
 	case PHY_INTERFACE_MODE_QUSGMII:
 | 
			
		||||
--- a/drivers/net/phy/phylink.c
 | 
			
		||||
+++ b/drivers/net/phy/phylink.c
 | 
			
		||||
@@ -231,6 +231,7 @@ static int phylink_interface_max_speed(p
 | 
			
		||||
@@ -251,6 +251,7 @@ static int phylink_interface_max_speed(p
 | 
			
		||||
 		return SPEED_1000;
 | 
			
		||||
 
 | 
			
		||||
 	case PHY_INTERFACE_MODE_2500BASEX:
 | 
			
		||||
@ -33,7 +33,7 @@ Signed-off-by: Bhaskar Upadhaya <Bhaskar.Upadhaya@nxp.com>
 | 
			
		||||
 		return SPEED_2500;
 | 
			
		||||
 
 | 
			
		||||
 	case PHY_INTERFACE_MODE_5GBASER:
 | 
			
		||||
@@ -539,6 +540,7 @@ unsigned long phylink_get_capabilities(p
 | 
			
		||||
@@ -559,6 +560,7 @@ unsigned long phylink_get_capabilities(p
 | 
			
		||||
 		break;
 | 
			
		||||
 
 | 
			
		||||
 	case PHY_INTERFACE_MODE_2500BASEX:
 | 
			
		||||
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -14,7 +14,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 | 
			
		||||
---
 | 
			
		||||
--- a/drivers/net/ethernet/marvell/mvneta.c
 | 
			
		||||
+++ b/drivers/net/ethernet/marvell/mvneta.c
 | 
			
		||||
@@ -5296,6 +5296,16 @@ static int mvneta_setup_tc(struct net_de
 | 
			
		||||
@@ -5303,6 +5303,16 @@ static int mvneta_setup_tc(struct net_de
 | 
			
		||||
 	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@ -31,7 +31,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 | 
			
		||||
 static const struct net_device_ops mvneta_netdev_ops = {
 | 
			
		||||
 	.ndo_open            = mvneta_open,
 | 
			
		||||
 	.ndo_stop            = mvneta_stop,
 | 
			
		||||
@@ -5306,6 +5316,9 @@ static const struct net_device_ops mvnet
 | 
			
		||||
@@ -5313,6 +5323,9 @@ static const struct net_device_ops mvnet
 | 
			
		||||
 	.ndo_fix_features    = mvneta_fix_features,
 | 
			
		||||
 	.ndo_get_stats64     = mvneta_get_stats64,
 | 
			
		||||
 	.ndo_eth_ioctl        = mvneta_ioctl,
 | 
			
		||||
 | 
			
		||||
@ -170,7 +170,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
 | 
			
		||||
 	/* This is optional functionality. If not supported, we may get an error
 | 
			
		||||
--- a/include/linux/phy.h
 | 
			
		||||
+++ b/include/linux/phy.h
 | 
			
		||||
@@ -1897,6 +1897,7 @@ int genphy_c45_an_config_aneg(struct phy
 | 
			
		||||
@@ -1931,6 +1931,7 @@ int genphy_c45_an_config_aneg(struct phy
 | 
			
		||||
 int genphy_c45_an_disable_aneg(struct phy_device *phydev);
 | 
			
		||||
 int genphy_c45_read_mdix(struct phy_device *phydev);
 | 
			
		||||
 int genphy_c45_pma_read_abilities(struct phy_device *phydev);
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user