436-phylink-propagate-PHY-interface-mode-to-MAC-driver.patch 4.1 KB

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