History

net: phylink: resolve fixed link flow control

Resolve the fixed link flow control using the recently introduced linkmode_resolve_pause() helper, which we use in phylink_get_fixed_state() only when operating in full duplex mode.

Russell King committed 6 years ago

Commit 4e5aeb41 parent 33faac82 files · +34 −44Browse files

Unified · Split

2 files
  1. drivers/net/phy/phylink.c +31 −39
  2. include/linux/phylink.h +3 −5
drivers/net/phy/phylink.c+31−39
@@ -181,9 +181,11 @@ static int phylink_parse_fixedlink(struct phylink *pl, · 180 unmodified lines
181181 /* We treat the "pause" and "asym-pause" terminology as
182182 * defining the link partner's ability. */
183183 if (fwnode_property_read_bool(fixed_node, "pause"))
184− pl->link_config.pause |= MLO_PAUSE_SYM;
184+ __set_bit(ETHTOOL_LINK_MODE_Pause_BIT,
185+ pl->link_config.lp_advertising);
185186 if (fwnode_property_read_bool(fixed_node, "asym-pause"))
186− pl->link_config.pause |= MLO_PAUSE_ASYM;
187+ __set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
188+ pl->link_config.lp_advertising);
187189
188190 if (ret == 0) {
189191 desc = fwnode_gpiod_get_index(fixed_node, "link", 0,
@@ -215,9 +217,11 @@ static int phylink_parse_fixedlink(struct phylink *pl, · 25 unmodified lines
215217 DUPLEX_FULL : DUPLEX_HALF;
216218 pl->link_config.speed = prop[2];
217219 if (prop[3])
218− pl->link_config.pause |= MLO_PAUSE_SYM;
220+ __set_bit(ETHTOOL_LINK_MODE_Pause_BIT,
221+ pl->link_config.lp_advertising);
219222 if (prop[4])
220− pl->link_config.pause |= MLO_PAUSE_ASYM;
223+ __set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
224+ pl->link_config.lp_advertising);
221225 }
222226 }
223227
@@ -351,6 +355,22 @@ static void phylink_apply_manual_flow(struct phylink *pl, · 127 unmodified lines
351355 state->pause = pl->link_config.pause;
352356 }
353357
358+static void phylink_resolve_flow(struct phylink_link_state *state)
359+{
360+ bool tx_pause, rx_pause;
361+
362+ state->pause = MLO_PAUSE_NONE;
363+ if (state->duplex == DUPLEX_FULL) {
364+ linkmode_resolve_pause(state->advertising,
365+ state->lp_advertising,
366+ &tx_pause, &rx_pause);
367+ if (tx_pause)
368+ state->pause |= MLO_PAUSE_TX;
369+ if (rx_pause)
370+ state->pause |= MLO_PAUSE_RX;
371+ }
372+}
373+
354374 static void phylink_mac_config(struct phylink *pl,
355375 const struct phylink_link_state *state)
356376 {
@@ -399,44 +419,16 @@ static void phylink_mac_pcs_get_state(struct phylink *pl, · 42 unmodified lines
399419 /* The fixed state is... fixed except for the link state,
400420 * which may be determined by a GPIO or a callback.
401421 */
402−static void phylink_get_fixed_state(struct phylink *pl, struct phylink_link_state *state)
422+static void phylink_get_fixed_state(struct phylink *pl,
423+ struct phylink_link_state *state)
403424 {
404425 *state = pl->link_config;
405426 if (pl->get_fixed_state)
406427 pl->get_fixed_state(pl->netdev, state);
407428 else if (pl->link_gpio)
408429 state->link = !!gpiod_get_value_cansleep(pl->link_gpio);
409−}
410430
411−/* Flow control is resolved according to our and the link partners
412− * advertisements using the following drawn from the 802.3 specs:
413− * Local device Link partner
414− * Pause AsymDir Pause AsymDir Result
415− * 1 X 1 X TX+RX
416− * 0 1 1 1 TX
417− * 1 1 0 1 RX
418− */
419−static void phylink_resolve_flow(struct phylink *pl,
420− struct phylink_link_state *state)
421−{
422− int new_pause = 0;
423− int pause = 0;
424−
425− if (phylink_test(pl->link_config.advertising, Pause))
426− pause |= MLO_PAUSE_SYM;
427− if (phylink_test(pl->link_config.advertising, Asym_Pause))
428− pause |= MLO_PAUSE_ASYM;
429−
430− pause &= state->pause;
431−
432− if (pause & MLO_PAUSE_SYM)
433− new_pause = MLO_PAUSE_TX | MLO_PAUSE_RX;
434− else if (pause & MLO_PAUSE_ASYM)
435− new_pause = state->pause & MLO_PAUSE_SYM ?
436− MLO_PAUSE_TX : MLO_PAUSE_RX;
437−
438− state->pause &= ~MLO_PAUSE_TXRX_MASK;
439− state->pause |= new_pause;
431+ phylink_resolve_flow(state);
440432 }
441433
442434 static const char *phylink_pause_to_str(int pause)
@@ -1393,8 +1385,7 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl, · 950 unmodified lines
13931385 !pause->autoneg && pause->rx_pause != pause->tx_pause)
13941386 return -EINVAL;
13951387
1396− config->pause &= ~(MLO_PAUSE_AN | MLO_PAUSE_TXRX_MASK);
1397−
1388+ config->pause = 0;
13981389 if (pause->autoneg)
13991390 config->pause |= MLO_PAUSE_AN;
14001391 if (pause->rx_pause)
@@ -1505,13 +1496,14 @@ static int phylink_mii_emul_read(unsigned int reg, · 104 unmodified lines
15051496 struct phylink_link_state *state)
15061497 {
15071498 struct fixed_phy_status fs;
1499+ unsigned long *lpa = state->lp_advertising;
15081500 int val;
15091501
15101502 fs.link = state->link;
15111503 fs.speed = state->speed;
15121504 fs.duplex = state->duplex;
1513− fs.pause = state->pause & MLO_PAUSE_SYM;
1514− fs.asym_pause = state->pause & MLO_PAUSE_ASYM;
1505+ fs.pause = test_bit(ETHTOOL_LINK_MODE_Pause_BIT, lpa);
1506+ fs.asym_pause = test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, lpa);
15151507
15161508 val = swphy_read_reg(reg, &fs);
15171509 if (reg == MII_BMSR) {
include/linux/phylink.h+3−5
@@ -12,12 +12,10 @@ struct net_device; · 11 unmodified lines
1212
1313 enum {
1414 MLO_PAUSE_NONE,
15− MLO_PAUSE_ASYM = BIT(0),
16− MLO_PAUSE_SYM = BIT(1),
17− MLO_PAUSE_RX = BIT(2),
18− MLO_PAUSE_TX = BIT(3),
15+ MLO_PAUSE_RX = BIT(0),
16+ MLO_PAUSE_TX = BIT(1),
1917 MLO_PAUSE_TXRX_MASK = MLO_PAUSE_TX | MLO_PAUSE_RX,
20− MLO_PAUSE_AN = BIT(4),
18+ MLO_PAUSE_AN = BIT(2),
2119
2220 MLO_AN_PHY = 0, /* Conventional PHY */
2321 MLO_AN_FIXED, /* Fixed-link mode */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t