From: Christian Marangi Date: Sun, 19 Oct 2025 23:36:34 +0000 (+0200) Subject: generic: backport phylink patches for PCS/PHY caps OPs X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F20461%2Fhead;p=thirdparty%2Fopenwrt.git 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 --- 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 00000000000..a9b86c25083 --- /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)" +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) +Link: https://patch.msgid.link/E1t9RQe-002Feh-T1@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..7ff091e85fa --- /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)" +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) +Link: https://patch.msgid.link/E1t9RQk-002Fen-1A@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..76e76fbba1d --- /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)" +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) +Link: https://patch.msgid.link/E1t9RQp-002Fet-5W@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..989fc10b716 --- /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)" +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) +Link: https://patch.msgid.link/E1t9RQu-002Fez-AA@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..285eea862eb --- /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)" +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) +Link: https://patch.msgid.link/E1t9RQz-002Ff5-EA@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..6868cd1518f --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUrP-006ITh-6u@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..76f4d5a48bf --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUrU-006ITn-Ai@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..ee625c74861 --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUrZ-006ITt-Fa@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..67f4f0be424 --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUre-006ITz-KF@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..0ba3cd28022 --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Acked-by: Florian Fainelli +Link: https://patch.msgid.link/E1tIUrj-006IU6-ON@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..fb5d9c20afd --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUro-006IUC-Rq@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..99f11fe07bf --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUru-006IUI-08@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..00788d42fc5 --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUrz-006IUO-3r@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..422802457e7 --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUs4-006IUU-7K@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..0937ad1388c --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUs9-006IUb-Au@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 = 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 00000000000..846d9df36de --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUsE-006IUh-E7@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + .../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 = 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 00000000000..f629133013b --- /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)" +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) +Link: https://patch.msgid.link/E1tIUsJ-006IUn-H3@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..8be74a2ad6b --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUsO-006IUt-KN@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..32ba605b1c4 --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tJ8NM-006L5J-AH@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..1cfd3bab9b6 --- /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)" +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) +Link: https://patch.msgid.link/E1tJ8NR-006L5P-E3@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..8dc495bd0c4 --- /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)" +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) +Link: https://patch.msgid.link/E1tJ8NW-006L5V-I9@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 6b85e59577a..3a6e0ac80a6 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 { 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 }; --- 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 9c317606e11..5563f3dce67 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 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 cda52269042..d2b20cc8a52 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 } --- 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 9e28011b0cc..dd24ba23700 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 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 00000000000..7de4f586f45 --- /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)" +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) +Link: https://patch.msgid.link/E1t9RQe-002Feh-T1@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..d81ab2af0da --- /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)" +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) +Link: https://patch.msgid.link/E1t9RQk-002Fen-1A@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..269c50a077c --- /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)" +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) +Link: https://patch.msgid.link/E1t9RQp-002Fet-5W@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..521da5f30b4 --- /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)" +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) +Link: https://patch.msgid.link/E1t9RQu-002Fez-AA@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..e5e2e165c8d --- /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)" +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) +Link: https://patch.msgid.link/E1t9RQz-002Ff5-EA@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..42715ef97f1 --- /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)" +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) +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + 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 00000000000..2150a4a3414 --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUrP-006ITh-6u@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..2cc97dd7355 --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUrU-006ITn-Ai@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..483fe07a437 --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUrZ-006ITt-Fa@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..dcff6b27d75 --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUre-006ITz-KF@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..a78fad173fa --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Acked-by: Florian Fainelli +Link: https://patch.msgid.link/E1tIUrj-006IU6-ON@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..c1f481e8087 --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUro-006IUC-Rq@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..652aaa1215d --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUru-006IUI-08@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..30c393d1528 --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUrz-006IUO-3r@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..2ca722b39ba --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUs4-006IUU-7K@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..b926312e794 --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUs9-006IUb-Au@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 = 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 00000000000..1ff6035a3d8 --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUsE-006IUh-E7@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + .../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 = 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 00000000000..cf234f806b4 --- /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)" +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) +Link: https://patch.msgid.link/E1tIUsJ-006IUn-H3@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..7c5d0393287 --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tIUsO-006IUt-KN@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..d5eb15d50d8 --- /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)" +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 +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1tJ8NM-006L5J-AH@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..1cfd3bab9b6 --- /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)" +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) +Link: https://patch.msgid.link/E1tJ8NR-006L5P-E3@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 00000000000..4945f7c04ca --- /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)" +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) +Link: https://patch.msgid.link/E1tJ8NW-006L5V-I9@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + 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 514a80b298d..3efeb04d8bc 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 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 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 d42da1b71fe..ae8a43feb17 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 * @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 1fdd91497b2..2fd03e920a0 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 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 4bb44b921d4..22179d8cc4b 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 } --- 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 b8460a2b5e2..b60ce1cfcfc 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 } --- 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 1c0b5d836db..639856fcb83 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 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 4d8742f0e33..bc58e99276a 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 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 /** * 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 1b979f8662a..aea1046add1 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 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 397780f7fdf..c73104522d5 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 --- 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 33f64e81c20..ed2f3485672 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 --- 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 e3915f06091..9f79748da90 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 --- 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 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 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 5f66869ef37..6e04ebeda4c 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 --- 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 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 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 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 e29503398e0..a02677d9a41 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 --- 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 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 86ed7a868ec..1d98dd1de0c 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 --- 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 /** * 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 /* 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 30a502a237c..bf26a2f6ec1 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 --- 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 } 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 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 30a502a237c..bf26a2f6ec1 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 --- 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 } 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 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 ed6c9070b24..f8bcf6744f7 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 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 6b2b016881d..0af507eed36 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 --- 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 /* 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 8eb9d35b580..0e4a63ec7fb 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 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 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 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 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 { 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 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 } 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 efa76572f86..3fe618ab9c1 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 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 78e0049f052..968fea4431f 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 --- 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 /* 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 faa7624307d..11cb53428fb 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 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 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 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 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 { 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 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 } 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 92e71276bf8..af14871b59f 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 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 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 b4e527214e8..975288871eb 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 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 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 12638978b3e..00000000000 --- 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)" -To: Andrew Lunn , Heiner Kallweit -Cc: Alexander Couzens , - Andrew Lunn , - AngeloGioacchino Del Regno - , - Broadcom internal kernel review list - , - Daniel Golle , - "David S. Miller" , - Eric Dumazet , - Florian Fainelli , - Ioana Ciornei , - Jakub Kicinski , - Jose Abreu , - linux-arm-kernel@lists.infradead.org, - linux-mediatek@lists.infradead.org, - Marcin Wojtas , - Matthias Brugger , - netdev@vger.kernel.org, Paolo Abeni -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: (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 = 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 = 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 28aadad1ffe..39112f23bb1 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 --- --- 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 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 98a6f07de80..e693e95cb0f 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 /* 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);