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
181 /* We treat the "pause" and "asym-pause" terminology as181 /* We treat the "pause" and "asym-pause" terminology as
182 * defining the link partner's ability. */182 * defining the link partner's ability. */
183 if (fwnode_property_read_bool(fixed_node, "pause"))183 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);
185 if (fwnode_property_read_bool(fixed_node, "asym-pause"))186 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);
187 189
188 if (ret == 0) {190 if (ret == 0) {
189 desc = fwnode_gpiod_get_index(fixed_node, "link", 0,191 desc = fwnode_gpiod_get_index(fixed_node, "link", 0,
@@ -215,9 +217,11 @@ static int phylink_parse_fixedlink(struct phylink *pl, · 25 unmodified lines
215 DUPLEX_FULL : DUPLEX_HALF;217 DUPLEX_FULL : DUPLEX_HALF;
216 pl->link_config.speed = prop[2];218 pl->link_config.speed = prop[2];
217 if (prop[3])219 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);
219 if (prop[4])222 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);
221 }225 }
222 }226 }
223 227
@@ -351,6 +355,22 @@ static void phylink_apply_manual_flow(struct phylink *pl, · 127 unmodified lines
351 state->pause = pl->link_config.pause;355 state->pause = pl->link_config.pause;
352}356}
353 357
358static 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
354static void phylink_mac_config(struct phylink *pl,374static void phylink_mac_config(struct phylink *pl,
355 const struct phylink_link_state *state)375 const struct phylink_link_state *state)
356{376{
@@ -399,44 +419,16 @@ static void phylink_mac_pcs_get_state(struct phylink *pl, · 42 unmodified lines
399/* The fixed state is... fixed except for the link state,419/* The fixed state is... fixed except for the link state,
400 * which may be determined by a GPIO or a callback.420 * which may be determined by a GPIO or a callback.
401 */421 */
402static void phylink_get_fixed_state(struct phylink *pl, struct phylink_link_state *state)422static void phylink_get_fixed_state(struct phylink *pl,
423 struct phylink_link_state *state)
403{424{
404 *state = pl->link_config;425 *state = pl->link_config;
405 if (pl->get_fixed_state)426 if (pl->get_fixed_state)
406 pl->get_fixed_state(pl->netdev, state);427 pl->get_fixed_state(pl->netdev, state);
407 else if (pl->link_gpio)428 else if (pl->link_gpio)
408 state->link = !!gpiod_get_value_cansleep(pl->link_gpio);429 state->link = !!gpiod_get_value_cansleep(pl->link_gpio);
409}
410 430
411/* Flow control is resolved according to our and the link partners431 phylink_resolve_flow(state);
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 */
419static 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;
440}432}
441 433
442static const char *phylink_pause_to_str(int pause)434static const char *phylink_pause_to_str(int pause)
@@ -1393,8 +1385,7 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl, · 950 unmodified lines
1393 !pause->autoneg && pause->rx_pause != pause->tx_pause)1385 !pause->autoneg && pause->rx_pause != pause->tx_pause)
1394 return -EINVAL;1386 return -EINVAL;
1395 1387
1396 config->pause &= ~(MLO_PAUSE_AN | MLO_PAUSE_TXRX_MASK);1388 config->pause = 0;
1397
1398 if (pause->autoneg)1389 if (pause->autoneg)
1399 config->pause |= MLO_PAUSE_AN;1390 config->pause |= MLO_PAUSE_AN;
1400 if (pause->rx_pause)1391 if (pause->rx_pause)
@@ -1505,13 +1496,14 @@ static int phylink_mii_emul_read(unsigned int reg, · 104 unmodified lines
1505 struct phylink_link_state *state)1496 struct phylink_link_state *state)
1506{1497{
1507 struct fixed_phy_status fs;1498 struct fixed_phy_status fs;
1499 unsigned long *lpa = state->lp_advertising;
1508 int val;1500 int val;
1509 1501
1510 fs.link = state->link;1502 fs.link = state->link;
1511 fs.speed = state->speed;1503 fs.speed = state->speed;
1512 fs.duplex = state->duplex;1504 fs.duplex = state->duplex;
1513 fs.pause = state->pause & MLO_PAUSE_SYM;1505 fs.pause = test_bit(ETHTOOL_LINK_MODE_Pause_BIT, lpa);
1514 fs.asym_pause = state->pause & MLO_PAUSE_ASYM;1506 fs.asym_pause = test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, lpa);
1515 1507
1516 val = swphy_read_reg(reg, &fs);1508 val = swphy_read_reg(reg, &fs);
1517 if (reg == MII_BMSR) {1509 if (reg == MII_BMSR) {
include/linux/phylink.h+3−5
@@ -12,12 +12,10 @@ struct net_device; · 11 unmodified lines
12 12
13enum {13enum {
14 MLO_PAUSE_NONE,14 MLO_PAUSE_NONE,
15 MLO_PAUSE_ASYM = BIT(0),15 MLO_PAUSE_RX = BIT(0),
16 MLO_PAUSE_SYM = BIT(1),16 MLO_PAUSE_TX = BIT(1),
17 MLO_PAUSE_RX = BIT(2),
18 MLO_PAUSE_TX = BIT(3),
19 MLO_PAUSE_TXRX_MASK = MLO_PAUSE_TX | MLO_PAUSE_RX,17 MLO_PAUSE_TXRX_MASK = MLO_PAUSE_TX | MLO_PAUSE_RX,
20 MLO_PAUSE_AN = BIT(4),18 MLO_PAUSE_AN = BIT(2),
21 19
22 MLO_AN_PHY = 0, /* Conventional PHY */20 MLO_AN_PHY = 0, /* Conventional PHY */
23 MLO_AN_FIXED, /* Fixed-link mode */21 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