[openwrt/openwrt] generic: backport phylink patches for PCS/PHY caps OPs

LEDE Commits lede-commits at lists.infradead.org
Wed Oct 22 03:30:17 PDT 2025


ansuel pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/813ecda1f387e529bddb059acc7cef27bf821537

commit 813ecda1f387e529bddb059acc7cef27bf821537
Author: Christian Marangi <ansuelsmth at gmail.com>
AuthorDate: Mon Oct 20 01:36:34 2025 +0200

    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 at gmail.com>
---
 ...-phylink-move-manual-flow-control-setting.patch |   41 +
 ...-move-MLO_AN_FIXED-resolve-handling-to-if.patch |   42 +
 ...-move-MLO_AN_PHY-resolve-handling-to-if-s.patch |   37 +
 ...-remove-switch-statement-in-resolve-handl.patch |  127 ++
 ...6.13-net-phylink-clean-up-phylink_resolve.patch |   85 ++
 ...-pass-phylink-and-pcs-into-phylink_pcs_ne.patch |   95 ++
 ...-split-cur_link_an_mode-into-requested-an.patch |  290 +++++
 ...hylink-add-debug-for-phylink_major_config.patch |   66 ++
 .../601-04-v6.14-net-phy-add-phy_inband_caps.patch |  118 ++
 ...bcm84881-implement-phy_inband_caps-method.patch |   41 +
 ...-marvell-implement-phy_inband_caps-method.patch |   63 +
 ...01-07-v6.14-net-phy-add-phy_config_inband.patch |   79 ++
 ...hy-marvell-implement-config_inband-method.patch |   77 ++
 ...14-net-phylink-add-pcs_inband_caps-method.patch |  159 +++
 ...t-mvneta-implement-pcs_inband_caps-method.patch |   64 +
 ...et-mvpp2-implement-pcs_inband_caps-method.patch |   62 +
 ...k-add-negotiation-of-in-band-capabilities.patch |  228 ++++
 ...-net-phylink-remove-phylink_phy_no_inband.patch |  110 ++
 ...pcs-lynx-implement-pcs_inband_caps-method.patch |   53 +
 ...-mtk-lynxi-implement-pcs_inband_caps-meth.patch |   47 +
 ...pcs-xpcs-implement-pcs_inband_caps-method.patch |   58 +
 ...14-net-phy-Constify-struct-mdio_device_id.patch |    4 +-
 ...support-active-high-property-for-PHY-LEDs.patch |    2 +-
 ...y-pass-PHY-driver-to-.match_phy_device-OP.patch |    2 +-
 ...net-phy-introduce-genphy_match_phy_device.patch |    2 +-
 ...-phylink-move-manual-flow-control-setting.patch |   41 +
 ...-move-MLO_AN_FIXED-resolve-handling-to-if.patch |   42 +
 ...-move-MLO_AN_PHY-resolve-handling-to-if-s.patch |   37 +
 ...-remove-switch-statement-in-resolve-handl.patch |  127 ++
 ...6.13-net-phylink-clean-up-phylink_resolve.patch |   85 ++
 ...-move-phylink_pcs_neg_mode-into-phylink.c.patch |  166 +++
 ...-pass-phylink-and-pcs-into-phylink_pcs_ne.patch |   95 ++
 ...-split-cur_link_an_mode-into-requested-an.patch |  281 +++++
 ...hylink-add-debug-for-phylink_major_config.patch |   66 ++
 .../606-04-v6.14-net-phy-add-phy_inband_caps.patch |  118 ++
 ...bcm84881-implement-phy_inband_caps-method.patch |   41 +
 ...-marvell-implement-phy_inband_caps-method.patch |   63 +
 ...06-07-v6.14-net-phy-add-phy_config_inband.patch |   79 ++
 ...hy-marvell-implement-config_inband-method.patch |   77 ++
 ...14-net-phylink-add-pcs_inband_caps-method.patch |  159 +++
 ...t-mvneta-implement-pcs_inband_caps-method.patch |   64 +
 ...et-mvpp2-implement-pcs_inband_caps-method.patch |   62 +
 ...k-add-negotiation-of-in-band-capabilities.patch |  228 ++++
 ...-net-phylink-remove-phylink_phy_no_inband.patch |  110 ++
 ...pcs-lynx-implement-pcs_inband_caps-method.patch |   53 +
 ...-mtk-lynxi-implement-pcs_inband_caps-meth.patch |   47 +
 ...pcs-xpcs-implement-pcs_inband_caps-method.patch |   58 +
 ...end-PHY-package-API-to-support-multiple-g.patch |    4 +-
 ...dd-support-for-PHY-package-MMD-read-write.patch |    2 +-
 ...t-phy-add-devm-of_phy_package_join-helper.patch |    2 +-
 ...vide-whether-link-has-changed-in-c37_read.patch |    2 +-
 ...y-pass-PHY-driver-to-.match_phy_device-OP.patch |    2 +-
 ...net-phy-introduce-genphy_match_phy_device.patch |    2 +-
 ...y-add-support-for-PHY-LEDs-polarity-modes.patch |    4 +-
 ...support-active-high-property-for-PHY-LEDs.patch |    2 +-
 ...-02-v6.8-net-phylink-use-for_each_set_bit.patch |    2 +-
 ...hylink-split-out-per-interface-validation.patch |    2 +-
 ...hylink-pass-PHY-into-phylink_validate_one.patch |    6 +-
 ...ylink-pass-PHY-into-phylink_validate_mask.patch |    8 +-
 ...-split-out-PHY-validation-from-phylink_br.patch |    4 +-
 ...-use-the-PHY-s-possible_interfaces-if-pop.patch |    6 +-
 ...-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch |    6 +-
 ...-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch |    6 +-
 ...-add-detach-callback-to-struct-phy_driver.patch |    2 +-
 ...pulate-host_interfaces-when-attaching-PHY.patch |    4 +-
 ...-mtk-lynxi-add-platform-driver-for-MT7988.patch |   14 +-
 ...-add-detach-callback-to-struct-phy_driver.patch |    2 +-
 ...pulate-host_interfaces-when-attaching-PHY.patch |    4 +-
 ...-mtk-lynxi-add-platform-driver-for-MT7988.patch |   14 +-
 .../702-phy-Add-2.5G-SGMII-interface-mode.patch    |    4 +-
 .../702-phy-Add-2.5G-SGMII-interface-mode.patch    |    4 +-
 ...t-add-negotiation-of-in-band-capabilities.patch | 1242 --------------------
 .../700-mvneta-tx-queue-workaround.patch           |    4 +-
 ...-add-genphy_c45_pma_read_ext_abilities-fu.patch |    2 +-
 74 files changed, 4103 insertions(+), 1304 deletions(-)

diff --git a/target/linux/generic/backport-6.12/600-01-v6.13-net-phylink-move-manual-flow-control-setting.patch b/target/linux/generic/backport-6.12/600-01-v6.13-net-phylink-move-manual-flow-control-setting.patch
new file mode 100644
index 0000000000..a9b86c2508
--- /dev/null
+++ b/target/linux/generic/backport-6.12/600-01-v6.13-net-phylink-move-manual-flow-control-setting.patch
@@ -0,0 +1,41 @@
+From 8cc5f4cb94c0b1c7c1ba8013c14fd02ffb1a25f3 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at armlinux.org.uk>
+Link: https://patch.msgid.link/E1t9RQe-002Feh-T1@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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
diff --git a/target/linux/generic/backport-6.12/600-02-v6.13-net-phylink-move-MLO_AN_FIXED-resolve-handling-to-if.patch b/target/linux/generic/backport-6.12/600-02-v6.13-net-phylink-move-MLO_AN_FIXED-resolve-handling-to-if.patch
new file mode 100644
index 0000000000..7ff091e85f
--- /dev/null
+++ b/target/linux/generic/backport-6.12/600-02-v6.13-net-phylink-move-MLO_AN_FIXED-resolve-handling-to-if.patch
@@ -0,0 +1,42 @@
+From 92abfcb4ced482afbe65d18980e6734fe1e62a34 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at armlinux.org.uk>
+Link: https://patch.msgid.link/E1t9RQk-002Fen-1A@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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);
+ 
diff --git a/target/linux/generic/backport-6.12/600-03-v6.13-net-phylink-move-MLO_AN_PHY-resolve-handling-to-if-s.patch b/target/linux/generic/backport-6.12/600-03-v6.13-net-phylink-move-MLO_AN_PHY-resolve-handling-to-if-s.patch
new file mode 100644
index 0000000000..76e76fbba1
--- /dev/null
+++ b/target/linux/generic/backport-6.12/600-03-v6.13-net-phylink-move-MLO_AN_PHY-resolve-handling-to-if-s.patch
@@ -0,0 +1,37 @@
+From f0f46c2a3d8ea9d1427298c8103a777d9e616c29 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at armlinux.org.uk>
+Link: https://patch.msgid.link/E1t9RQp-002Fet-5W@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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);
+ 
diff --git a/target/linux/generic/backport-6.12/600-04-v6.13-net-phylink-remove-switch-statement-in-resolve-handl.patch b/target/linux/generic/backport-6.12/600-04-v6.13-net-phylink-remove-switch-statement-in-resolve-handl.patch
new file mode 100644
index 0000000000..989fc10b71
--- /dev/null
+++ b/target/linux/generic/backport-6.12/600-04-v6.13-net-phylink-remove-switch-statement-in-resolve-handl.patch
@@ -0,0 +1,127 @@
+From d1a16dbbd84e02d2a6dcfcb8d5c4b8b2c0289f00 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at armlinux.org.uk>
+Link: https://patch.msgid.link/E1t9RQu-002Fez-AA@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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;
+ 		}
+ 	}
+ 
diff --git a/target/linux/generic/backport-6.12/600-05-v6.13-net-phylink-clean-up-phylink_resolve.patch b/target/linux/generic/backport-6.12/600-05-v6.13-net-phylink-clean-up-phylink_resolve.patch
new file mode 100644
index 0000000000..285eea862e
--- /dev/null
+++ b/target/linux/generic/backport-6.12/600-05-v6.13-net-phylink-clean-up-phylink_resolve.patch
@@ -0,0 +1,85 @@
+From bc08ce37d99a3992e975a0f397503cb23404f25a Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at armlinux.org.uk>
+Link: https://patch.msgid.link/E1t9RQz-002Ff5-EA@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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;
diff --git a/target/linux/generic/backport-6.12/601-01-v6.14-net-phylink-pass-phylink-and-pcs-into-phylink_pcs_ne.patch b/target/linux/generic/backport-6.12/601-01-v6.14-net-phylink-pass-phylink-and-pcs-into-phylink_pcs_ne.patch
new file mode 100644
index 0000000000..6868cd1518
--- /dev/null
+++ b/target/linux/generic/backport-6.12/601-01-v6.14-net-phylink-pass-phylink-and-pcs-into-phylink_pcs_ne.patch
@@ -0,0 +1,95 @@
+From 17ed1911f9c8d4f9af8e13b2c95103ee06dadc0f Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tIUrP-006ITh-6u@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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)
diff --git a/target/linux/generic/backport-6.12/601-02-v6.14-net-phylink-split-cur_link_an_mode-into-requested-an.patch b/target/linux/generic/backport-6.12/601-02-v6.14-net-phylink-split-cur_link_an_mode-into-requested-an.patch
new file mode 100644
index 0000000000..76f4d5a48b
--- /dev/null
+++ b/target/linux/generic/backport-6.12/601-02-v6.14-net-phylink-split-cur_link_an_mode-into-requested-an.patch
@@ -0,0 +1,290 @@
+From 1f92ead7e15003f632b5f138e8138095e0997d3d Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tIUrU-006ITn-Ai@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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;
diff --git a/target/linux/generic/backport-6.12/601-03-v6.14-net-phylink-add-debug-for-phylink_major_config.patch b/target/linux/generic/backport-6.12/601-03-v6.14-net-phylink-add-debug-for-phylink_major_config.patch
new file mode 100644
index 0000000000..ee625c7486
--- /dev/null
+++ b/target/linux/generic/backport-6.12/601-03-v6.14-net-phylink-add-debug-for-phylink_major_config.patch
@@ -0,0 +1,66 @@
+From 4e7d000286fe8e12f2d88032711ffab3ab658b12 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tIUrZ-006ITt-Fa@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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) {
diff --git a/target/linux/generic/backport-6.12/601-04-v6.14-net-phy-add-phy_inband_caps.patch b/target/linux/generic/backport-6.12/601-04-v6.14-net-phy-add-phy_inband_caps.patch
new file mode 100644
index 0000000000..67f4f0be42
--- /dev/null
+++ b/target/linux/generic/backport-6.12/601-04-v6.14-net-phy-add-phy_inband_caps.patch
@@ -0,0 +1,118 @@
+From b4c7698dd95f253c6958d8c6ac219098009bf28a Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tIUre-006ITz-KF@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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);
diff --git a/target/linux/generic/backport-6.12/601-05-v6.14-net-phy-bcm84881-implement-phy_inband_caps-method.patch b/target/linux/generic/backport-6.12/601-05-v6.14-net-phy-bcm84881-implement-phy_inband_caps-method.patch
new file mode 100644
index 0000000000..0ba3cd2802
--- /dev/null
+++ b/target/linux/generic/backport-6.12/601-05-v6.14-net-phy-bcm84881-implement-phy_inband_caps-method.patch
@@ -0,0 +1,41 @@
+From c64c7fa0a774d9da72071a8517e359992baac982 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Acked-by: Florian Fainelli <florian.fainelli at broadcom.com>
+Link: https://patch.msgid.link/E1tIUrj-006IU6-ON@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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,
diff --git a/target/linux/generic/backport-6.12/601-06-v6.14-net-phy-marvell-implement-phy_inband_caps-method.patch b/target/linux/generic/backport-6.12/601-06-v6.14-net-phy-marvell-implement-phy_inband_caps-method.patch
new file mode 100644
index 0000000000..fb5d9c20af
--- /dev/null
+++ b/target/linux/generic/backport-6.12/601-06-v6.14-net-phy-marvell-implement-phy_inband_caps-method.patch
@@ -0,0 +1,63 @@
+From 1c86828dff88e28b8ade6bddeee0163a023faf91 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tIUro-006IUC-Rq@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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,
diff --git a/target/linux/generic/backport-6.12/601-07-v6.14-net-phy-add-phy_config_inband.patch b/target/linux/generic/backport-6.12/601-07-v6.14-net-phy-add-phy_config_inband.patch
new file mode 100644
index 0000000000..99f11fe07b
--- /dev/null
+++ b/target/linux/generic/backport-6.12/601-07-v6.14-net-phy-add-phy_config_inband.patch
@@ -0,0 +1,79 @@
+From 5d58a890c02770ba8d790b1f3c6e8c0e20514dc2 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tIUru-006IUI-08@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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);
diff --git a/target/linux/generic/backport-6.12/601-08-v6.14-net-phy-marvell-implement-config_inband-method.patch b/target/linux/generic/backport-6.12/601-08-v6.14-net-phy-marvell-implement-config_inband-method.patch
new file mode 100644
index 0000000000..00788d42fc
--- /dev/null
+++ b/target/linux/generic/backport-6.12/601-08-v6.14-net-phy-marvell-implement-config_inband-method.patch
@@ -0,0 +1,77 @@
+From a219912e0fec73c346e64ef47013cb2e152f88fc Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tIUrz-006IUO-3r@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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,
diff --git a/target/linux/generic/backport-6.12/601-09-v6.14-net-phylink-add-pcs_inband_caps-method.patch b/target/linux/generic/backport-6.12/601-09-v6.14-net-phylink-add-pcs_inband_caps-method.patch
new file mode 100644
index 0000000000..422802457e
--- /dev/null
+++ b/target/linux/generic/backport-6.12/601-09-v6.14-net-phylink-add-pcs_inband_caps-method.patch
@@ -0,0 +1,159 @@
+From df874f9e52c340cc6f0a0014a97b778f67d46849 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tIUs4-006IUU-7K@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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.
+  */
diff --git a/target/linux/generic/backport-6.12/601-10-v6.14-net-mvneta-implement-pcs_inband_caps-method.patch b/target/linux/generic/backport-6.12/601-10-v6.14-net-mvneta-implement-pcs_inband_caps-method.patch
new file mode 100644
index 0000000000..0937ad1388
--- /dev/null
+++ b/target/linux/generic/backport-6.12/601-10-v6.14-net-mvneta-implement-pcs_inband_caps-method.patch
@@ -0,0 +1,64 @@
+From 513e8fb8fa32035b3325e2e14fb9598f8cb545e9 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tIUs9-006IUb-Au@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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,
diff --git a/target/linux/generic/backport-6.12/601-11-v6.14-net-mvpp2-implement-pcs_inband_caps-method.patch b/target/linux/generic/backport-6.12/601-11-v6.14-net-mvpp2-implement-pcs_inband_caps-method.patch
new file mode 100644
index 0000000000..846d9df36d
--- /dev/null
+++ b/target/linux/generic/backport-6.12/601-11-v6.14-net-mvpp2-implement-pcs_inband_caps-method.patch
@@ -0,0 +1,62 @@
+From d4169f0c7665afb8d8adb5e1b1df3db88517d0ad Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tIUsE-006IUh-E7@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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,
diff --git a/target/linux/generic/backport-6.12/601-12-v6.14-net-phylink-add-negotiation-of-in-band-capabilities.patch b/target/linux/generic/backport-6.12/601-12-v6.14-net-phylink-add-negotiation-of-in-band-capabilities.patch
new file mode 100644
index 0000000000..f629133013
--- /dev/null
+++ b/target/linux/generic/backport-6.12/601-12-v6.14-net-phylink-add-negotiation-of-in-band-capabilities.patch
@@ -0,0 +1,228 @@
+From 5fd0f1a02e750e2db4038dee60edea669ce5aab1 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tIUsJ-006IUn-H3@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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)
diff --git a/target/linux/generic/backport-6.12/601-13-v6.14-net-phylink-remove-phylink_phy_no_inband.patch b/target/linux/generic/backport-6.12/601-13-v6.14-net-phylink-remove-phylink_phy_no_inband.patch
new file mode 100644
index 0000000000..8be74a2ad6
--- /dev/null
+++ b/target/linux/generic/backport-6.12/601-13-v6.14-net-phylink-remove-phylink_phy_no_inband.patch
@@ -0,0 +1,110 @@
+From 77ac9a8b2536e0eaca6c6f21070068458bf55981 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tIUsO-006IUt-KN@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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;
+ 
diff --git a/target/linux/generic/backport-6.12/602-01-v6.14-net-pcs-pcs-lynx-implement-pcs_inband_caps-method.patch b/target/linux/generic/backport-6.12/602-01-v6.14-net-pcs-pcs-lynx-implement-pcs_inband_caps-method.patch
new file mode 100644
index 0000000000..32ba605b1c
--- /dev/null
+++ b/target/linux/generic/backport-6.12/602-01-v6.14-net-pcs-pcs-lynx-implement-pcs_inband_caps-method.patch
@@ -0,0 +1,53 @@
+From 6561f0e547be221f411fda5eddfcc5bd8bb058a5 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at bootlin.com>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tJ8NM-006L5J-AH@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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,
diff --git a/target/linux/generic/backport-6.12/602-02-v6.14-net-pcs-pcs-mtk-lynxi-implement-pcs_inband_caps-meth.patch b/target/linux/generic/backport-6.12/602-02-v6.14-net-pcs-pcs-mtk-lynxi-implement-pcs_inband_caps-meth.patch
new file mode 100644
index 0000000000..1cfd3bab9b
--- /dev/null
+++ b/target/linux/generic/backport-6.12/602-02-v6.14-net-pcs-pcs-mtk-lynxi-implement-pcs_inband_caps-meth.patch
@@ -0,0 +1,47 @@
+From 520d29bdda86915b3caf8c72825a574bff212553 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tJ8NR-006L5P-E3@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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,
diff --git a/target/linux/generic/backport-6.12/602-03-v6.14-net-pcs-xpcs-implement-pcs_inband_caps-method.patch b/target/linux/generic/backport-6.12/602-03-v6.14-net-pcs-xpcs-implement-pcs_inband_caps-method.patch
new file mode 100644
index 0000000000..8dc495bd0c
--- /dev/null
+++ b/target/linux/generic/backport-6.12/602-03-v6.14-net-pcs-xpcs-implement-pcs_inband_caps-method.patch
@@ -0,0 +1,58 @@
+From 484d0170d6c6bbb5213d037664e9a551f793bacd Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tJ8NW-006L5V-I9@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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,
diff --git a/target/linux/generic/backport-6.12/720-09-v6.14-net-phy-Constify-struct-mdio_device_id.patch b/target/linux/generic/backport-6.12/720-09-v6.14-net-phy-Constify-struct-mdio_device_id.patch
index 6b85e59577..3a6e0ac80a 100644
--- a/target/linux/generic/backport-6.12/720-09-v6.14-net-phy-Constify-struct-mdio_device_id.patch
+++ b/target/linux/generic/backport-6.12/720-09-v6.14-net-phy-Constify-struct-mdio_device_id.patch
@@ -194,7 +194,7 @@ Signed-off-by: Jakub Kicinski <kuba at 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 at 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);
  
diff --git a/target/linux/generic/backport-6.12/730-03-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch b/target/linux/generic/backport-6.12/730-03-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch
index 9c317606e1..5563f3dce6 100644
--- a/target/linux/generic/backport-6.12/730-03-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch
+++ b/target/linux/generic/backport-6.12/730-03-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch
@@ -39,7 +39,7 @@ Signed-off-by: Paolo Abeni <pabeni at 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 {
diff --git a/target/linux/generic/backport-6.12/782-01-v6.16-net-phy-pass-PHY-driver-to-.match_phy_device-OP.patch b/target/linux/generic/backport-6.12/782-01-v6.16-net-phy-pass-PHY-driver-to-.match_phy_device-OP.patch
index cda5226904..d2b20cc8a5 100644
--- a/target/linux/generic/backport-6.12/782-01-v6.16-net-phy-pass-PHY-driver-to-.match_phy_device-OP.patch
+++ b/target/linux/generic/backport-6.12/782-01-v6.16-net-phy-pass-PHY-driver-to-.match_phy_device-OP.patch
@@ -281,7 +281,7 @@ Signed-off-by: Jakub Kicinski <kuba at 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.
  	 */
diff --git a/target/linux/generic/backport-6.12/782-04-v6.16-net-phy-introduce-genphy_match_phy_device.patch b/target/linux/generic/backport-6.12/782-04-v6.16-net-phy-introduce-genphy_match_phy_device.patch
index 9e28011b0c..dd24ba2370 100644
--- a/target/linux/generic/backport-6.12/782-04-v6.16-net-phy-introduce-genphy_match_phy_device.patch
+++ b/target/linux/generic/backport-6.12/782-04-v6.16-net-phy-introduce-genphy_match_phy_device.patch
@@ -97,7 +97,7 @@ Signed-off-by: Jakub Kicinski <kuba at 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);
  
diff --git a/target/linux/generic/backport-6.6/604-01-v6.13-net-phylink-move-manual-flow-control-setting.patch b/target/linux/generic/backport-6.6/604-01-v6.13-net-phylink-move-manual-flow-control-setting.patch
new file mode 100644
index 0000000000..7de4f586f4
--- /dev/null
+++ b/target/linux/generic/backport-6.6/604-01-v6.13-net-phylink-move-manual-flow-control-setting.patch
@@ -0,0 +1,41 @@
+From 8cc5f4cb94c0b1c7c1ba8013c14fd02ffb1a25f3 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at armlinux.org.uk>
+Link: https://patch.msgid.link/E1t9RQe-002Feh-T1@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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
diff --git a/target/linux/generic/backport-6.6/604-02-v6.13-net-phylink-move-MLO_AN_FIXED-resolve-handling-to-if.patch b/target/linux/generic/backport-6.6/604-02-v6.13-net-phylink-move-MLO_AN_FIXED-resolve-handling-to-if.patch
new file mode 100644
index 0000000000..d81ab2af0d
--- /dev/null
+++ b/target/linux/generic/backport-6.6/604-02-v6.13-net-phylink-move-MLO_AN_FIXED-resolve-handling-to-if.patch
@@ -0,0 +1,42 @@
+From 92abfcb4ced482afbe65d18980e6734fe1e62a34 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at armlinux.org.uk>
+Link: https://patch.msgid.link/E1t9RQk-002Fen-1A@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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);
+ 
diff --git a/target/linux/generic/backport-6.6/604-03-v6.13-net-phylink-move-MLO_AN_PHY-resolve-handling-to-if-s.patch b/target/linux/generic/backport-6.6/604-03-v6.13-net-phylink-move-MLO_AN_PHY-resolve-handling-to-if-s.patch
new file mode 100644
index 0000000000..269c50a077
--- /dev/null
+++ b/target/linux/generic/backport-6.6/604-03-v6.13-net-phylink-move-MLO_AN_PHY-resolve-handling-to-if-s.patch
@@ -0,0 +1,37 @@
+From f0f46c2a3d8ea9d1427298c8103a777d9e616c29 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at armlinux.org.uk>
+Link: https://patch.msgid.link/E1t9RQp-002Fet-5W@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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);
+ 
diff --git a/target/linux/generic/backport-6.6/604-04-v6.13-net-phylink-remove-switch-statement-in-resolve-handl.patch b/target/linux/generic/backport-6.6/604-04-v6.13-net-phylink-remove-switch-statement-in-resolve-handl.patch
new file mode 100644
index 0000000000..521da5f30b
--- /dev/null
+++ b/target/linux/generic/backport-6.6/604-04-v6.13-net-phylink-remove-switch-statement-in-resolve-handl.patch
@@ -0,0 +1,127 @@
+From d1a16dbbd84e02d2a6dcfcb8d5c4b8b2c0289f00 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at armlinux.org.uk>
+Link: https://patch.msgid.link/E1t9RQu-002Fez-AA@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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;
+ 		}
+ 	}
+ 
diff --git a/target/linux/generic/backport-6.6/604-05-v6.13-net-phylink-clean-up-phylink_resolve.patch b/target/linux/generic/backport-6.6/604-05-v6.13-net-phylink-clean-up-phylink_resolve.patch
new file mode 100644
index 0000000000..e5e2e165c8
--- /dev/null
+++ b/target/linux/generic/backport-6.6/604-05-v6.13-net-phylink-clean-up-phylink_resolve.patch
@@ -0,0 +1,85 @@
+From bc08ce37d99a3992e975a0f397503cb23404f25a Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at armlinux.org.uk>
+Link: https://patch.msgid.link/E1t9RQz-002Ff5-EA@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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;
diff --git a/target/linux/generic/backport-6.6/605-v6.8-net-phylink-move-phylink_pcs_neg_mode-into-phylink.c.patch b/target/linux/generic/backport-6.6/605-v6.8-net-phylink-move-phylink_pcs_neg_mode-into-phylink.c.patch
new file mode 100644
index 0000000000..42715ef97f
--- /dev/null
+++ b/target/linux/generic/backport-6.6/605-v6.8-net-phylink-move-phylink_pcs_neg_mode-into-phylink.c.patch
@@ -0,0 +1,166 @@
+From 5e5401d6612ef599ad45785b941eebda7effc90f Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at armlinux.org.uk>
+Reviewed-by: Andrew Lunn <andrew at lunn.ch>
+Signed-off-by: David S. Miller <davem at 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
diff --git a/target/linux/generic/backport-6.6/606-01-v6.14-net-phylink-pass-phylink-and-pcs-into-phylink_pcs_ne.patch b/target/linux/generic/backport-6.6/606-01-v6.14-net-phylink-pass-phylink-and-pcs-into-phylink_pcs_ne.patch
new file mode 100644
index 0000000000..2150a4a341
--- /dev/null
+++ b/target/linux/generic/backport-6.6/606-01-v6.14-net-phylink-pass-phylink-and-pcs-into-phylink_pcs_ne.patch
@@ -0,0 +1,95 @@
+From 17ed1911f9c8d4f9af8e13b2c95103ee06dadc0f Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tIUrP-006ITh-6u@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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)
diff --git a/target/linux/generic/backport-6.6/606-02-v6.14-net-phylink-split-cur_link_an_mode-into-requested-an.patch b/target/linux/generic/backport-6.6/606-02-v6.14-net-phylink-split-cur_link_an_mode-into-requested-an.patch
new file mode 100644
index 0000000000..2cc97dd735
--- /dev/null
+++ b/target/linux/generic/backport-6.6/606-02-v6.14-net-phylink-split-cur_link_an_mode-into-requested-an.patch
@@ -0,0 +1,281 @@
+From 1f92ead7e15003f632b5f138e8138095e0997d3d Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tIUrU-006ITn-Ai@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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;
diff --git a/target/linux/generic/backport-6.6/606-03-v6.14-net-phylink-add-debug-for-phylink_major_config.patch b/target/linux/generic/backport-6.6/606-03-v6.14-net-phylink-add-debug-for-phylink_major_config.patch
new file mode 100644
index 0000000000..483fe07a43
--- /dev/null
+++ b/target/linux/generic/backport-6.6/606-03-v6.14-net-phylink-add-debug-for-phylink_major_config.patch
@@ -0,0 +1,66 @@
+From 4e7d000286fe8e12f2d88032711ffab3ab658b12 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tIUrZ-006ITt-Fa@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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) {
diff --git a/target/linux/generic/backport-6.6/606-04-v6.14-net-phy-add-phy_inband_caps.patch b/target/linux/generic/backport-6.6/606-04-v6.14-net-phy-add-phy_inband_caps.patch
new file mode 100644
index 0000000000..dcff6b27d7
--- /dev/null
+++ b/target/linux/generic/backport-6.6/606-04-v6.14-net-phy-add-phy_inband_caps.patch
@@ -0,0 +1,118 @@
+From b4c7698dd95f253c6958d8c6ac219098009bf28a Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tIUre-006ITz-KF@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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);
diff --git a/target/linux/generic/backport-6.6/606-05-v6.14-net-phy-bcm84881-implement-phy_inband_caps-method.patch b/target/linux/generic/backport-6.6/606-05-v6.14-net-phy-bcm84881-implement-phy_inband_caps-method.patch
new file mode 100644
index 0000000000..a78fad173f
--- /dev/null
+++ b/target/linux/generic/backport-6.6/606-05-v6.14-net-phy-bcm84881-implement-phy_inband_caps-method.patch
@@ -0,0 +1,41 @@
+From c64c7fa0a774d9da72071a8517e359992baac982 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Acked-by: Florian Fainelli <florian.fainelli at broadcom.com>
+Link: https://patch.msgid.link/E1tIUrj-006IU6-ON@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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,
diff --git a/target/linux/generic/backport-6.6/606-06-v6.14-net-phy-marvell-implement-phy_inband_caps-method.patch b/target/linux/generic/backport-6.6/606-06-v6.14-net-phy-marvell-implement-phy_inband_caps-method.patch
new file mode 100644
index 0000000000..c1f481e808
--- /dev/null
+++ b/target/linux/generic/backport-6.6/606-06-v6.14-net-phy-marvell-implement-phy_inband_caps-method.patch
@@ -0,0 +1,63 @@
+From 1c86828dff88e28b8ade6bddeee0163a023faf91 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tIUro-006IUC-Rq@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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,
diff --git a/target/linux/generic/backport-6.6/606-07-v6.14-net-phy-add-phy_config_inband.patch b/target/linux/generic/backport-6.6/606-07-v6.14-net-phy-add-phy_config_inband.patch
new file mode 100644
index 0000000000..652aaa1215
--- /dev/null
+++ b/target/linux/generic/backport-6.6/606-07-v6.14-net-phy-add-phy_config_inband.patch
@@ -0,0 +1,79 @@
+From 5d58a890c02770ba8d790b1f3c6e8c0e20514dc2 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tIUru-006IUI-08@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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);
diff --git a/target/linux/generic/backport-6.6/606-08-v6.14-net-phy-marvell-implement-config_inband-method.patch b/target/linux/generic/backport-6.6/606-08-v6.14-net-phy-marvell-implement-config_inband-method.patch
new file mode 100644
index 0000000000..30c393d152
--- /dev/null
+++ b/target/linux/generic/backport-6.6/606-08-v6.14-net-phy-marvell-implement-config_inband-method.patch
@@ -0,0 +1,77 @@
+From a219912e0fec73c346e64ef47013cb2e152f88fc Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tIUrz-006IUO-3r@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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,
diff --git a/target/linux/generic/backport-6.6/606-09-v6.14-net-phylink-add-pcs_inband_caps-method.patch b/target/linux/generic/backport-6.6/606-09-v6.14-net-phylink-add-pcs_inband_caps-method.patch
new file mode 100644
index 0000000000..2ca722b39b
--- /dev/null
+++ b/target/linux/generic/backport-6.6/606-09-v6.14-net-phylink-add-pcs_inband_caps-method.patch
@@ -0,0 +1,159 @@
+From df874f9e52c340cc6f0a0014a97b778f67d46849 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tIUs4-006IUU-7K@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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.
+  */
diff --git a/target/linux/generic/backport-6.6/606-10-v6.14-net-mvneta-implement-pcs_inband_caps-method.patch b/target/linux/generic/backport-6.6/606-10-v6.14-net-mvneta-implement-pcs_inband_caps-method.patch
new file mode 100644
index 0000000000..b926312e79
--- /dev/null
+++ b/target/linux/generic/backport-6.6/606-10-v6.14-net-mvneta-implement-pcs_inband_caps-method.patch
@@ -0,0 +1,64 @@
+From 513e8fb8fa32035b3325e2e14fb9598f8cb545e9 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tIUs9-006IUb-Au@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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,
diff --git a/target/linux/generic/backport-6.6/606-11-v6.14-net-mvpp2-implement-pcs_inband_caps-method.patch b/target/linux/generic/backport-6.6/606-11-v6.14-net-mvpp2-implement-pcs_inband_caps-method.patch
new file mode 100644
index 0000000000..1ff6035a3d
--- /dev/null
+++ b/target/linux/generic/backport-6.6/606-11-v6.14-net-mvpp2-implement-pcs_inband_caps-method.patch
@@ -0,0 +1,62 @@
+From d4169f0c7665afb8d8adb5e1b1df3db88517d0ad Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tIUsE-006IUh-E7@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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,
diff --git a/target/linux/generic/backport-6.6/606-12-v6.14-net-phylink-add-negotiation-of-in-band-capabilities.patch b/target/linux/generic/backport-6.6/606-12-v6.14-net-phylink-add-negotiation-of-in-band-capabilities.patch
new file mode 100644
index 0000000000..cf234f806b
--- /dev/null
+++ b/target/linux/generic/backport-6.6/606-12-v6.14-net-phylink-add-negotiation-of-in-band-capabilities.patch
@@ -0,0 +1,228 @@
+From 5fd0f1a02e750e2db4038dee60edea669ce5aab1 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tIUsJ-006IUn-H3@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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)
diff --git a/target/linux/generic/backport-6.6/606-13-v6.14-net-phylink-remove-phylink_phy_no_inband.patch b/target/linux/generic/backport-6.6/606-13-v6.14-net-phylink-remove-phylink_phy_no_inband.patch
new file mode 100644
index 0000000000..7c5d039328
--- /dev/null
+++ b/target/linux/generic/backport-6.6/606-13-v6.14-net-phylink-remove-phylink_phy_no_inband.patch
@@ -0,0 +1,110 @@
+From 77ac9a8b2536e0eaca6c6f21070068458bf55981 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tIUsO-006IUt-KN@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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;
+ 
diff --git a/target/linux/generic/backport-6.6/607-01-v6.14-net-pcs-pcs-lynx-implement-pcs_inband_caps-method.patch b/target/linux/generic/backport-6.6/607-01-v6.14-net-pcs-pcs-lynx-implement-pcs_inband_caps-method.patch
new file mode 100644
index 0000000000..d5eb15d50d
--- /dev/null
+++ b/target/linux/generic/backport-6.6/607-01-v6.14-net-pcs-pcs-lynx-implement-pcs_inband_caps-method.patch
@@ -0,0 +1,53 @@
+From 6561f0e547be221f411fda5eddfcc5bd8bb058a5 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at bootlin.com>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tJ8NM-006L5J-AH@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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,
diff --git a/target/linux/generic/backport-6.6/607-02-v6.14-net-pcs-pcs-mtk-lynxi-implement-pcs_inband_caps-meth.patch b/target/linux/generic/backport-6.6/607-02-v6.14-net-pcs-pcs-mtk-lynxi-implement-pcs_inband_caps-meth.patch
new file mode 100644
index 0000000000..1cfd3bab9b
--- /dev/null
+++ b/target/linux/generic/backport-6.6/607-02-v6.14-net-pcs-pcs-mtk-lynxi-implement-pcs_inband_caps-meth.patch
@@ -0,0 +1,47 @@
+From 520d29bdda86915b3caf8c72825a574bff212553 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tJ8NR-006L5P-E3@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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,
diff --git a/target/linux/generic/backport-6.6/607-03-v6.14-net-pcs-xpcs-implement-pcs_inband_caps-method.patch b/target/linux/generic/backport-6.6/607-03-v6.14-net-pcs-xpcs-implement-pcs_inband_caps-method.patch
new file mode 100644
index 0000000000..4945f7c04c
--- /dev/null
+++ b/target/linux/generic/backport-6.6/607-03-v6.14-net-pcs-xpcs-implement-pcs_inband_caps-method.patch
@@ -0,0 +1,58 @@
+From 484d0170d6c6bbb5213d037664e9a551f793bacd Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at 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 at armlinux.org.uk>
+Link: https://patch.msgid.link/E1tJ8NW-006L5V-I9@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at 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,
diff --git a/target/linux/generic/backport-6.6/714-v6.8-02-net-phy-extend-PHY-package-API-to-support-multiple-g.patch b/target/linux/generic/backport-6.6/714-v6.8-02-net-phy-extend-PHY-package-API-to-support-multiple-g.patch
index 514a80b298..3efeb04d8b 100644
--- a/target/linux/generic/backport-6.6/714-v6.8-02-net-phy-extend-PHY-package-API-to-support-multiple-g.patch
+++ b/target/linux/generic/backport-6.6/714-v6.8-02-net-phy-extend-PHY-package-API-to-support-multiple-g.patch
@@ -242,7 +242,7 @@ Signed-off-by: David S. Miller <davem at 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 at 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);
  
diff --git a/target/linux/generic/backport-6.6/714-v6.8-04-net-phy-add-support-for-PHY-package-MMD-read-write.patch b/target/linux/generic/backport-6.6/714-v6.8-04-net-phy-add-support-for-PHY-package-MMD-read-write.patch
index d42da1b71f..ae8a43feb1 100644
--- a/target/linux/generic/backport-6.6/714-v6.8-04-net-phy-add-support-for-PHY-package-MMD-read-write.patch
+++ b/target/linux/generic/backport-6.6/714-v6.8-04-net-phy-add-support-for-PHY-package-MMD-read-write.patch
@@ -171,7 +171,7 @@ Signed-off-by: David S. Miller <davem at 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);
  }
  
diff --git a/target/linux/generic/backport-6.6/716-v6.9-03-net-phy-add-devm-of_phy_package_join-helper.patch b/target/linux/generic/backport-6.6/716-v6.9-03-net-phy-add-devm-of_phy_package_join-helper.patch
index 1fdd91497b..2fd03e920a 100644
--- a/target/linux/generic/backport-6.6/716-v6.9-03-net-phy-add-devm-of_phy_package_join-helper.patch
+++ b/target/linux/generic/backport-6.6/716-v6.9-03-net-phy-add-devm-of_phy_package_join-helper.patch
@@ -170,7 +170,7 @@ Signed-off-by: David S. Miller <davem at 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);
diff --git a/target/linux/generic/backport-6.6/716-v6.9-06-net-phy-provide-whether-link-has-changed-in-c37_read.patch b/target/linux/generic/backport-6.6/716-v6.9-06-net-phy-provide-whether-link-has-changed-in-c37_read.patch
index 4bb44b921d..22179d8cc4 100644
--- a/target/linux/generic/backport-6.6/716-v6.9-06-net-phy-provide-whether-link-has-changed-in-c37_read.patch
+++ b/target/linux/generic/backport-6.6/716-v6.9-06-net-phy-provide-whether-link-has-changed-in-c37_read.patch
@@ -89,7 +89,7 @@ Signed-off-by: David S. Miller <davem at 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);
diff --git a/target/linux/generic/backport-6.6/782-01-v6.16-net-phy-pass-PHY-driver-to-.match_phy_device-OP.patch b/target/linux/generic/backport-6.6/782-01-v6.16-net-phy-pass-PHY-driver-to-.match_phy_device-OP.patch
index b8460a2b5e..b60ce1cfcf 100644
--- a/target/linux/generic/backport-6.6/782-01-v6.16-net-phy-pass-PHY-driver-to-.match_phy_device-OP.patch
+++ b/target/linux/generic/backport-6.6/782-01-v6.16-net-phy-pass-PHY-driver-to-.match_phy_device-OP.patch
@@ -261,7 +261,7 @@ Signed-off-by: Jakub Kicinski <kuba at 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.
  	 */
diff --git a/target/linux/generic/backport-6.6/782-04-v6.16-net-phy-introduce-genphy_match_phy_device.patch b/target/linux/generic/backport-6.6/782-04-v6.16-net-phy-introduce-genphy_match_phy_device.patch
index 1c0b5d836d..639856fcb8 100644
--- a/target/linux/generic/backport-6.6/782-04-v6.16-net-phy-introduce-genphy_match_phy_device.patch
+++ b/target/linux/generic/backport-6.6/782-04-v6.16-net-phy-introduce-genphy_match_phy_device.patch
@@ -97,7 +97,7 @@ Signed-off-by: Jakub Kicinski <kuba at 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);
  
diff --git a/target/linux/generic/backport-6.6/835-v6.9-net-phy-add-support-for-PHY-LEDs-polarity-modes.patch b/target/linux/generic/backport-6.6/835-v6.9-net-phy-add-support-for-PHY-LEDs-polarity-modes.patch
index 4d8742f0e3..bc58e99276 100644
--- a/target/linux/generic/backport-6.6/835-v6.9-net-phy-add-support-for-PHY-LEDs-polarity-modes.patch
+++ b/target/linux/generic/backport-6.6/835-v6.9-net-phy-add-support-for-PHY-LEDs-polarity-modes.patch
@@ -60,7 +60,7 @@ Signed-off-by: Jakub Kicinski <kuba at 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 at 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);
  
diff --git a/target/linux/generic/backport-6.6/841-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch b/target/linux/generic/backport-6.6/841-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch
index 1b979f8662..aea1046add 100644
--- a/target/linux/generic/backport-6.6/841-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch
+++ b/target/linux/generic/backport-6.6/841-v6.13-net-phy-support-active-high-property-for-PHY-LEDs.patch
@@ -39,7 +39,7 @@ Signed-off-by: Paolo Abeni <pabeni at 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 {
diff --git a/target/linux/generic/backport-6.6/895-02-v6.8-net-phylink-use-for_each_set_bit.patch b/target/linux/generic/backport-6.6/895-02-v6.8-net-phylink-use-for_each_set_bit.patch
index 397780f7fd..c73104522d 100644
--- a/target/linux/generic/backport-6.6/895-02-v6.8-net-phylink-use-for_each_set_bit.patch
+++ b/target/linux/generic/backport-6.6/895-02-v6.8-net-phylink-use-for_each_set_bit.patch
@@ -17,7 +17,7 @@ Signed-off-by: Paolo Abeni <pabeni at 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;
diff --git a/target/linux/generic/backport-6.6/895-03-v6.8-net-phylink-split-out-per-interface-validation.patch b/target/linux/generic/backport-6.6/895-03-v6.8-net-phylink-split-out-per-interface-validation.patch
index 33f64e81c2..ed2f348567 100644
--- a/target/linux/generic/backport-6.6/895-03-v6.8-net-phylink-split-out-per-interface-validation.patch
+++ b/target/linux/generic/backport-6.6/895-03-v6.8-net-phylink-split-out-per-interface-validation.patch
@@ -17,7 +17,7 @@ Signed-off-by: Jakub Kicinski <kuba at 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;
  }
  
diff --git a/target/linux/generic/backport-6.6/895-04-v6.8-net-phylink-pass-PHY-into-phylink_validate_one.patch b/target/linux/generic/backport-6.6/895-04-v6.8-net-phylink-pass-PHY-into-phylink_validate_one.patch
index e3915f0609..9f79748da9 100644
--- a/target/linux/generic/backport-6.6/895-04-v6.8-net-phylink-pass-PHY-into-phylink_validate_one.patch
+++ b/target/linux/generic/backport-6.6/895-04-v6.8-net-phylink-pass-PHY-into-phylink_validate_one.patch
@@ -17,7 +17,7 @@ Signed-off-by: Jakub Kicinski <kuba at 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 at 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 at 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)
diff --git a/target/linux/generic/backport-6.6/895-05-v6.8-net-phylink-pass-PHY-into-phylink_validate_mask.patch b/target/linux/generic/backport-6.6/895-05-v6.8-net-phylink-pass-PHY-into-phylink_validate_mask.patch
index 5f66869ef3..6e04ebeda4 100644
--- a/target/linux/generic/backport-6.6/895-05-v6.8-net-phylink-pass-PHY-into-phylink_validate_mask.patch
+++ b/target/linux/generic/backport-6.6/895-05-v6.8-net-phylink-pass-PHY-into-phylink_validate_mask.patch
@@ -17,7 +17,7 @@ Signed-off-by: Jakub Kicinski <kuba at 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 at 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 at 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 at 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.
  	 */
diff --git a/target/linux/generic/backport-6.6/895-06-v6.8-net-phylink-split-out-PHY-validation-from-phylink_br.patch b/target/linux/generic/backport-6.6/895-06-v6.8-net-phylink-split-out-PHY-validation-from-phylink_br.patch
index e29503398e..a02677d9a4 100644
--- a/target/linux/generic/backport-6.6/895-06-v6.8-net-phylink-split-out-PHY-validation-from-phylink_br.patch
+++ b/target/linux/generic/backport-6.6/895-06-v6.8-net-phylink-split-out-PHY-validation-from-phylink_br.patch
@@ -22,7 +22,7 @@ Signed-off-by: Jakub Kicinski <kuba at 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 at 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);
diff --git a/target/linux/generic/backport-6.6/895-07-v6.8-net-phylink-use-the-PHY-s-possible_interfaces-if-pop.patch b/target/linux/generic/backport-6.6/895-07-v6.8-net-phylink-use-the-PHY-s-possible_interfaces-if-pop.patch
index 86ed7a868e..1d98dd1de0 100644
--- a/target/linux/generic/backport-6.6/895-07-v6.8-net-phylink-use-the-PHY-s-possible_interfaces-if-pop.patch
+++ b/target/linux/generic/backport-6.6/895-07-v6.8-net-phylink-use-the-PHY-s-possible_interfaces-if-pop.patch
@@ -40,7 +40,7 @@ Signed-off-by: Jakub Kicinski <kuba at 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 at 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 at 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;
  }
  
diff --git a/target/linux/generic/hack-6.12/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch b/target/linux/generic/hack-6.12/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch
index 30a502a237..bf26a2f6ec 100644
--- a/target/linux/generic/hack-6.12/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch
+++ b/target/linux/generic/hack-6.12/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch
@@ -13,7 +13,7 @@ Signed-off-by: Daniel Golle <daniel at 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 at 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 at 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;
diff --git a/target/linux/generic/hack-6.6/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch b/target/linux/generic/hack-6.6/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch
index 30a502a237..bf26a2f6ec 100644
--- a/target/linux/generic/hack-6.6/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch
+++ b/target/linux/generic/hack-6.6/750-net-pcs-mtk-lynxi-workaround-2500BaseX-no-an.patch
@@ -13,7 +13,7 @@ Signed-off-by: Daniel Golle <daniel at 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 at 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 at 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;
diff --git a/target/linux/generic/pending-6.12/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/pending-6.12/703-phy-add-detach-callback-to-struct-phy_driver.patch
index ed6c9070b2..f8bcf6744f 100644
--- a/target/linux/generic/pending-6.12/703-phy-add-detach-callback-to-struct-phy_driver.patch
+++ b/target/linux/generic/pending-6.12/703-phy-add-detach-callback-to-struct-phy_driver.patch
@@ -23,7 +23,7 @@ Signed-off-by: Gabor Juhos <juhosg at 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);
  
diff --git a/target/linux/generic/pending-6.12/706-net-phy-populate-host_interfaces-when-attaching-PHY.patch b/target/linux/generic/pending-6.12/706-net-phy-populate-host_interfaces-when-attaching-PHY.patch
index 6b2b016881..0af507eed3 100644
--- a/target/linux/generic/pending-6.12/706-net-phy-populate-host_interfaces-when-attaching-PHY.patch
+++ b/target/linux/generic/pending-6.12/706-net-phy-populate-host_interfaces-when-attaching-PHY.patch
@@ -20,7 +20,7 @@ Signed-off-by: Daniel Golle <daniel at 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 at 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;
  
diff --git a/target/linux/generic/pending-6.12/739-03-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch b/target/linux/generic/pending-6.12/739-03-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch
index 8eb9d35b58..0e4a63ec7f 100644
--- a/target/linux/generic/pending-6.12/739-03-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch
+++ b/target/linux/generic/pending-6.12/739-03-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch
@@ -79,7 +79,7 @@ Signed-off-by: Daniel Golle <daniel at 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 at 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 at 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 at 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 at 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 at 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 at 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);
  
diff --git a/target/linux/generic/pending-6.6/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/pending-6.6/703-phy-add-detach-callback-to-struct-phy_driver.patch
index efa76572f8..3fe618ab9c 100644
--- a/target/linux/generic/pending-6.6/703-phy-add-detach-callback-to-struct-phy_driver.patch
+++ b/target/linux/generic/pending-6.6/703-phy-add-detach-callback-to-struct-phy_driver.patch
@@ -23,7 +23,7 @@ Signed-off-by: Gabor Juhos <juhosg at 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);
  
diff --git a/target/linux/generic/pending-6.6/706-net-phy-populate-host_interfaces-when-attaching-PHY.patch b/target/linux/generic/pending-6.6/706-net-phy-populate-host_interfaces-when-attaching-PHY.patch
index 78e0049f05..968fea4431 100644
--- a/target/linux/generic/pending-6.6/706-net-phy-populate-host_interfaces-when-attaching-PHY.patch
+++ b/target/linux/generic/pending-6.6/706-net-phy-populate-host_interfaces-when-attaching-PHY.patch
@@ -20,7 +20,7 @@ Signed-off-by: Daniel Golle <daniel at 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 at 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;
  	}
  
diff --git a/target/linux/generic/pending-6.6/739-03-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch b/target/linux/generic/pending-6.6/739-03-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch
index faa7624307..11cb53428f 100644
--- a/target/linux/generic/pending-6.6/739-03-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch
+++ b/target/linux/generic/pending-6.6/739-03-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch
@@ -79,7 +79,7 @@ Signed-off-by: Daniel Golle <daniel at 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 at 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 at 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 at 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 at 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 at 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 at 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);
  
diff --git a/target/linux/layerscape/patches-6.12/702-phy-Add-2.5G-SGMII-interface-mode.patch b/target/linux/layerscape/patches-6.12/702-phy-Add-2.5G-SGMII-interface-mode.patch
index 92e71276bf..af14871b59 100644
--- a/target/linux/layerscape/patches-6.12/702-phy-Add-2.5G-SGMII-interface-mode.patch
+++ b/target/linux/layerscape/patches-6.12/702-phy-Add-2.5G-SGMII-interface-mode.patch
@@ -36,7 +36,7 @@ Signed-off-by: Bhaskar Upadhaya <Bhaskar.Upadhaya at 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 at 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:
diff --git a/target/linux/layerscape/patches-6.6/702-phy-Add-2.5G-SGMII-interface-mode.patch b/target/linux/layerscape/patches-6.6/702-phy-Add-2.5G-SGMII-interface-mode.patch
index b4e527214e..975288871e 100644
--- a/target/linux/layerscape/patches-6.6/702-phy-Add-2.5G-SGMII-interface-mode.patch
+++ b/target/linux/layerscape/patches-6.6/702-phy-Add-2.5G-SGMII-interface-mode.patch
@@ -25,7 +25,7 @@ Signed-off-by: Bhaskar Upadhaya <Bhaskar.Upadhaya at 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 at 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:
diff --git a/target/linux/mediatek/patches-6.12/739-net-add-negotiation-of-in-band-capabilities.patch b/target/linux/mediatek/patches-6.12/739-net-add-negotiation-of-in-band-capabilities.patch
deleted file mode 100644
index 12638978b3..0000000000
--- a/target/linux/mediatek/patches-6.12/739-net-add-negotiation-of-in-band-capabilities.patch
+++ /dev/null
@@ -1,1242 +0,0 @@
-From: "Russell King (Oracle)" <linux at armlinux.org.uk>
-To: Andrew Lunn <andrew at lunn.ch>, Heiner Kallweit <hkallweit1 at gmail.com>
-Cc: Alexander Couzens <lynxis at fe80.eu>,
-	Andrew Lunn <andrew+netdev at lunn.ch>,
-	AngeloGioacchino Del Regno
-	<angelogioacchino.delregno at collabora.com>,
-	Broadcom internal kernel review list
-	<bcm-kernel-feedback-list at broadcom.com>,
-	Daniel Golle <daniel at makrotopia.org>,
-	"David S. Miller" <davem at davemloft.net>,
-	Eric Dumazet <edumazet at google.com>,
-	Florian Fainelli <florian.fainelli at broadcom.com>,
-	Ioana Ciornei <ioana.ciornei at nxp.com>,
-	Jakub Kicinski <kuba at kernel.org>,
-	Jose Abreu <Jose.Abreu at synopsys.com>,
-	linux-arm-kernel at lists.infradead.org,
-	linux-mediatek at lists.infradead.org,
-	Marcin Wojtas <marcin.s.wojtas at gmail.com>,
-	Matthias Brugger <matthias.bgg at gmail.com>,
-	netdev at vger.kernel.org, Paolo Abeni <pabeni at redhat.com>
-Subject: [PATCH RFC net-next 00/16] net: add negotiation of in-band capabilities
-Date: Tue, 26 Nov 2024 09:23:48 +0000	[thread overview]
-Message-ID: <Z0WTpE8wkpjMiv_J at shell.armlinux.org.uk> (raw)
-
-Hi,
-
-Yes, this is one patch over the limit of 15 for netdev - but I think it's
-important to include the last patch to head off review comments like "why
-don't you remove phylink_phy_no_inband() in this series?"
-
-Phylink's handling of in-band has been deficient for a long time, and
-people keep hitting problems with it. Notably, situations with the way-
-to-late standardized 2500Base-X and whether that should or should not
-have in-band enabled. We have also been carrying a hack in the form of
-phylink_phy_no_inband() for a PHY that has been used on a SFP module,
-but has no in-band capabilities, not even for SGMII.
-
-When phylink is trying to operate in in-band mode, this series will look
-at the capabilities of the MAC-side PCS and PHY, and work out whether
-in-band can or should be used, programming the PHY as appropriate. This
-includes in-band bypass mode at the PHY.
-
-We don't... yet... support that on the MAC side PCS, because that
-requires yet more complexity.
-
-Patch 1 passes struct phylink and struct phylink_pcs into
-phylink_pcs_neg_mode() so we can look at more state in this function in
-a future patch.
-
-Patch 2 splits "cur_link_an_mode" (the MLO_AN_* mode) into two separate
-purposes - a requested and an active mode. The active mode is the one
-we will be using for the MAC, which becomes dependent on the result of
-in-band negotiation.
-
-Patch 3 adds debug to phylink_major_config() so we can see what is going
-on with the requested and active AN modes.
-
-Patch 4 adds to phylib a method to get the in-band capabilities of the
-PHY from phylib. Patches 5 and 6 add implementations for BCM84881 and
-some Marvell PHYs found on SFPs.
-
-Patch 7 adds to phylib a method to configure the PHY in-band signalling,
-and patch 8 implements it for those Marvell PHYs that support the method
-in patch 4.
-
-Patch 9 does the same as patch 4 but for the MAC-side PCS, with patches
-10 through 14 adding support to several PCS.
-
-Patch 15 adds the code to phylink_pcs_neg_mode() which looks at the
-capabilities, and works out whether to use in-band or out-band mode for
-driving the link between the MAC PCS and PHY.
-
-Patch 16 removes the phylink_phy_no_inband() hack now that we are
-publishing the in-band capabilities from the BCM84881 PHY driver.
-
- drivers/net/ethernet/marvell/mvneta.c           |  27 +-
- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c |  25 +-
- drivers/net/pcs/pcs-lynx.c                      |  22 ++
- drivers/net/pcs/pcs-mtk-lynxi.c                 |  16 ++
- drivers/net/pcs/pcs-xpcs.c                      |  28 ++
- drivers/net/phy/bcm84881.c                      |  10 +
- drivers/net/phy/marvell.c                       |  48 ++++
- drivers/net/phy/phy.c                           |  52 ++++
- drivers/net/phy/phylink.c                       | 352 +++++++++++++++++++-----
- include/linux/phy.h                             |  34 +++
- include/linux/phylink.h                         |  17 ++
- 11 files changed, 539 insertions(+), 92 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);
- 
-@@ -74,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;
-@@ -175,6 +177,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) {
-@@ -988,6 +1008,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)
- {
-@@ -1041,6 +1070,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)
-@@ -1082,13 +1129,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,13 +1143,14 @@ 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);
- }
- 
- /**
-  * 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 +1167,21 @@ 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 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:
-@@ -1136,10 +1194,7 @@ static unsigned int phylink_pcs_neg_mode
- 		 * 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:
-@@ -1150,21 +1205,143 @@ static unsigned int phylink_pcs_neg_mode
- 		 * 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;
- 	}
- 
--	return neg_mode;
-+	pl->pcs_neg_mode = neg_mode;
-+	pl->act_link_an_mode = mode;
- }
- 
- static void phylink_major_config(struct phylink *pl, bool restart,
-@@ -1176,11 +1353,9 @@ static void phylink_major_config(struct
- 	unsigned int neg_mode;
- 	int err;
- 
--	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);
-+	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);
-@@ -1194,10 +1369,17 @@ static void phylink_major_config(struct
- 		pcs_changed = pcs && pl->pcs != pcs;
- 	}
- 
-+	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) {
--		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",
-@@ -1231,7 +1413,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;
- 
-@@ -1247,13 +1429,20 @@ 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",
- 				    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)
-@@ -1278,17 +1467,16 @@ 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);
- 
- 	/* 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;
-+	neg_mode = pl->act_link_an_mode;
- 	if (pl->pcs->neg_mode)
- 		neg_mode = pl->pcs_neg_mode;
- 
-@@ -1353,7 +1541,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 +1615,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 +1642,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");
- }
-@@ -1481,7 +1669,7 @@ static void phylink_resolve(struct work_
- 		link_state.link = false;
- 		retrigger = true;
- 	} else {
--		switch (pl->cur_link_an_mode) {
-+		switch (pl->act_link_an_mode) {
- 		case MLO_AN_PHY:
- 			link_state = pl->phy_state;
- 			phylink_apply_manual_flow(pl, &link_state);
-@@ -1671,7 +1859,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;
- }
-@@ -1766,7 +1954,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) {
-@@ -2242,7 +2430,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 */
-@@ -2501,7 +2689,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
-@@ -2532,6 +2720,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()
-@@ -2593,7 +2801,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;
-@@ -2609,7 +2817,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;
-@@ -2649,7 +2857,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;
-@@ -2667,6 +2875,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;
-@@ -2749,7 +2964,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) &&
-@@ -3013,7 +3228,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);
-@@ -3038,7 +3253,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;
- 
-@@ -3208,10 +3423,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",
-@@ -3228,9 +3444,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;
-@@ -3245,8 +3461,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);
-@@ -3285,8 +3500,7 @@ static int phylink_sfp_config_phy(struct
- 	ret = phylink_validate(pl, support1, &config);
- 	if (ret) {
- 		phylink_err(pl,
--			    "validation of %s/%s with support %*pb failed: %pe\n",
--			    phylink_an_mode_str(mode),
-+			    "validation of %s with support %*pb failed: %pe\n",
- 			    phy_modes(config.interface),
- 			    __ETHTOOL_LINK_MODE_MASK_NBITS, support,
- 			    ERR_PTR(ret));
-@@ -3295,7 +3509,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;
- }
-@@ -3351,6 +3565,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 */
-@@ -3364,7 +3584,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;
- }
-@@ -3435,20 +3655,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;
- 
- 	/*
-@@ -3460,17 +3670,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;
- 
---- a/drivers/net/phy/phy.c
-+++ b/drivers/net/phy/phy.c
-@@ -1049,6 +1049,58 @@ 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_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;
-+}
-+
-+/**
-  * _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.
-  *
-@@ -955,6 +973,19 @@ 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);
-+
-+	/**
-+	 * @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
-@@ -1840,6 +1871,9 @@ 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_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);
---- 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,
---- a/drivers/net/phy/marvell.c
-+++ b/drivers/net/phy/marvell.c
-@@ -716,6 +716,48 @@ 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_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);
-@@ -3667,6 +3709,8 @@ static struct phy_driver marvell_drivers
- 		.name = "Marvell 88E1112",
- 		/* 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,
-@@ -3688,6 +3732,8 @@ static struct phy_driver marvell_drivers
- 		/* PHY_GBIT_FEATURES */
- 		.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,
-@@ -3711,6 +3757,8 @@ static struct phy_driver marvell_drivers
- 		.name = "Marvell 88E1111 (Finisar)",
- 		/* 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,
---- 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.
-  */
---- 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,
---- 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,
---- 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,
---- a/drivers/net/pcs/pcs-mtk-lynxi.c
-+++ b/drivers/net/pcs/pcs-mtk-lynxi.c
-@@ -110,6 +110,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)
- {
-@@ -302,6 +317,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,
---- 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, 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,
diff --git a/target/linux/mvebu/patches-6.12/700-mvneta-tx-queue-workaround.patch b/target/linux/mvebu/patches-6.12/700-mvneta-tx-queue-workaround.patch
index 28aadad1ff..39112f23bb 100644
--- a/target/linux/mvebu/patches-6.12/700-mvneta-tx-queue-workaround.patch
+++ b/target/linux/mvebu/patches-6.12/700-mvneta-tx-queue-workaround.patch
@@ -14,7 +14,7 @@ Signed-off-by: Felix Fietkau <nbd at 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 at 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,
diff --git a/target/linux/siflower/patches-6.6/001-net-phy-c45-add-genphy_c45_pma_read_ext_abilities-fu.patch b/target/linux/siflower/patches-6.6/001-net-phy-c45-add-genphy_c45_pma_read_ext_abilities-fu.patch
index 98a6f07de8..e693e95cb0 100644
--- a/target/linux/siflower/patches-6.6/001-net-phy-c45-add-genphy_c45_pma_read_ext_abilities-fu.patch
+++ b/target/linux/siflower/patches-6.6/001-net-phy-c45-add-genphy_c45_pma_read_ext_abilities-fu.patch
@@ -170,7 +170,7 @@ Signed-off-by: Jakub Kicinski <kuba at 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);




More information about the lede-commits mailing list