| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- From: Russell King <[email protected]>
- 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 <[email protected]>
- ---
- --- 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;
|