[][kernel][mt7988][eth][Add 10G interface dyanmically change support fo ESP-T5-R SFP+ modules]
[Description]
Add 10G interface dyanmically change support for ESP-T5-R SFP+ modules.
- Support ETU ESP-T5-R module
Note: This feature backport from Linux-6.1.
https://elixir.bootlin.com/linux/v6.1/source/drivers/net/phy/phylink.c
[Release-log]
N/A
Change-Id: Ic15fa31f5ae7539c20a5009e74ab4ecb5c7a9621
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/7123798
diff --git a/target/linux/mediatek/patches-5.4/755-net-phy-sfp-add-rollball-support.patch b/target/linux/mediatek/patches-5.4/755-net-phy-sfp-add-rollball-support.patch
index ee68b4e..6233046 100644
--- a/target/linux/mediatek/patches-5.4/755-net-phy-sfp-add-rollball-support.patch
+++ b/target/linux/mediatek/patches-5.4/755-net-phy-sfp-add-rollball-support.patch
@@ -370,6 +370,140 @@
+ enum mdio_i2c_proto protocol);
#endif
+diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
+index f360d92..67f34ed 100644
+--- a/drivers/net/phy/phylink.c
++++ b/drivers/net/phy/phylink.c
+@@ -483,62 +483,105 @@ static void phylink_resolve(struct work_struct *w)
+ struct phylink *pl = container_of(w, struct phylink, resolve);
+ struct phylink_link_state link_state;
+ struct net_device *ndev = pl->netdev;
+- int link_changed;
++ bool mac_config = false;
++ bool retrigger = false;
++ bool cur_link_state;
+
+ mutex_lock(&pl->state_mutex);
++ if (pl->netdev)
++ cur_link_state = netif_carrier_ok(ndev);
++ else
++ cur_link_state = pl->old_link_state;
++
+ if (pl->phylink_disable_state) {
+ pl->mac_link_dropped = false;
+ link_state.link = false;
+ } else if (pl->mac_link_dropped) {
+ link_state.link = false;
++ retrigger = true;
+ } else {
+ switch (pl->cur_link_an_mode) {
+ case MLO_AN_PHY:
+ link_state = pl->phy_state;
+ phylink_resolve_flow(pl, &link_state);
+- phylink_mac_config_up(pl, &link_state);
++ mac_config = link_state.link;
+ break;
+
+ case MLO_AN_FIXED:
+ phylink_get_fixed_state(pl, &link_state);
+- phylink_mac_config_up(pl, &link_state);
++ mac_config = link_state.link;
+ break;
+
+ case MLO_AN_INBAND:
+ phylink_get_mac_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_get_mac_state(pl,
++ &link_state);
++ }
++
+ /* If we have a phy, the "up" state is the union of
+- * both the PHY and the MAC */
++ * 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.interface !=
++ pl->phy_state.interface) {
++ retrigger = true;
++ link_state.link = false;
++ }
+ link_state.interface = pl->phy_state.interface;
+
+ /* If we have a PHY, we need to update with
+- * the pause mode bits. */
+- link_state.pause |= pl->phy_state.pause;
+- phylink_resolve_flow(pl, &link_state);
+- phylink_mac_config(pl, &link_state);
++ * the PHY flow control bits.
++ */
++ link_state.pause = pl->phy_state.pause;
++ mac_config = true;
+ }
++ phylink_resolve_flow(pl, &link_state);
+ break;
+ }
+ }
+
+- if (pl->netdev)
+- link_changed = (link_state.link != netif_carrier_ok(ndev));
+- else
+- link_changed = (link_state.link != pl->old_link_state);
++ if (mac_config) {
++ if (link_state.interface != pl->link_config.interface) {
++ /* The interface has changed, force the link down and
++ * then reconfigure.
++ */
++ if (cur_link_state) {
++ phylink_mac_link_down(pl);
++ cur_link_state = false;
++ }
++ phylink_mac_config(pl, &link_state);
++ pl->link_config.interface = link_state.interface;
++ } else {
++ phylink_mac_config(pl, &link_state);
++ }
++ }
+
+- if (link_changed) {
++ if (link_state.link != cur_link_state) {
+ pl->old_link_state = link_state.link;
+ if (!link_state.link)
+ phylink_mac_link_down(pl);
+ else
+ phylink_mac_link_up(pl, link_state);
+ }
+- if (!link_state.link && pl->mac_link_dropped) {
++ if (!link_state.link && retrigger) {
+ pl->mac_link_dropped = false;
+ queue_work(system_power_efficient_wq, &pl->resolve);
+ }
+@@ -1014,7 +1057,8 @@ void phylink_start(struct phylink *pl)
+ if (irq <= 0)
+ mod_timer(&pl->link_poll, jiffies + HZ);
+ }
+- if (pl->cfg_link_an_mode == MLO_AN_FIXED && pl->get_fixed_state)
++ if ((pl->cfg_link_an_mode == MLO_AN_FIXED && pl->get_fixed_state) ||
++ (pl->cfg_link_an_mode == MLO_AN_INBAND))
+ mod_timer(&pl->link_poll, jiffies + HZ);
+ if (pl->phydev)
+ phy_start(pl->phydev);
diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c
index 42f0441..0d5ac2a 100644
--- a/drivers/net/phy/sfp-bus.c
@@ -552,7 +686,7 @@
#if IS_ENABLED(CONFIG_HWMON)
struct sfp_diag diag;
-@@ -303,6 +313,135 @@ static const struct of_device_id sfp_of_match[] = {
+@@ -303,6 +313,136 @@ static const struct of_device_id sfp_of_match[] = {
};
MODULE_DEVICE_TABLE(of, sfp_of_match);
@@ -636,6 +770,7 @@
+
+ SFP_QUIRK_M("UBNT", "UF-INSTANT", sfp_quirk_ubnt_uf_instant),
+
++ SFP_QUIRK_F("ETU", "ESP-T5-R", sfp_fixup_rollball_cc),
+ SFP_QUIRK_F("OEM", "SFP-10G-T", sfp_fixup_rollball_cc),
+ SFP_QUIRK_F("OEM", "RTSFP-10", sfp_fixup_rollball_cc),
+ SFP_QUIRK_F("OEM", "RTSFP-10G", sfp_fixup_rollball_cc),