From: Robert Marko Date: Tue, 27 Feb 2024 18:07:42 +0000 (+0100) Subject: generic: backport QCA808x possible interfaces fix X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=f04e377a5003daa771414befdd9642e848cb42f9;p=openwrt%2Fstaging%2Fblocktrron.git generic: backport QCA808x possible interfaces fix QCA808x does not currently fill in the possible_interfaces. This leads to Phylink not being aware that it supports 2500Base-X as well so in cases where it is connected to a DSA switch like MV88E6393 it will limit that port to phy-mode set in the DTS. That means that if SGMII is used you are limited to 1G only while if 2500Base-X was set you are limited to 2.5G only. Populating the possible_interfaces fixes this, so lets backport the patches from kernel 6.9. This also includes a backport of the Phylink PHY validation series from kernel 6.8 that allows the use of possible_interfaces. Link: https://github.com/openwrt/openwrt/pull/15765 Signed-off-by: Robert Marko --- diff --git a/target/linux/generic/backport-6.1/895-01-v6.8-net-phy-add-possible-interfaces.patch b/target/linux/generic/backport-6.1/895-01-v6.8-net-phy-add-possible-interfaces.patch new file mode 100644 index 0000000000..3a9b856a20 --- /dev/null +++ b/target/linux/generic/backport-6.1/895-01-v6.8-net-phy-add-possible-interfaces.patch @@ -0,0 +1,60 @@ +From 1a7aa058bc92f0edae7a0d1ef1a7b05aec0c643a Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 24 Nov 2023 12:27:52 +0000 +Subject: [PATCH 1/7] net: phy: add possible interfaces + +Add a possible_interfaces member to struct phy_device to indicate which +interfaces a clause 45 PHY may switch between depending on the media. +This must be populated by the PHY driver by the time the .config_init() +method completes according to the PHYs host-side configuration. + +For example, the Marvell 88x3310 PHY can switch between 10GBASE-R, +5GBASE-R, 2500BASE-X, and SGMII on the host side depending on the media +side speed, so all these interface modes are set in the +possible_interfaces member. + +This allows phylib users (such as phylink) to know in advance which +interface modes to expect, which allows them to appropriately restrict +the advertised link modes according to the capabilities of other parts +of the link. + +Tested-by: Luo Jie +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/E1r6VHk-00DDLN-I7@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phy_device.c | 2 ++ + include/linux/phy.h | 3 +++ + 2 files changed, 5 insertions(+) + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -1215,6 +1215,8 @@ int phy_init_hw(struct phy_device *phyde + if (ret < 0) + return ret; + ++ phy_interface_zero(phydev->possible_interfaces); ++ + if (phydev->drv->config_init) { + ret = phydev->drv->config_init(phydev); + if (ret < 0) +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -600,6 +600,8 @@ struct macsec_ops; + * @irq_rerun: Flag indicating interrupts occurred while PHY was suspended, + * requiring a rerun of the interrupt handler after resume + * @interface: enum phy_interface_t value ++ * @possible_interfaces: bitmap if interface modes that the attached PHY ++ * will switch between depending on media speed. + * @skb: Netlink message for cable diagnostics + * @nest: Netlink nest used for cable diagnostics + * @ehdr: nNtlink header for cable diagnostics +@@ -665,6 +667,7 @@ struct phy_device { + u32 dev_flags; + + phy_interface_t interface; ++ DECLARE_PHY_INTERFACE_MASK(possible_interfaces); + + /* + * forced speed & duplex (no autoneg) diff --git a/target/linux/generic/backport-6.1/895-02-v6.8-net-phylink-use-for_each_set_bit.patch b/target/linux/generic/backport-6.1/895-02-v6.8-net-phylink-use-for_each_set_bit.patch new file mode 100644 index 0000000000..155ec1c2d9 --- /dev/null +++ b/target/linux/generic/backport-6.1/895-02-v6.8-net-phylink-use-for_each_set_bit.patch @@ -0,0 +1,46 @@ +From 85631f5b33f2acce7d42dec1d0a062ab40de95b8 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Sun, 19 Nov 2023 21:07:43 +0000 +Subject: [PATCH 2/7] net: phylink: use for_each_set_bit() + +Use for_each_set_bit() rather than open coding the for() test_bit() +loop. + +Reviewed-by: Andrew Lunn +Signed-off-by: Russell King (Oracle) +Reviewed-by: Wojciech Drewek +Link: https://lore.kernel.org/r/E1r4p15-00Cpxe-C7@rmk-PC.armlinux.org.uk +Signed-off-by: Paolo Abeni +--- + drivers/net/phy/phylink.c | 18 ++++++++---------- + 1 file changed, 8 insertions(+), 10 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -690,18 +690,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; +- int intf; ++ int interface; + +- for (intf = 0; intf < PHY_INTERFACE_MODE_MAX; intf++) { +- if (test_bit(intf, interfaces)) { +- linkmode_copy(s, supported); ++ for_each_set_bit(interface, interfaces, PHY_INTERFACE_MODE_MAX) { ++ linkmode_copy(s, supported); + +- t = *state; +- t.interface = intf; +- if (!phylink_validate_mac_and_pcs(pl, s, &t)) { +- linkmode_or(all_s, all_s, s); +- linkmode_or(all_adv, all_adv, t.advertising); +- } ++ t = *state; ++ t.interface = interface; ++ if (!phylink_validate_mac_and_pcs(pl, s, &t)) { ++ linkmode_or(all_s, all_s, s); ++ linkmode_or(all_adv, all_adv, t.advertising); + } + } + diff --git a/target/linux/generic/backport-6.1/895-03-v6.8-net-phylink-split-out-per-interface-validation.patch b/target/linux/generic/backport-6.1/895-03-v6.8-net-phylink-split-out-per-interface-validation.patch new file mode 100644 index 0000000000..163cb953f7 --- /dev/null +++ b/target/linux/generic/backport-6.1/895-03-v6.8-net-phylink-split-out-per-interface-validation.patch @@ -0,0 +1,76 @@ +From d4788b4383ce5caeb4e68818357c81a02117a3f9 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 24 Nov 2023 12:28:19 +0000 +Subject: [PATCH 3/7] net: phylink: split out per-interface validation + +Split out the internals of phylink_validate_mask() to make the code +easier to read. + +Tested-by: Luo Jie +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/E1r6VIB-00DDLr-7g@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 42 ++++++++++++++++++++++++++++----------- + 1 file changed, 30 insertions(+), 12 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -682,26 +682,44 @@ static int phylink_validate_mac_and_pcs( + return phylink_is_empty_linkmode(supported) ? -EINVAL : 0; + } + ++static void phylink_validate_one(struct phylink *pl, ++ const unsigned long *supported, ++ const struct phylink_link_state *state, ++ phy_interface_t interface, ++ unsigned long *accum_supported, ++ unsigned long *accum_advertising) ++{ ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(tmp_supported); ++ struct phylink_link_state tmp_state; ++ ++ linkmode_copy(tmp_supported, supported); ++ ++ tmp_state = *state; ++ tmp_state.interface = interface; ++ ++ 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), ++ phy_rate_matching_to_str(tmp_state.rate_matching), ++ __ETHTOOL_LINK_MODE_MASK_NBITS, tmp_supported); ++ ++ linkmode_or(accum_supported, accum_supported, tmp_supported); ++ linkmode_or(accum_advertising, accum_advertising, ++ tmp_state.advertising); ++ } ++} ++ + static int phylink_validate_mask(struct phylink *pl, unsigned long *supported, + struct phylink_link_state *state, + const unsigned long *interfaces) + { + __ETHTOOL_DECLARE_LINK_MODE_MASK(all_adv) = { 0, }; + __ETHTOOL_DECLARE_LINK_MODE_MASK(all_s) = { 0, }; +- __ETHTOOL_DECLARE_LINK_MODE_MASK(s); +- struct phylink_link_state t; + int interface; + +- for_each_set_bit(interface, interfaces, PHY_INTERFACE_MODE_MAX) { +- linkmode_copy(s, supported); +- +- t = *state; +- t.interface = interface; +- if (!phylink_validate_mac_and_pcs(pl, s, &t)) { +- linkmode_or(all_s, all_s, s); +- linkmode_or(all_adv, all_adv, t.advertising); +- } +- } ++ for_each_set_bit(interface, interfaces, PHY_INTERFACE_MODE_MAX) ++ phylink_validate_one(pl, supported, state, interface, ++ all_s, all_adv); + + linkmode_copy(supported, all_s); + linkmode_copy(state->advertising, all_adv); diff --git a/target/linux/generic/backport-6.1/895-04-v6.8-net-phylink-pass-PHY-into-phylink_validate_one.patch b/target/linux/generic/backport-6.1/895-04-v6.8-net-phylink-pass-PHY-into-phylink_validate_one.patch new file mode 100644 index 0000000000..5012020676 --- /dev/null +++ b/target/linux/generic/backport-6.1/895-04-v6.8-net-phylink-pass-PHY-into-phylink_validate_one.patch @@ -0,0 +1,47 @@ +From ce7273c31fadb3143fc80c96a72a42adc19c2757 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 24 Nov 2023 12:28:24 +0000 +Subject: [PATCH 4/7] net: phylink: pass PHY into phylink_validate_one() + +Pass the phy (if any) into phylink_validate_one() so that we can +validate each interface with its rate matching setting. + +Tested-by: Luo Jie +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/E1r6VIG-00DDLx-Cb@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -682,7 +682,7 @@ static int phylink_validate_mac_and_pcs( + return phylink_is_empty_linkmode(supported) ? -EINVAL : 0; + } + +-static void phylink_validate_one(struct phylink *pl, ++static void phylink_validate_one(struct phylink *pl, struct phy_device *phy, + const unsigned long *supported, + const struct phylink_link_state *state, + phy_interface_t interface, +@@ -697,6 +697,9 @@ static void phylink_validate_one(struct + tmp_state = *state; + tmp_state.interface = interface; + ++ if (phy) ++ tmp_state.rate_matching = phy_get_rate_matching(phy, interface); ++ + 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), +@@ -718,7 +721,7 @@ static int phylink_validate_mask(struct + int interface; + + for_each_set_bit(interface, interfaces, PHY_INTERFACE_MODE_MAX) +- phylink_validate_one(pl, supported, state, interface, ++ phylink_validate_one(pl, NULL, supported, state, interface, + all_s, all_adv); + + linkmode_copy(supported, all_s); diff --git a/target/linux/generic/backport-6.1/895-05-v6.8-net-phylink-pass-PHY-into-phylink_validate_mask.patch b/target/linux/generic/backport-6.1/895-05-v6.8-net-phylink-pass-PHY-into-phylink_validate_mask.patch new file mode 100644 index 0000000000..997c74346c --- /dev/null +++ b/target/linux/generic/backport-6.1/895-05-v6.8-net-phylink-pass-PHY-into-phylink_validate_mask.patch @@ -0,0 +1,58 @@ +From c6fec66d3cd76d797f70b30f1511bed10ba45a96 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 24 Nov 2023 12:28:29 +0000 +Subject: [PATCH 5/7] net: phylink: pass PHY into phylink_validate_mask() + +Pass the phy (if any) into phylink_validate_mask() so that we can +validate each interface with its rate matching setting. + +Tested-by: Luo Jie +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/E1r6VIL-00DDM3-HJ@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -712,7 +712,8 @@ static void phylink_validate_one(struct + } + } + +-static int phylink_validate_mask(struct phylink *pl, unsigned long *supported, ++static int phylink_validate_mask(struct phylink *pl, struct phy_device *phy, ++ unsigned long *supported, + struct phylink_link_state *state, + const unsigned long *interfaces) + { +@@ -721,7 +722,7 @@ static int phylink_validate_mask(struct + int interface; + + for_each_set_bit(interface, interfaces, PHY_INTERFACE_MODE_MAX) +- phylink_validate_one(pl, NULL, supported, state, interface, ++ phylink_validate_one(pl, phy, supported, state, interface, + all_s, all_adv); + + linkmode_copy(supported, all_s); +@@ -736,7 +737,8 @@ static int phylink_validate(struct phyli + const unsigned long *interfaces = pl->config->supported_interfaces; + + if (state->interface == PHY_INTERFACE_MODE_NA) +- return phylink_validate_mask(pl, supported, state, interfaces); ++ return phylink_validate_mask(pl, NULL, supported, state, ++ interfaces); + + if (!test_bit(state->interface, interfaces)) + return -EINVAL; +@@ -3132,7 +3134,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. + */ +- ret = phylink_validate_mask(pl, pl->sfp_support, &config, interfaces); ++ ret = phylink_validate_mask(pl, NULL, pl->sfp_support, &config, ++ interfaces); + if (ret) { + phylink_err(pl, "unsupported SFP module: validation with support %*pb failed\n", + __ETHTOOL_LINK_MODE_MASK_NBITS, support); diff --git a/target/linux/generic/backport-6.1/895-06-v6.8-net-phylink-split-out-PHY-validation-from-phylink_br.patch b/target/linux/generic/backport-6.1/895-06-v6.8-net-phylink-split-out-PHY-validation-from-phylink_br.patch new file mode 100644 index 0000000000..d3d24c58fb --- /dev/null +++ b/target/linux/generic/backport-6.1/895-06-v6.8-net-phylink-split-out-PHY-validation-from-phylink_br.patch @@ -0,0 +1,95 @@ +From ee0e0ddb910e7e989b65a19d72b6435baa641fc7 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 24 Nov 2023 12:28:34 +0000 +Subject: [PATCH 6/7] net: phylink: split out PHY validation from + phylink_bringup_phy() + +When bringing up a PHY, we need to work out which ethtool link modes it +should support and advertise. Clause 22 PHYs operate in a single +interface mode, which can be easily dealt with. However, clause 45 PHYs +tend to switch interface mode depending on the media. We need more +flexible validation at this point, so this patch splits out that code +in preparation to changing it. + +Tested-by: Luo Jie +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/E1r6VIQ-00DDM9-LK@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 56 ++++++++++++++++++++++----------------- + 1 file changed, 31 insertions(+), 25 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -1738,6 +1738,35 @@ static void phylink_phy_change(struct ph + phylink_pause_to_str(pl->phy_state.pause)); + } + ++static int phylink_validate_phy(struct phylink *pl, struct phy_device *phy, ++ unsigned long *supported, ++ struct phylink_link_state *state) ++{ ++ /* Check whether we would use rate matching for the proposed interface ++ * mode. ++ */ ++ state->rate_matching = phy_get_rate_matching(phy, state->interface); ++ ++ /* Clause 45 PHYs may switch their Serdes lane between, e.g. 10GBASE-R, ++ * 5GBASE-R, 2500BASE-X and SGMII if they are not using rate matching. ++ * For some interface modes (e.g. RXAUI, XAUI and USXGMII) switching ++ * their Serdes is either unnecessary or not reasonable. ++ * ++ * For these which switch interface modes, we really need to know which ++ * interface modes the PHY supports to properly work out which ethtool ++ * linkmodes can be supported. For now, as a work-around, we validate ++ * against all interface modes, which may lead to more ethtool link ++ * modes being advertised than are actually supported. ++ */ ++ if (phy->is_c45 && state->rate_matching == RATE_MATCH_NONE && ++ state->interface != PHY_INTERFACE_MODE_RXAUI && ++ state->interface != PHY_INTERFACE_MODE_XAUI && ++ state->interface != PHY_INTERFACE_MODE_USXGMII) ++ state->interface = PHY_INTERFACE_MODE_NA; ++ ++ return phylink_validate(pl, supported, state); ++} ++ + static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy, + phy_interface_t interface) + { +@@ -1758,32 +1787,9 @@ static int phylink_bringup_phy(struct ph + memset(&config, 0, sizeof(config)); + linkmode_copy(supported, phy->supported); + linkmode_copy(config.advertising, phy->advertising); ++ config.interface = interface; + +- /* Check whether we would use rate matching for the proposed interface +- * mode. +- */ +- config.rate_matching = phy_get_rate_matching(phy, interface); +- +- /* Clause 45 PHYs may switch their Serdes lane between, e.g. 10GBASE-R, +- * 5GBASE-R, 2500BASE-X and SGMII if they are not using rate matching. +- * For some interface modes (e.g. RXAUI, XAUI and USXGMII) switching +- * their Serdes is either unnecessary or not reasonable. +- * +- * For these which switch interface modes, we really need to know which +- * interface modes the PHY supports to properly work out which ethtool +- * linkmodes can be supported. For now, as a work-around, we validate +- * against all interface modes, which may lead to more ethtool link +- * modes being advertised than are actually supported. +- */ +- if (phy->is_c45 && config.rate_matching == RATE_MATCH_NONE && +- interface != PHY_INTERFACE_MODE_RXAUI && +- interface != PHY_INTERFACE_MODE_XAUI && +- interface != PHY_INTERFACE_MODE_USXGMII) +- config.interface = PHY_INTERFACE_MODE_NA; +- else +- config.interface = interface; +- +- ret = phylink_validate(pl, supported, &config); ++ ret = phylink_validate_phy(pl, phy, supported, &config); + if (ret) { + phylink_warn(pl, "validation of %s with support %*pb and advertisement %*pb failed: %pe\n", + phy_modes(config.interface), diff --git a/target/linux/generic/backport-6.1/895-07-v6.8-net-phylink-use-the-PHY-s-possible_interfaces-if-pop.patch b/target/linux/generic/backport-6.1/895-07-v6.8-net-phylink-use-the-PHY-s-possible_interfaces-if-pop.patch new file mode 100644 index 0000000000..201afbb7cf --- /dev/null +++ b/target/linux/generic/backport-6.1/895-07-v6.8-net-phylink-use-the-PHY-s-possible_interfaces-if-pop.patch @@ -0,0 +1,130 @@ +From 8f7a9799c5949f94ecc3acfd71b36437a7ade73b Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 24 Nov 2023 12:28:39 +0000 +Subject: [PATCH 7/7] net: phylink: use the PHY's possible_interfaces if + populated + +Some PHYs such as Aquantia, Broadcom 84881, and Marvell 88X33x0 can +switch between a set of interface types depending on the negotiated +media speed, or can use rate adaption for some or all of these +interface types. + +We currently assume that these are Clause 45 PHYs that are configured +not to use a specific set of interface modes, which has worked so far, +but is just a work-around. In this workaround, we validate using all +interfaces that the MAC supports, which can lead to extra modes being +advertised that can not be supported. + +To properly address this, switch to using the newly introduced PHY +possible_interfaces bitmap which indicates which interface modes will +be used by the PHY as configured. We calculate the union of the PHY's +possible interfaces and MACs supported interfaces, checking that is +non-empty. If the PHY is on a SFP, we further reduce the set by those +which can be used on a SFP module, again checking that is non-empty. +Finally, we validate the subset of interfaces, taking account of +whether rate matching will be used for each individual interface mode. + +This becomes independent of whether the PHY is clause 22 or clause 45. + +It is encouraged that all PHYs that switch interface modes or use +rate matching should populate phydev->possible_interfaces. + +Tested-by: Luo Jie +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/E1r6VIV-00DDMF-Pi@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 67 +++++++++++++++++++++++++++++++-------- + 1 file changed, 54 insertions(+), 13 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -121,6 +121,19 @@ do { \ + }) + #endif + ++static const phy_interface_t phylink_sfp_interface_preference[] = { ++ PHY_INTERFACE_MODE_25GBASER, ++ PHY_INTERFACE_MODE_USXGMII, ++ PHY_INTERFACE_MODE_10GBASER, ++ PHY_INTERFACE_MODE_5GBASER, ++ PHY_INTERFACE_MODE_2500BASEX, ++ PHY_INTERFACE_MODE_SGMII, ++ PHY_INTERFACE_MODE_1000BASEX, ++ PHY_INTERFACE_MODE_100BASEX, ++}; ++ ++static DECLARE_PHY_INTERFACE_MASK(phylink_sfp_interfaces); ++ + /** + * phylink_set_port_modes() - set the port type modes in the ethtool mask + * @mask: ethtool link mode mask +@@ -1742,6 +1755,47 @@ static int phylink_validate_phy(struct p + unsigned long *supported, + struct phylink_link_state *state) + { ++ DECLARE_PHY_INTERFACE_MASK(interfaces); ++ ++ /* If the PHY provides a bitmap of the interfaces it will be using ++ * depending on the negotiated media speeds, use this to validate ++ * which ethtool link modes can be used. ++ */ ++ if (!phy_interface_empty(phy->possible_interfaces)) { ++ /* We only care about the union of the PHY's interfaces and ++ * those which the host supports. ++ */ ++ phy_interface_and(interfaces, phy->possible_interfaces, ++ pl->config->supported_interfaces); ++ ++ if (phy_interface_empty(interfaces)) { ++ phylink_err(pl, "PHY has no common interfaces\n"); ++ return -EINVAL; ++ } ++ ++ if (phy_on_sfp(phy)) { ++ /* If the PHY is on a SFP, limit the interfaces to ++ * those that can be used with a SFP module. ++ */ ++ phy_interface_and(interfaces, interfaces, ++ phylink_sfp_interfaces); ++ ++ if (phy_interface_empty(interfaces)) { ++ phylink_err(pl, "SFP PHY's possible interfaces becomes empty\n"); ++ return -EINVAL; ++ } ++ } ++ ++ phylink_dbg(pl, "PHY %s uses interfaces %*pbl, validating %*pbl\n", ++ phydev_name(phy), ++ (int)PHY_INTERFACE_MODE_MAX, ++ phy->possible_interfaces, ++ (int)PHY_INTERFACE_MODE_MAX, interfaces); ++ ++ return phylink_validate_mask(pl, phy, supported, state, ++ interfaces); ++ } ++ + /* Check whether we would use rate matching for the proposed interface + * mode. + */ +@@ -2985,19 +3039,6 @@ static void phylink_sfp_detach(void *ups + pl->netdev->sfp_bus = NULL; + } + +-static const phy_interface_t phylink_sfp_interface_preference[] = { +- PHY_INTERFACE_MODE_25GBASER, +- PHY_INTERFACE_MODE_USXGMII, +- PHY_INTERFACE_MODE_10GBASER, +- PHY_INTERFACE_MODE_5GBASER, +- PHY_INTERFACE_MODE_2500BASEX, +- PHY_INTERFACE_MODE_SGMII, +- PHY_INTERFACE_MODE_1000BASEX, +- PHY_INTERFACE_MODE_100BASEX, +-}; +- +-static DECLARE_PHY_INTERFACE_MASK(phylink_sfp_interfaces); +- + static phy_interface_t phylink_choose_sfp_interface(struct phylink *pl, + const unsigned long *intf) + { diff --git a/target/linux/generic/backport-6.1/897-01-v6.9-net-phy-qcom-qca808x-add-helper-for-checking-for-1G-.patch b/target/linux/generic/backport-6.1/897-01-v6.9-net-phy-qcom-qca808x-add-helper-for-checking-for-1G-.patch new file mode 100644 index 0000000000..a11e804958 --- /dev/null +++ b/target/linux/generic/backport-6.1/897-01-v6.9-net-phy-qcom-qca808x-add-helper-for-checking-for-1G-.patch @@ -0,0 +1,50 @@ +From f058b2dd70b1a5503dff899010aeb53b436091e5 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 28 Feb 2024 18:24:09 +0100 +Subject: [PATCH 1/2] net: phy: qcom: qca808x: add helper for checking for 1G + only model + +There are 2 versions of QCA808x, one 2.5G capable and one 1G capable. +Currently, this matter only in the .get_features call however, it will +be required for filling supported interface modes so lets add a helper +that can be reused. + +Signed-off-by: Robert Marko +Signed-off-by: David S. Miller +--- + drivers/net/phy/qcom/qca808x.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +--- a/drivers/net/phy/qcom/qca808x.c ++++ b/drivers/net/phy/qcom/qca808x.c +@@ -156,6 +156,17 @@ static bool qca808x_has_fast_retrain_or_ + return linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); + } + ++static bool qca808x_is_1g_only(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_CHIP_TYPE); ++ if (ret < 0) ++ return true; ++ ++ return !!(QCA808X_PHY_CHIP_TYPE_1G & ret); ++} ++ + static int qca808x_probe(struct phy_device *phydev) + { + struct device *dev = &phydev->mdio.dev; +@@ -350,11 +361,7 @@ static int qca808x_get_features(struct p + * existed in the bit0 of MMD1.21, we need to remove it manually if + * it is the qca8081 1G chip according to the bit0 of MMD7.0x901d. + */ +- ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_CHIP_TYPE); +- if (ret < 0) +- return ret; +- +- if (QCA808X_PHY_CHIP_TYPE_1G & ret) ++ if (qca808x_is_1g_only(phydev)) + linkmode_clear_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); + + return 0; diff --git a/target/linux/generic/backport-6.1/897-02-v6.9-net-phy-qcom-qca808x-fill-in-possible_interfaces.patch b/target/linux/generic/backport-6.1/897-02-v6.9-net-phy-qcom-qca808x-fill-in-possible_interfaces.patch new file mode 100644 index 0000000000..c162fc7348 --- /dev/null +++ b/target/linux/generic/backport-6.1/897-02-v6.9-net-phy-qcom-qca808x-fill-in-possible_interfaces.patch @@ -0,0 +1,44 @@ +From cb28f702960695e26597c332b0e46776e825cc34 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 28 Feb 2024 18:24:10 +0100 +Subject: [PATCH 2/2] net: phy: qcom: qca808x: fill in possible_interfaces + +Currently QCA808x driver does not fill the possible_interfaces. +2.5G QCA808x support SGMII and 2500Base-X while 1G model only supports +SGMII, so fill the possible_interfaces accordingly. + +Signed-off-by: Robert Marko +Reviewed-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/qcom/qca808x.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/drivers/net/phy/qcom/qca808x.c ++++ b/drivers/net/phy/qcom/qca808x.c +@@ -167,6 +167,16 @@ static bool qca808x_is_1g_only(struct ph + return !!(QCA808X_PHY_CHIP_TYPE_1G & ret); + } + ++static void qca808x_fill_possible_interfaces(struct phy_device *phydev) ++{ ++ unsigned long *possible = phydev->possible_interfaces; ++ ++ __set_bit(PHY_INTERFACE_MODE_SGMII, possible); ++ ++ if (!qca808x_is_1g_only(phydev)) ++ __set_bit(PHY_INTERFACE_MODE_2500BASEX, possible); ++} ++ + static int qca808x_probe(struct phy_device *phydev) + { + struct device *dev = &phydev->mdio.dev; +@@ -231,6 +241,8 @@ static int qca808x_config_init(struct ph + } + } + ++ qca808x_fill_possible_interfaces(phydev); ++ + /* Configure adc threshold as 100mv for the link 10M */ + return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD, + QCA808X_ADC_THRESHOLD_MASK, diff --git a/target/linux/generic/backport-6.6/895-01-v6.8-net-phy-add-possible-interfaces.patch b/target/linux/generic/backport-6.6/895-01-v6.8-net-phy-add-possible-interfaces.patch new file mode 100644 index 0000000000..b86dbea898 --- /dev/null +++ b/target/linux/generic/backport-6.6/895-01-v6.8-net-phy-add-possible-interfaces.patch @@ -0,0 +1,60 @@ +From 1a7aa058bc92f0edae7a0d1ef1a7b05aec0c643a Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 24 Nov 2023 12:27:52 +0000 +Subject: [PATCH 1/7] net: phy: add possible interfaces + +Add a possible_interfaces member to struct phy_device to indicate which +interfaces a clause 45 PHY may switch between depending on the media. +This must be populated by the PHY driver by the time the .config_init() +method completes according to the PHYs host-side configuration. + +For example, the Marvell 88x3310 PHY can switch between 10GBASE-R, +5GBASE-R, 2500BASE-X, and SGMII on the host side depending on the media +side speed, so all these interface modes are set in the +possible_interfaces member. + +This allows phylib users (such as phylink) to know in advance which +interface modes to expect, which allows them to appropriately restrict +the advertised link modes according to the capabilities of other parts +of the link. + +Tested-by: Luo Jie +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/E1r6VHk-00DDLN-I7@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phy_device.c | 2 ++ + include/linux/phy.h | 3 +++ + 2 files changed, 5 insertions(+) + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -1247,6 +1247,8 @@ int phy_init_hw(struct phy_device *phyde + if (ret < 0) + return ret; + ++ phy_interface_zero(phydev->possible_interfaces); ++ + if (phydev->drv->config_init) { + ret = phydev->drv->config_init(phydev); + if (ret < 0) +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -609,6 +609,8 @@ struct macsec_ops; + * @irq_rerun: Flag indicating interrupts occurred while PHY was suspended, + * requiring a rerun of the interrupt handler after resume + * @interface: enum phy_interface_t value ++ * @possible_interfaces: bitmap if interface modes that the attached PHY ++ * will switch between depending on media speed. + * @skb: Netlink message for cable diagnostics + * @nest: Netlink nest used for cable diagnostics + * @ehdr: nNtlink header for cable diagnostics +@@ -678,6 +680,7 @@ struct phy_device { + u32 dev_flags; + + phy_interface_t interface; ++ DECLARE_PHY_INTERFACE_MASK(possible_interfaces); + + /* + * forced speed & duplex (no autoneg) 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 new file mode 100644 index 0000000000..397780f7fd --- /dev/null +++ b/target/linux/generic/backport-6.6/895-02-v6.8-net-phylink-use-for_each_set_bit.patch @@ -0,0 +1,46 @@ +From 85631f5b33f2acce7d42dec1d0a062ab40de95b8 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Sun, 19 Nov 2023 21:07:43 +0000 +Subject: [PATCH 2/7] net: phylink: use for_each_set_bit() + +Use for_each_set_bit() rather than open coding the for() test_bit() +loop. + +Reviewed-by: Andrew Lunn +Signed-off-by: Russell King (Oracle) +Reviewed-by: Wojciech Drewek +Link: https://lore.kernel.org/r/E1r4p15-00Cpxe-C7@rmk-PC.armlinux.org.uk +Signed-off-by: Paolo Abeni +--- + drivers/net/phy/phylink.c | 18 ++++++++---------- + 1 file changed, 8 insertions(+), 10 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -712,18 +712,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; +- int intf; ++ int interface; + +- for (intf = 0; intf < PHY_INTERFACE_MODE_MAX; intf++) { +- if (test_bit(intf, interfaces)) { +- linkmode_copy(s, supported); ++ for_each_set_bit(interface, interfaces, PHY_INTERFACE_MODE_MAX) { ++ linkmode_copy(s, supported); + +- t = *state; +- t.interface = intf; +- if (!phylink_validate_mac_and_pcs(pl, s, &t)) { +- linkmode_or(all_s, all_s, s); +- linkmode_or(all_adv, all_adv, t.advertising); +- } ++ t = *state; ++ t.interface = interface; ++ if (!phylink_validate_mac_and_pcs(pl, s, &t)) { ++ linkmode_or(all_s, all_s, s); ++ linkmode_or(all_adv, all_adv, t.advertising); + } + } + 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 new file mode 100644 index 0000000000..33f64e81c2 --- /dev/null +++ b/target/linux/generic/backport-6.6/895-03-v6.8-net-phylink-split-out-per-interface-validation.patch @@ -0,0 +1,76 @@ +From d4788b4383ce5caeb4e68818357c81a02117a3f9 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 24 Nov 2023 12:28:19 +0000 +Subject: [PATCH 3/7] net: phylink: split out per-interface validation + +Split out the internals of phylink_validate_mask() to make the code +easier to read. + +Tested-by: Luo Jie +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/E1r6VIB-00DDLr-7g@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 42 ++++++++++++++++++++++++++++----------- + 1 file changed, 30 insertions(+), 12 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -704,26 +704,44 @@ static int phylink_validate_mac_and_pcs( + return phylink_is_empty_linkmode(supported) ? -EINVAL : 0; + } + ++static void phylink_validate_one(struct phylink *pl, ++ const unsigned long *supported, ++ const struct phylink_link_state *state, ++ phy_interface_t interface, ++ unsigned long *accum_supported, ++ unsigned long *accum_advertising) ++{ ++ __ETHTOOL_DECLARE_LINK_MODE_MASK(tmp_supported); ++ struct phylink_link_state tmp_state; ++ ++ linkmode_copy(tmp_supported, supported); ++ ++ tmp_state = *state; ++ tmp_state.interface = interface; ++ ++ 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), ++ phy_rate_matching_to_str(tmp_state.rate_matching), ++ __ETHTOOL_LINK_MODE_MASK_NBITS, tmp_supported); ++ ++ linkmode_or(accum_supported, accum_supported, tmp_supported); ++ linkmode_or(accum_advertising, accum_advertising, ++ tmp_state.advertising); ++ } ++} ++ + static int phylink_validate_mask(struct phylink *pl, unsigned long *supported, + struct phylink_link_state *state, + const unsigned long *interfaces) + { + __ETHTOOL_DECLARE_LINK_MODE_MASK(all_adv) = { 0, }; + __ETHTOOL_DECLARE_LINK_MODE_MASK(all_s) = { 0, }; +- __ETHTOOL_DECLARE_LINK_MODE_MASK(s); +- struct phylink_link_state t; + int interface; + +- for_each_set_bit(interface, interfaces, PHY_INTERFACE_MODE_MAX) { +- linkmode_copy(s, supported); +- +- t = *state; +- t.interface = interface; +- if (!phylink_validate_mac_and_pcs(pl, s, &t)) { +- linkmode_or(all_s, all_s, s); +- linkmode_or(all_adv, all_adv, t.advertising); +- } +- } ++ for_each_set_bit(interface, interfaces, PHY_INTERFACE_MODE_MAX) ++ phylink_validate_one(pl, supported, state, interface, ++ all_s, all_adv); + + linkmode_copy(supported, all_s); + linkmode_copy(state->advertising, all_adv); 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 new file mode 100644 index 0000000000..e3915f0609 --- /dev/null +++ b/target/linux/generic/backport-6.6/895-04-v6.8-net-phylink-pass-PHY-into-phylink_validate_one.patch @@ -0,0 +1,47 @@ +From ce7273c31fadb3143fc80c96a72a42adc19c2757 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 24 Nov 2023 12:28:24 +0000 +Subject: [PATCH 4/7] net: phylink: pass PHY into phylink_validate_one() + +Pass the phy (if any) into phylink_validate_one() so that we can +validate each interface with its rate matching setting. + +Tested-by: Luo Jie +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/E1r6VIG-00DDLx-Cb@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -704,7 +704,7 @@ static int phylink_validate_mac_and_pcs( + return phylink_is_empty_linkmode(supported) ? -EINVAL : 0; + } + +-static void phylink_validate_one(struct phylink *pl, ++static void phylink_validate_one(struct phylink *pl, struct phy_device *phy, + const unsigned long *supported, + const struct phylink_link_state *state, + phy_interface_t interface, +@@ -719,6 +719,9 @@ static void phylink_validate_one(struct + tmp_state = *state; + tmp_state.interface = interface; + ++ if (phy) ++ tmp_state.rate_matching = phy_get_rate_matching(phy, interface); ++ + 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 + int interface; + + for_each_set_bit(interface, interfaces, PHY_INTERFACE_MODE_MAX) +- phylink_validate_one(pl, supported, state, interface, ++ phylink_validate_one(pl, NULL, supported, state, interface, + all_s, all_adv); + + linkmode_copy(supported, all_s); 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 new file mode 100644 index 0000000000..5f66869ef3 --- /dev/null +++ b/target/linux/generic/backport-6.6/895-05-v6.8-net-phylink-pass-PHY-into-phylink_validate_mask.patch @@ -0,0 +1,58 @@ +From c6fec66d3cd76d797f70b30f1511bed10ba45a96 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 24 Nov 2023 12:28:29 +0000 +Subject: [PATCH 5/7] net: phylink: pass PHY into phylink_validate_mask() + +Pass the phy (if any) into phylink_validate_mask() so that we can +validate each interface with its rate matching setting. + +Tested-by: Luo Jie +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/E1r6VIL-00DDM3-HJ@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -734,7 +734,8 @@ static void phylink_validate_one(struct + } + } + +-static int phylink_validate_mask(struct phylink *pl, unsigned long *supported, ++static int phylink_validate_mask(struct phylink *pl, struct phy_device *phy, ++ unsigned long *supported, + struct phylink_link_state *state, + const unsigned long *interfaces) + { +@@ -743,7 +744,7 @@ static int phylink_validate_mask(struct + int interface; + + for_each_set_bit(interface, interfaces, PHY_INTERFACE_MODE_MAX) +- phylink_validate_one(pl, NULL, supported, state, interface, ++ phylink_validate_one(pl, phy, supported, state, interface, + all_s, all_adv); + + linkmode_copy(supported, all_s); +@@ -758,7 +759,8 @@ static int phylink_validate(struct phyli + const unsigned long *interfaces = pl->config->supported_interfaces; + + if (state->interface == PHY_INTERFACE_MODE_NA) +- return phylink_validate_mask(pl, supported, state, interfaces); ++ return phylink_validate_mask(pl, NULL, supported, state, ++ interfaces); + + if (!test_bit(state->interface, interfaces)) + return -EINVAL; +@@ -3194,7 +3196,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. + */ +- ret = phylink_validate_mask(pl, pl->sfp_support, &config, interfaces); ++ ret = phylink_validate_mask(pl, NULL, pl->sfp_support, &config, ++ interfaces); + if (ret) { + phylink_err(pl, "unsupported SFP module: validation with support %*pb failed\n", + __ETHTOOL_LINK_MODE_MASK_NBITS, support); 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 new file mode 100644 index 0000000000..e29503398e --- /dev/null +++ b/target/linux/generic/backport-6.6/895-06-v6.8-net-phylink-split-out-PHY-validation-from-phylink_br.patch @@ -0,0 +1,95 @@ +From ee0e0ddb910e7e989b65a19d72b6435baa641fc7 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 24 Nov 2023 12:28:34 +0000 +Subject: [PATCH 6/7] net: phylink: split out PHY validation from + phylink_bringup_phy() + +When bringing up a PHY, we need to work out which ethtool link modes it +should support and advertise. Clause 22 PHYs operate in a single +interface mode, which can be easily dealt with. However, clause 45 PHYs +tend to switch interface mode depending on the media. We need more +flexible validation at this point, so this patch splits out that code +in preparation to changing it. + +Tested-by: Luo Jie +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/E1r6VIQ-00DDM9-LK@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 56 ++++++++++++++++++++++----------------- + 1 file changed, 31 insertions(+), 25 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -1775,6 +1775,35 @@ static void phylink_phy_change(struct ph + phylink_pause_to_str(pl->phy_state.pause)); + } + ++static int phylink_validate_phy(struct phylink *pl, struct phy_device *phy, ++ unsigned long *supported, ++ struct phylink_link_state *state) ++{ ++ /* Check whether we would use rate matching for the proposed interface ++ * mode. ++ */ ++ state->rate_matching = phy_get_rate_matching(phy, state->interface); ++ ++ /* Clause 45 PHYs may switch their Serdes lane between, e.g. 10GBASE-R, ++ * 5GBASE-R, 2500BASE-X and SGMII if they are not using rate matching. ++ * For some interface modes (e.g. RXAUI, XAUI and USXGMII) switching ++ * their Serdes is either unnecessary or not reasonable. ++ * ++ * For these which switch interface modes, we really need to know which ++ * interface modes the PHY supports to properly work out which ethtool ++ * linkmodes can be supported. For now, as a work-around, we validate ++ * against all interface modes, which may lead to more ethtool link ++ * modes being advertised than are actually supported. ++ */ ++ if (phy->is_c45 && state->rate_matching == RATE_MATCH_NONE && ++ state->interface != PHY_INTERFACE_MODE_RXAUI && ++ state->interface != PHY_INTERFACE_MODE_XAUI && ++ state->interface != PHY_INTERFACE_MODE_USXGMII) ++ state->interface = PHY_INTERFACE_MODE_NA; ++ ++ return phylink_validate(pl, supported, state); ++} ++ + 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 + memset(&config, 0, sizeof(config)); + linkmode_copy(supported, phy->supported); + linkmode_copy(config.advertising, phy->advertising); ++ config.interface = interface; + +- /* Check whether we would use rate matching for the proposed interface +- * mode. +- */ +- config.rate_matching = phy_get_rate_matching(phy, interface); +- +- /* Clause 45 PHYs may switch their Serdes lane between, e.g. 10GBASE-R, +- * 5GBASE-R, 2500BASE-X and SGMII if they are not using rate matching. +- * For some interface modes (e.g. RXAUI, XAUI and USXGMII) switching +- * their Serdes is either unnecessary or not reasonable. +- * +- * For these which switch interface modes, we really need to know which +- * interface modes the PHY supports to properly work out which ethtool +- * linkmodes can be supported. For now, as a work-around, we validate +- * against all interface modes, which may lead to more ethtool link +- * modes being advertised than are actually supported. +- */ +- if (phy->is_c45 && config.rate_matching == RATE_MATCH_NONE && +- interface != PHY_INTERFACE_MODE_RXAUI && +- interface != PHY_INTERFACE_MODE_XAUI && +- interface != PHY_INTERFACE_MODE_USXGMII) +- config.interface = PHY_INTERFACE_MODE_NA; +- else +- config.interface = interface; +- +- ret = phylink_validate(pl, supported, &config); ++ ret = phylink_validate_phy(pl, phy, supported, &config); + if (ret) { + phylink_warn(pl, "validation of %s with support %*pb and advertisement %*pb failed: %pe\n", + phy_modes(config.interface), 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 new file mode 100644 index 0000000000..86ed7a868e --- /dev/null +++ b/target/linux/generic/backport-6.6/895-07-v6.8-net-phylink-use-the-PHY-s-possible_interfaces-if-pop.patch @@ -0,0 +1,130 @@ +From 8f7a9799c5949f94ecc3acfd71b36437a7ade73b Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 24 Nov 2023 12:28:39 +0000 +Subject: [PATCH 7/7] net: phylink: use the PHY's possible_interfaces if + populated + +Some PHYs such as Aquantia, Broadcom 84881, and Marvell 88X33x0 can +switch between a set of interface types depending on the negotiated +media speed, or can use rate adaption for some or all of these +interface types. + +We currently assume that these are Clause 45 PHYs that are configured +not to use a specific set of interface modes, which has worked so far, +but is just a work-around. In this workaround, we validate using all +interfaces that the MAC supports, which can lead to extra modes being +advertised that can not be supported. + +To properly address this, switch to using the newly introduced PHY +possible_interfaces bitmap which indicates which interface modes will +be used by the PHY as configured. We calculate the union of the PHY's +possible interfaces and MACs supported interfaces, checking that is +non-empty. If the PHY is on a SFP, we further reduce the set by those +which can be used on a SFP module, again checking that is non-empty. +Finally, we validate the subset of interfaces, taking account of +whether rate matching will be used for each individual interface mode. + +This becomes independent of whether the PHY is clause 22 or clause 45. + +It is encouraged that all PHYs that switch interface modes or use +rate matching should populate phydev->possible_interfaces. + +Tested-by: Luo Jie +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/E1r6VIV-00DDMF-Pi@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + drivers/net/phy/phylink.c | 67 +++++++++++++++++++++++++++++++-------- + 1 file changed, 54 insertions(+), 13 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -121,6 +121,19 @@ do { \ + }) + #endif + ++static const phy_interface_t phylink_sfp_interface_preference[] = { ++ PHY_INTERFACE_MODE_25GBASER, ++ PHY_INTERFACE_MODE_USXGMII, ++ PHY_INTERFACE_MODE_10GBASER, ++ PHY_INTERFACE_MODE_5GBASER, ++ PHY_INTERFACE_MODE_2500BASEX, ++ PHY_INTERFACE_MODE_SGMII, ++ PHY_INTERFACE_MODE_1000BASEX, ++ PHY_INTERFACE_MODE_100BASEX, ++}; ++ ++static DECLARE_PHY_INTERFACE_MASK(phylink_sfp_interfaces); ++ + /** + * phylink_set_port_modes() - set the port type modes in the ethtool mask + * @mask: ethtool link mode mask +@@ -1779,6 +1792,47 @@ static int phylink_validate_phy(struct p + unsigned long *supported, + struct phylink_link_state *state) + { ++ DECLARE_PHY_INTERFACE_MASK(interfaces); ++ ++ /* If the PHY provides a bitmap of the interfaces it will be using ++ * depending on the negotiated media speeds, use this to validate ++ * which ethtool link modes can be used. ++ */ ++ if (!phy_interface_empty(phy->possible_interfaces)) { ++ /* We only care about the union of the PHY's interfaces and ++ * those which the host supports. ++ */ ++ phy_interface_and(interfaces, phy->possible_interfaces, ++ pl->config->supported_interfaces); ++ ++ if (phy_interface_empty(interfaces)) { ++ phylink_err(pl, "PHY has no common interfaces\n"); ++ return -EINVAL; ++ } ++ ++ if (phy_on_sfp(phy)) { ++ /* If the PHY is on a SFP, limit the interfaces to ++ * those that can be used with a SFP module. ++ */ ++ phy_interface_and(interfaces, interfaces, ++ phylink_sfp_interfaces); ++ ++ if (phy_interface_empty(interfaces)) { ++ phylink_err(pl, "SFP PHY's possible interfaces becomes empty\n"); ++ return -EINVAL; ++ } ++ } ++ ++ phylink_dbg(pl, "PHY %s uses interfaces %*pbl, validating %*pbl\n", ++ phydev_name(phy), ++ (int)PHY_INTERFACE_MODE_MAX, ++ phy->possible_interfaces, ++ (int)PHY_INTERFACE_MODE_MAX, interfaces); ++ ++ return phylink_validate_mask(pl, phy, supported, state, ++ interfaces); ++ } ++ + /* Check whether we would use rate matching for the proposed interface + * mode. + */ +@@ -3047,19 +3101,6 @@ static void phylink_sfp_detach(void *ups + pl->netdev->sfp_bus = NULL; + } + +-static const phy_interface_t phylink_sfp_interface_preference[] = { +- PHY_INTERFACE_MODE_25GBASER, +- PHY_INTERFACE_MODE_USXGMII, +- PHY_INTERFACE_MODE_10GBASER, +- PHY_INTERFACE_MODE_5GBASER, +- PHY_INTERFACE_MODE_2500BASEX, +- PHY_INTERFACE_MODE_SGMII, +- PHY_INTERFACE_MODE_1000BASEX, +- PHY_INTERFACE_MODE_100BASEX, +-}; +- +-static DECLARE_PHY_INTERFACE_MASK(phylink_sfp_interfaces); +- + static phy_interface_t phylink_choose_sfp_interface(struct phylink *pl, + const unsigned long *intf) + { diff --git a/target/linux/generic/backport-6.6/897-01-v6.9-net-phy-qcom-qca808x-add-helper-for-checking-for-1G-.patch b/target/linux/generic/backport-6.6/897-01-v6.9-net-phy-qcom-qca808x-add-helper-for-checking-for-1G-.patch new file mode 100644 index 0000000000..a11e804958 --- /dev/null +++ b/target/linux/generic/backport-6.6/897-01-v6.9-net-phy-qcom-qca808x-add-helper-for-checking-for-1G-.patch @@ -0,0 +1,50 @@ +From f058b2dd70b1a5503dff899010aeb53b436091e5 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 28 Feb 2024 18:24:09 +0100 +Subject: [PATCH 1/2] net: phy: qcom: qca808x: add helper for checking for 1G + only model + +There are 2 versions of QCA808x, one 2.5G capable and one 1G capable. +Currently, this matter only in the .get_features call however, it will +be required for filling supported interface modes so lets add a helper +that can be reused. + +Signed-off-by: Robert Marko +Signed-off-by: David S. Miller +--- + drivers/net/phy/qcom/qca808x.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +--- a/drivers/net/phy/qcom/qca808x.c ++++ b/drivers/net/phy/qcom/qca808x.c +@@ -156,6 +156,17 @@ static bool qca808x_has_fast_retrain_or_ + return linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); + } + ++static bool qca808x_is_1g_only(struct phy_device *phydev) ++{ ++ int ret; ++ ++ ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_CHIP_TYPE); ++ if (ret < 0) ++ return true; ++ ++ return !!(QCA808X_PHY_CHIP_TYPE_1G & ret); ++} ++ + static int qca808x_probe(struct phy_device *phydev) + { + struct device *dev = &phydev->mdio.dev; +@@ -350,11 +361,7 @@ static int qca808x_get_features(struct p + * existed in the bit0 of MMD1.21, we need to remove it manually if + * it is the qca8081 1G chip according to the bit0 of MMD7.0x901d. + */ +- ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_CHIP_TYPE); +- if (ret < 0) +- return ret; +- +- if (QCA808X_PHY_CHIP_TYPE_1G & ret) ++ if (qca808x_is_1g_only(phydev)) + linkmode_clear_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported); + + return 0; diff --git a/target/linux/generic/backport-6.6/897-02-v6.9-net-phy-qcom-qca808x-fill-in-possible_interfaces.patch b/target/linux/generic/backport-6.6/897-02-v6.9-net-phy-qcom-qca808x-fill-in-possible_interfaces.patch new file mode 100644 index 0000000000..c162fc7348 --- /dev/null +++ b/target/linux/generic/backport-6.6/897-02-v6.9-net-phy-qcom-qca808x-fill-in-possible_interfaces.patch @@ -0,0 +1,44 @@ +From cb28f702960695e26597c332b0e46776e825cc34 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Wed, 28 Feb 2024 18:24:10 +0100 +Subject: [PATCH 2/2] net: phy: qcom: qca808x: fill in possible_interfaces + +Currently QCA808x driver does not fill the possible_interfaces. +2.5G QCA808x support SGMII and 2500Base-X while 1G model only supports +SGMII, so fill the possible_interfaces accordingly. + +Signed-off-by: Robert Marko +Reviewed-by: Russell King (Oracle) +Signed-off-by: David S. Miller +--- + drivers/net/phy/qcom/qca808x.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/drivers/net/phy/qcom/qca808x.c ++++ b/drivers/net/phy/qcom/qca808x.c +@@ -167,6 +167,16 @@ static bool qca808x_is_1g_only(struct ph + return !!(QCA808X_PHY_CHIP_TYPE_1G & ret); + } + ++static void qca808x_fill_possible_interfaces(struct phy_device *phydev) ++{ ++ unsigned long *possible = phydev->possible_interfaces; ++ ++ __set_bit(PHY_INTERFACE_MODE_SGMII, possible); ++ ++ if (!qca808x_is_1g_only(phydev)) ++ __set_bit(PHY_INTERFACE_MODE_2500BASEX, possible); ++} ++ + static int qca808x_probe(struct phy_device *phydev) + { + struct device *dev = &phydev->mdio.dev; +@@ -231,6 +241,8 @@ static int qca808x_config_init(struct ph + } + } + ++ qca808x_fill_possible_interfaces(phydev); ++ + /* Configure adc threshold as 100mv for the link 10M */ + return at803x_debug_reg_mask(phydev, QCA808X_PHY_DEBUG_ADC_THRESHOLD, + QCA808X_ADC_THRESHOLD_MASK, diff --git a/target/linux/generic/pending-6.1/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/pending-6.1/703-phy-add-detach-callback-to-struct-phy_driver.patch index e4937a1df1..d50bc9cd4c 100644 --- a/target/linux/generic/pending-6.1/703-phy-add-detach-callback-to-struct-phy_driver.patch +++ b/target/linux/generic/pending-6.1/703-phy-add-detach-callback-to-struct-phy_driver.patch @@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -1850,6 +1850,9 @@ void phy_detach(struct phy_device *phyde +@@ -1852,6 +1852,9 @@ void phy_detach(struct phy_device *phyde struct module *ndev_owner = NULL; struct mii_bus *bus; @@ -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 -@@ -900,6 +900,12 @@ struct phy_driver { +@@ -903,6 +903,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/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 c544a06dfc..aa83968263 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 @@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c -@@ -1908,6 +1908,9 @@ void phy_detach(struct phy_device *phyde +@@ -1910,6 +1910,9 @@ void phy_detach(struct phy_device *phyde if (phydev->devlink) device_link_del(phydev->devlink); @@ -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 -@@ -976,6 +976,12 @@ struct phy_driver { +@@ -979,6 +979,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/999-net-phy-move-LED-polarity-to-phy_init_hw.patch b/target/linux/generic/pending-6.6/999-net-phy-move-LED-polarity-to-phy_init_hw.patch index 22c4776827..2cc9a7f5d5 100644 --- a/target/linux/generic/pending-6.6/999-net-phy-move-LED-polarity-to-phy_init_hw.patch +++ b/target/linux/generic/pending-6.6/999-net-phy-move-LED-polarity-to-phy_init_hw.patch @@ -55,7 +55,7 @@ Signed-off-by: Christian Marangi int phy_init_hw(struct phy_device *phydev) { int ret = 0; -@@ -1259,6 +1290,12 @@ int phy_init_hw(struct phy_device *phyde +@@ -1261,6 +1292,12 @@ int phy_init_hw(struct phy_device *phyde return ret; } @@ -68,7 +68,7 @@ Signed-off-by: Christian Marangi return 0; } EXPORT_SYMBOL(phy_init_hw); -@@ -3204,7 +3241,6 @@ static int of_phy_led(struct phy_device +@@ -3206,7 +3243,6 @@ static int of_phy_led(struct phy_device struct device *dev = &phydev->mdio.dev; struct led_init_data init_data = {}; struct led_classdev *cdev; @@ -76,7 +76,7 @@ Signed-off-by: Christian Marangi struct phy_led *phyled; u32 index; int err; -@@ -3222,21 +3258,6 @@ static int of_phy_led(struct phy_device +@@ -3224,21 +3260,6 @@ static int of_phy_led(struct phy_device if (index > U8_MAX) return -EINVAL;