diff options
Diffstat (limited to 'target/linux/mvebu/patches-4.9/436-phylink-propagate-PHY-interface-mode-to-MAC-driver.patch')
-rw-r--r-- | target/linux/mvebu/patches-4.9/436-phylink-propagate-PHY-interface-mode-to-MAC-driver.patch | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/target/linux/mvebu/patches-4.9/436-phylink-propagate-PHY-interface-mode-to-MAC-driver.patch b/target/linux/mvebu/patches-4.9/436-phylink-propagate-PHY-interface-mode-to-MAC-driver.patch new file mode 100644 index 0000000000..9b872b82d7 --- /dev/null +++ b/target/linux/mvebu/patches-4.9/436-phylink-propagate-PHY-interface-mode-to-MAC-driver.patch @@ -0,0 +1,126 @@ +From: Russell King <rmk+kernel@armlinux.org.uk> +Date: Tue, 3 Jan 2017 18:34:17 +0000 +Subject: [PATCH] phylink: propagate PHY interface mode to MAC driver + +Some 10Gigabit PHYs automatically switch the mode of their host +interface depending on their negotiated speed. We need to communicate +this to the MAC driver so the MAC can switch its host interface to +match the PHYs new operating mode. Provide the current PHY interface +mode to the MAC driver. + +Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> +--- + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -242,8 +242,9 @@ static void phylink_mac_config(struct ph + const struct phylink_link_state *state) + { + netdev_dbg(pl->netdev, +- "%s: mode=%s/%s/%s adv=%*pb pause=%02x link=%u an=%u\n", ++ "%s: mode=%s/%s/%s/%s adv=%*pb pause=%02x link=%u an=%u\n", + __func__, phylink_an_mode_str(pl->link_an_mode), ++ phy_modes(state->interface), + phy_speed_to_str(state->speed), + phy_duplex_to_str(state->duplex), + __ETHTOOL_LINK_MODE_MASK_NBITS, state->advertising, +@@ -264,6 +265,7 @@ static int phylink_get_mac_state(struct + + linkmode_copy(state->advertising, pl->link_config.advertising); + linkmode_zero(state->lp_advertising); ++ state->interface = pl->link_config.interface; + state->an_enabled = pl->link_config.an_enabled; + state->link = 1; + +@@ -344,19 +346,38 @@ static void phylink_resolve(struct work_ + case MLO_AN_PHY: + link_state = pl->phy_state; + phylink_resolve_flow(pl, &link_state); ++ phylink_mac_config(pl, &link_state); + break; + + case MLO_AN_FIXED: + phylink_get_fixed_state(pl, &link_state); ++ phylink_mac_config(pl, &link_state); + break; + + case MLO_AN_SGMII: + phylink_get_mac_state(pl, &link_state); + if (pl->phydev) { ++ bool changed = false; ++ + link_state.link = link_state.link && + pl->phy_state.link; +- link_state.pause |= pl->phy_state.pause; +- phylink_resolve_flow(pl, &link_state); ++ ++ if (pl->phy_state.interface != ++ link_state.interface) { ++ link_state.interface = pl->phy_state.interface; ++ changed = true; ++ } ++ ++ /* Propagate the flow control from the PHY ++ * to the MAC. Also propagate the interface ++ * if changed. ++ */ ++ if (pl->phy_state.link || changed) { ++ link_state.pause |= pl->phy_state.pause; ++ phylink_resolve_flow(pl, &link_state); ++ ++ phylink_mac_config(pl, &link_state); ++ } + } + break; + +@@ -372,13 +393,6 @@ static void phylink_resolve(struct work_ + pl->ops->mac_link_down(ndev, pl->link_an_mode); + netdev_info(ndev, "Link is Down\n"); + } else { +- /* If we have a PHY, we need the MAC updated with +- * the current link parameters (eg, in SGMII mode, +- * with flow control status.) +- */ +- if (pl->phydev) +- phylink_mac_config(pl, &link_state); +- + pl->ops->mac_link_up(ndev, pl->link_an_mode, + pl->phydev); + +@@ -414,8 +428,10 @@ struct phylink *phylink_create(struct ne + mutex_init(&pl->config_mutex); + INIT_WORK(&pl->resolve, phylink_resolve); + pl->netdev = ndev; ++ pl->phy_state.interface = iface; + pl->link_interface = iface; + pl->link_port = PORT_MII; ++ pl->link_config.interface = iface; + pl->link_config.pause = MLO_PAUSE_AN; + pl->link_config.speed = SPEED_UNKNOWN; + pl->link_config.duplex = DUPLEX_UNKNOWN; +@@ -471,12 +487,14 @@ void phylink_phy_change(struct phy_devic + pl->phy_state.pause |= MLO_PAUSE_SYM; + if (phydev->asym_pause) + pl->phy_state.pause |= MLO_PAUSE_ASYM; ++ pl->phy_state.interface = phydev->interface; + pl->phy_state.link = up; + mutex_unlock(&pl->state_mutex); + + phylink_run_resolve(pl); + +- netdev_dbg(pl->netdev, "phy link %s %s/%s\n", up ? "up" : "down", ++ netdev_dbg(pl->netdev, "phy link %s %s/%s/%s\n", up ? "up" : "down", ++ phy_modes(phydev->interface), + phy_speed_to_str(phydev->speed), + phy_duplex_to_str(phydev->duplex)); + } +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -27,6 +27,7 @@ enum { + struct phylink_link_state { + __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising); + __ETHTOOL_DECLARE_LINK_MODE_MASK(lp_advertising); ++ phy_interface_t interface; /* PHY_INTERFACE_xxx */ + int speed; + int duplex; + int pause; |