[][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),