mvebu: Migrate uci config to new PCIe path
[openwrt/staging/wigyori.git] / target / linux / mvebu / patches-4.9 / 436-phylink-propagate-PHY-interface-mode-to-MAC-driver.patch
1 From: Russell King <rmk+kernel@armlinux.org.uk>
2 Date: Tue, 3 Jan 2017 18:34:17 +0000
3 Subject: [PATCH] phylink: propagate PHY interface mode to MAC driver
4
5 Some 10Gigabit PHYs automatically switch the mode of their host
6 interface depending on their negotiated speed. We need to communicate
7 this to the MAC driver so the MAC can switch its host interface to
8 match the PHYs new operating mode. Provide the current PHY interface
9 mode to the MAC driver.
10
11 Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
12 ---
13
14 --- a/drivers/net/phy/phylink.c
15 +++ b/drivers/net/phy/phylink.c
16 @@ -242,8 +242,9 @@ static void phylink_mac_config(struct ph
17 const struct phylink_link_state *state)
18 {
19 netdev_dbg(pl->netdev,
20 - "%s: mode=%s/%s/%s adv=%*pb pause=%02x link=%u an=%u\n",
21 + "%s: mode=%s/%s/%s/%s adv=%*pb pause=%02x link=%u an=%u\n",
22 __func__, phylink_an_mode_str(pl->link_an_mode),
23 + phy_modes(state->interface),
24 phy_speed_to_str(state->speed),
25 phy_duplex_to_str(state->duplex),
26 __ETHTOOL_LINK_MODE_MASK_NBITS, state->advertising,
27 @@ -264,6 +265,7 @@ static int phylink_get_mac_state(struct
28
29 linkmode_copy(state->advertising, pl->link_config.advertising);
30 linkmode_zero(state->lp_advertising);
31 + state->interface = pl->link_config.interface;
32 state->an_enabled = pl->link_config.an_enabled;
33 state->link = 1;
34
35 @@ -344,19 +346,38 @@ static void phylink_resolve(struct work_
36 case MLO_AN_PHY:
37 link_state = pl->phy_state;
38 phylink_resolve_flow(pl, &link_state);
39 + phylink_mac_config(pl, &link_state);
40 break;
41
42 case MLO_AN_FIXED:
43 phylink_get_fixed_state(pl, &link_state);
44 + phylink_mac_config(pl, &link_state);
45 break;
46
47 case MLO_AN_SGMII:
48 phylink_get_mac_state(pl, &link_state);
49 if (pl->phydev) {
50 + bool changed = false;
51 +
52 link_state.link = link_state.link &&
53 pl->phy_state.link;
54 - link_state.pause |= pl->phy_state.pause;
55 - phylink_resolve_flow(pl, &link_state);
56 +
57 + if (pl->phy_state.interface !=
58 + link_state.interface) {
59 + link_state.interface = pl->phy_state.interface;
60 + changed = true;
61 + }
62 +
63 + /* Propagate the flow control from the PHY
64 + * to the MAC. Also propagate the interface
65 + * if changed.
66 + */
67 + if (pl->phy_state.link || changed) {
68 + link_state.pause |= pl->phy_state.pause;
69 + phylink_resolve_flow(pl, &link_state);
70 +
71 + phylink_mac_config(pl, &link_state);
72 + }
73 }
74 break;
75
76 @@ -372,13 +393,6 @@ static void phylink_resolve(struct work_
77 pl->ops->mac_link_down(ndev, pl->link_an_mode);
78 netdev_info(ndev, "Link is Down\n");
79 } else {
80 - /* If we have a PHY, we need the MAC updated with
81 - * the current link parameters (eg, in SGMII mode,
82 - * with flow control status.)
83 - */
84 - if (pl->phydev)
85 - phylink_mac_config(pl, &link_state);
86 -
87 pl->ops->mac_link_up(ndev, pl->link_an_mode,
88 pl->phydev);
89
90 @@ -414,8 +428,10 @@ struct phylink *phylink_create(struct ne
91 mutex_init(&pl->config_mutex);
92 INIT_WORK(&pl->resolve, phylink_resolve);
93 pl->netdev = ndev;
94 + pl->phy_state.interface = iface;
95 pl->link_interface = iface;
96 pl->link_port = PORT_MII;
97 + pl->link_config.interface = iface;
98 pl->link_config.pause = MLO_PAUSE_AN;
99 pl->link_config.speed = SPEED_UNKNOWN;
100 pl->link_config.duplex = DUPLEX_UNKNOWN;
101 @@ -471,12 +487,14 @@ void phylink_phy_change(struct phy_devic
102 pl->phy_state.pause |= MLO_PAUSE_SYM;
103 if (phydev->asym_pause)
104 pl->phy_state.pause |= MLO_PAUSE_ASYM;
105 + pl->phy_state.interface = phydev->interface;
106 pl->phy_state.link = up;
107 mutex_unlock(&pl->state_mutex);
108
109 phylink_run_resolve(pl);
110
111 - netdev_dbg(pl->netdev, "phy link %s %s/%s\n", up ? "up" : "down",
112 + netdev_dbg(pl->netdev, "phy link %s %s/%s/%s\n", up ? "up" : "down",
113 + phy_modes(phydev->interface),
114 phy_speed_to_str(phydev->speed),
115 phy_duplex_to_str(phydev->duplex));
116 }
117 --- a/include/linux/phylink.h
118 +++ b/include/linux/phylink.h
119 @@ -27,6 +27,7 @@ enum {
120 struct phylink_link_state {
121 __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising);
122 __ETHTOOL_DECLARE_LINK_MODE_MASK(lp_advertising);
123 + phy_interface_t interface; /* PHY_INTERFACE_xxx */
124 int speed;
125 int duplex;
126 int pause;