History

net: phylink: pcs: add 802.3 clause 22 helpers

Implement helpers for PCS accessed via the MII bus using 802.3 clause 22 cycles, conforming to 802.3 clause 37 and Cisco SGMII specifications for the advertisement word.

Russell King committed 6 years ago

Commit 74db1c11 parent 6cc7cf83 files · +217 −0Browse files

Unified · Split

3 files
  1. drivers/net/phy/phylink.c +206 −0
  2. include/linux/phylink.h +6 −0
  3. include/uapi/linux/mii.h +5 −0
drivers/net/phy/phylink.c+206−0
@@ -2068,4 +2068,210 @@ void phylink_helper_basex_speed(struct phylink_link_state *state) · 2067 unmodified lines
2068}2068}
2069EXPORT_SYMBOL_GPL(phylink_helper_basex_speed);2069EXPORT_SYMBOL_GPL(phylink_helper_basex_speed);
2070 2070
2071static void phylink_decode_c37_word(struct phylink_link_state *state,
2072 uint16_t config_reg, int speed)
2073{
2074 bool tx_pause, rx_pause;
2075 int fd_bit;
2076
2077 if (speed == SPEED_2500)
2078 fd_bit = ETHTOOL_LINK_MODE_2500baseX_Full_BIT;
2079 else
2080 fd_bit = ETHTOOL_LINK_MODE_1000baseX_Full_BIT;
2081
2082 mii_lpa_mod_linkmode_x(state->lp_advertising, config_reg, fd_bit);
2083
2084 if (linkmode_test_bit(fd_bit, state->advertising) &&
2085 linkmode_test_bit(fd_bit, state->lp_advertising)) {
2086 state->speed = speed;
2087 state->duplex = DUPLEX_FULL;
2088 } else {
2089 /* negotiation failure */
2090 state->link = false;
2091 }
2092
2093 linkmode_resolve_pause(state->advertising, state->lp_advertising,
2094 &tx_pause, &rx_pause);
2095
2096 if (tx_pause)
2097 state->pause |= MLO_PAUSE_TX;
2098 if (rx_pause)
2099 state->pause |= MLO_PAUSE_RX;
2100}
2101
2102static void phylink_decode_sgmii_word(struct phylink_link_state *state,
2103 uint16_t config_reg)
2104{
2105 if (!(config_reg & LPA_SGMII_LINK)) {
2106 state->link = false;
2107 return;
2108 }
2109
2110 switch (config_reg & LPA_SGMII_SPD_MASK) {
2111 case LPA_SGMII_10:
2112 state->speed = SPEED_10;
2113 break;
2114 case LPA_SGMII_100:
2115 state->speed = SPEED_100;
2116 break;
2117 case LPA_SGMII_1000:
2118 state->speed = SPEED_1000;
2119 break;
2120 default:
2121 state->link = false;
2122 return;
2123 }
2124 if (config_reg & LPA_SGMII_FULL_DUPLEX)
2125 state->duplex = DUPLEX_FULL;
2126 else
2127 state->duplex = DUPLEX_HALF;
2128}
2129
2130/**
2131 * phylink_mii_c22_pcs_get_state() - read the MAC PCS state
2132 * @pcs: a pointer to a &struct mdio_device.
2133 * @state: a pointer to a &struct phylink_link_state.
2134 *
2135 * Helper for MAC PCS supporting the 802.3 clause 22 register set for
2136 * clause 37 negotiation and/or SGMII control.
2137 *
2138 * Read the MAC PCS state from the MII device configured in @config and
2139 * parse the Clause 37 or Cisco SGMII link partner negotiation word into
2140 * the phylink @state structure. This is suitable to be directly plugged
2141 * into the mac_pcs_get_state() member of the struct phylink_mac_ops
2142 * structure.
2143 */
2144void phylink_mii_c22_pcs_get_state(struct mdio_device *pcs,
2145 struct phylink_link_state *state)
2146{
2147 struct mii_bus *bus = pcs->bus;
2148 int addr = pcs->addr;
2149 int bmsr, lpa;
2150
2151 bmsr = mdiobus_read(bus, addr, MII_BMSR);
2152 lpa = mdiobus_read(bus, addr, MII_LPA);
2153 if (bmsr < 0 || lpa < 0) {
2154 state->link = false;
2155 return;
2156 }
2157
2158 state->link = !!(bmsr & BMSR_LSTATUS);
2159 state->an_complete = !!(bmsr & BMSR_ANEGCOMPLETE);
2160 if (!state->link)
2161 return;
2162
2163 switch (state->interface) {
2164 case PHY_INTERFACE_MODE_1000BASEX:
2165 phylink_decode_c37_word(state, lpa, SPEED_1000);
2166 break;
2167
2168 case PHY_INTERFACE_MODE_2500BASEX:
2169 phylink_decode_c37_word(state, lpa, SPEED_2500);
2170 break;
2171
2172 case PHY_INTERFACE_MODE_SGMII:
2173 phylink_decode_sgmii_word(state, lpa);
2174 break;
2175
2176 default:
2177 state->link = false;
2178 break;
2179 }
2180}
2181EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_get_state);
2182
2183/**
2184 * phylink_mii_c22_pcs_set_advertisement() - configure the clause 37 PCS
2185 * advertisement
2186 * @pcs: a pointer to a &struct mdio_device.
2187 * @state: a pointer to the state being configured.
2188 *
2189 * Helper for MAC PCS supporting the 802.3 clause 22 register set for
2190 * clause 37 negotiation and/or SGMII control.
2191 *
2192 * Configure the clause 37 PCS advertisement as specified by @state. This
2193 * does not trigger a renegotiation; phylink will do that via the
2194 * mac_an_restart() method of the struct phylink_mac_ops structure.
2195 *
2196 * Returns negative error code on failure to configure the advertisement,
2197 * zero if no change has been made, or one if the advertisement has changed.
2198 */
2199int phylink_mii_c22_pcs_set_advertisement(struct mdio_device *pcs,
2200 const struct phylink_link_state *state)
2201{
2202 struct mii_bus *bus = pcs->bus;
2203 int addr = pcs->addr;
2204 int val, ret;
2205 u16 adv;
2206
2207 switch (state->interface) {
2208 case PHY_INTERFACE_MODE_1000BASEX:
2209 case PHY_INTERFACE_MODE_2500BASEX:
2210 adv = ADVERTISE_1000XFULL;
2211 if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT,
2212 state->advertising))
2213 adv |= ADVERTISE_1000XPAUSE;
2214 if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
2215 state->advertising))
2216 adv |= ADVERTISE_1000XPSE_ASYM;
2217
2218 val = mdiobus_read(bus, addr, MII_ADVERTISE);
2219 if (val < 0)
2220 return val;
2221
2222 if (val == adv)
2223 return 0;
2224
2225 ret = mdiobus_write(bus, addr, MII_ADVERTISE, adv);
2226 if (ret < 0)
2227 return ret;
2228
2229 return 1;
2230
2231 case PHY_INTERFACE_MODE_SGMII:
2232 val = mdiobus_read(bus, addr, MII_ADVERTISE);
2233 if (val < 0)
2234 return val;
2235
2236 if (val == 0x0001)
2237 return 0;
2238
2239 ret = mdiobus_write(bus, addr, MII_ADVERTISE, 0x0001);
2240 if (ret < 0)
2241 return ret;
2242
2243 return 1;
2244
2245 default:
2246 /* Nothing to do for other modes */
2247 return 0;
2248 }
2249}
2250EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_set_advertisement);
2251
2252/**
2253 * phylink_mii_c22_pcs_an_restart() - restart 802.3z autonegotiation
2254 * @pcs: a pointer to a &struct mdio_device.
2255 *
2256 * Helper for MAC PCS supporting the 802.3 clause 22 register set for
2257 * clause 37 negotiation.
2258 *
2259 * Restart the clause 37 negotiation with the link partner. This is
2260 * suitable to be directly plugged into the mac_pcs_get_state() member
2261 * of the struct phylink_mac_ops structure.
2262 */
2263void phylink_mii_c22_pcs_an_restart(struct mdio_device *pcs)
2264{
2265 struct mii_bus *bus = pcs->bus;
2266 int val, addr = pcs->addr;
2267
2268 val = mdiobus_read(bus, addr, MII_BMCR);
2269 if (val >= 0) {
2270 val |= BMCR_ANRESTART;
2271
2272 mdiobus_write(bus, addr, MII_BMCR, val);
2273 }
2274}
2275EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_an_restart);
2276
2071MODULE_LICENSE("GPL v2");2277MODULE_LICENSE("GPL v2");
include/linux/phylink.h+6−0
@@ -317,4 +317,10 @@ int phylink_mii_ioctl(struct phylink *, struct ifreq *, int); · 316 unmodified lines
317void phylink_set_port_modes(unsigned long *bits);317void phylink_set_port_modes(unsigned long *bits);
318void phylink_helper_basex_speed(struct phylink_link_state *state);318void phylink_helper_basex_speed(struct phylink_link_state *state);
319 319
320void phylink_mii_c22_pcs_get_state(struct mdio_device *pcs,
321 struct phylink_link_state *state);
322int phylink_mii_c22_pcs_set_advertisement(struct mdio_device *pcs,
323 const struct phylink_link_state *state);
324void phylink_mii_c22_pcs_an_restart(struct mdio_device *pcs);
325
320#endif326#endif
include/uapi/linux/mii.h+5−0
@@ -134,11 +134,16 @@ · 133 unmodified lines
134/* MAC and PHY tx_config_Reg[15:0] for SGMII in-band auto-negotiation.*/134/* MAC and PHY tx_config_Reg[15:0] for SGMII in-band auto-negotiation.*/
135#define ADVERTISE_SGMII 0x0001 /* MAC can do SGMII */135#define ADVERTISE_SGMII 0x0001 /* MAC can do SGMII */
136#define LPA_SGMII 0x0001 /* PHY can do SGMII */136#define LPA_SGMII 0x0001 /* PHY can do SGMII */
137#define LPA_SGMII_SPD_MASK 0x0c00 /* SGMII speed mask */
138#define LPA_SGMII_FULL_DUPLEX 0x1000 /* SGMII full duplex */
137#define LPA_SGMII_DPX_SPD_MASK 0x1C00 /* SGMII duplex and speed bits */139#define LPA_SGMII_DPX_SPD_MASK 0x1C00 /* SGMII duplex and speed bits */
140#define LPA_SGMII_10 0x0000 /* 10Mbps */
138#define LPA_SGMII_10HALF 0x0000 /* Can do 10mbps half-duplex */141#define LPA_SGMII_10HALF 0x0000 /* Can do 10mbps half-duplex */
139#define LPA_SGMII_10FULL 0x1000 /* Can do 10mbps full-duplex */142#define LPA_SGMII_10FULL 0x1000 /* Can do 10mbps full-duplex */
143#define LPA_SGMII_100 0x0400 /* 100Mbps */
140#define LPA_SGMII_100HALF 0x0400 /* Can do 100mbps half-duplex */144#define LPA_SGMII_100HALF 0x0400 /* Can do 100mbps half-duplex */
141#define LPA_SGMII_100FULL 0x1400 /* Can do 100mbps full-duplex */145#define LPA_SGMII_100FULL 0x1400 /* Can do 100mbps full-duplex */
146#define LPA_SGMII_1000 0x0800 /* 1000Mbps */
142#define LPA_SGMII_1000HALF 0x0800 /* Can do 1000mbps half-duplex */147#define LPA_SGMII_1000HALF 0x0800 /* Can do 1000mbps half-duplex */
143#define LPA_SGMII_1000FULL 0x1800 /* Can do 1000mbps full-duplex */148#define LPA_SGMII_1000FULL 0x1800 /* Can do 1000mbps full-duplex */
144#define LPA_SGMII_LINK 0x8000 /* PHY link with copper-side partner */149#define LPA_SGMII_LINK 0x8000 /* PHY link with copper-side partner */