diff options
author | Russell King | 2020-02-15 15:50:03 +0000 |
---|---|---|
committer | David S. Miller | 2020-02-16 19:39:45 -0800 |
commit | 97fec51fe79b1332c604473674febbf7b0ab7f51 (patch) | |
tree | 94f63c2e2ac3ee4ba1581a4afd12865efac1fb0a | |
parent | f904f15ea9b5c379d58e3c7d85862baf1adf7370 (diff) |
net: phylink: improve initial mac configuration
Improve the initial MAC configuration so we get a configuration which
more represents the final operating mode, in particular with respect
to the flow control settings.
We do this by:
1) more fully initialising our phy state, so we can use this as the
initial state for PHY based connections.
2) reading the fixed link state.
3) ensuring that in-band mode has sane pause settings for SGMII vs
802.3z negotiation modes.
In all three cases, we ensure that state->link is false, just in case
any MAC drivers have other ideas by mis-using this member, and we also
take account of manual pause mode configuration at this point.
This avoids MLO_PAUSE_AN being seen in mac_config() when operating in
PHY, fixed mode or inband SGMII mode, thereby giving cleaner semantics
to the pause flags. As a result of this, the pause flags now indicate
in a mode-independent way what is required from a mac_config()
implementation.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/phy/phylink.c | 36 |
1 files changed, 34 insertions, 2 deletions
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index ab72bd1a7dca..2899fbe699ab 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -431,6 +431,35 @@ static void phylink_get_fixed_state(struct phylink *pl, phylink_resolve_flow(state); } +static void phylink_mac_initial_config(struct phylink *pl) +{ + struct phylink_link_state link_state; + + switch (pl->cur_link_an_mode) { + case MLO_AN_PHY: + link_state = pl->phy_state; + break; + + case MLO_AN_FIXED: + phylink_get_fixed_state(pl, &link_state); + break; + + case MLO_AN_INBAND: + link_state = pl->link_config; + if (link_state.interface == PHY_INTERFACE_MODE_SGMII) + link_state.pause = MLO_PAUSE_NONE; + break; + + default: /* can't happen */ + return; + } + + link_state.link = false; + + phylink_apply_manual_flow(pl, &link_state); + phylink_mac_config(pl, &link_state); +} + static const char *phylink_pause_to_str(int pause) { switch (pause & MLO_PAUSE_TXRX_MASK) { @@ -779,6 +808,9 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy, mutex_lock(&pl->state_mutex); pl->phydev = phy; pl->phy_state.interface = interface; + pl->phy_state.pause = MLO_PAUSE_NONE; + pl->phy_state.speed = SPEED_UNKNOWN; + pl->phy_state.duplex = DUPLEX_UNKNOWN; linkmode_copy(pl->supported, supported); linkmode_copy(pl->link_config.advertising, config.advertising); @@ -1008,7 +1040,7 @@ void phylink_start(struct phylink *pl) * a fixed-link to start with the correct parameters, and also * ensures that we set the appropriate advertisement for Serdes links. */ - phylink_mac_config(pl, &pl->link_config); + phylink_mac_initial_config(pl); /* Restart autonegotiation if using 802.3z to ensure that the link * parameters are properly negotiated. This is necessary for DSA @@ -1826,7 +1858,7 @@ static int phylink_sfp_config(struct phylink *pl, u8 mode, if (changed && !test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state)) - phylink_mac_config(pl, &pl->link_config); + phylink_mac_initial_config(pl); return ret; } |