2
0

416-phylink-add-hooks-for-SFP-support.patch 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. From: Russell King <[email protected]>
  2. Date: Thu, 24 Sep 2015 11:01:13 +0100
  3. Subject: [PATCH] phylink: add hooks for SFP support
  4. Add support to phylink for SFP, which needs to control and configure
  5. the ethernet MAC link state. Specifically, SFP needs to:
  6. 1. set the negotiation mode between SGMII and 1000base-X
  7. 2. attach and detach the module PHY
  8. 3. prevent the link coming up when errors are reported
  9. In the absence of a PHY, we also need to set the ethtool port type
  10. according to the module plugged in.
  11. Reviewed-by: Florian Fainelli <[email protected]>
  12. Signed-off-by: Russell King <[email protected]>
  13. - rework phylink_set_link_*(), combining into a single function.
  14. ---
  15. --- a/drivers/net/phy/phylink.c
  16. +++ b/drivers/net/phy/phylink.c
  17. @@ -11,6 +11,7 @@
  18. #include <linux/ethtool.h>
  19. #include <linux/export.h>
  20. #include <linux/gpio/consumer.h>
  21. +#include <linux/list.h>
  22. #include <linux/netdevice.h>
  23. #include <linux/of.h>
  24. #include <linux/of_mdio.h>
  25. @@ -29,11 +30,16 @@
  26. (ADVERTISED_TP | ADVERTISED_MII | ADVERTISED_FIBRE | \
  27. ADVERTISED_BNC | ADVERTISED_AUI | ADVERTISED_Backplane)
  28. +static LIST_HEAD(phylinks);
  29. +static DEFINE_MUTEX(phylink_mutex);
  30. +
  31. enum {
  32. PHYLINK_DISABLE_STOPPED,
  33. + PHYLINK_DISABLE_LINK,
  34. };
  35. struct phylink {
  36. + struct list_head node;
  37. struct net_device *netdev;
  38. const struct phylink_mac_ops *ops;
  39. struct mutex config_mutex;
  40. @@ -375,12 +381,20 @@ struct phylink *phylink_create(struct ne
  41. phylink_init_advert(pl, pl->link_an_mode, pl->supported,
  42. pl->link_config.advertising);
  43. + mutex_lock(&phylink_mutex);
  44. + list_add_tail(&pl->node, &phylinks);
  45. + mutex_unlock(&phylink_mutex);
  46. +
  47. return pl;
  48. }
  49. EXPORT_SYMBOL_GPL(phylink_create);
  50. void phylink_destroy(struct phylink *pl)
  51. {
  52. + mutex_lock(&phylink_mutex);
  53. + list_del(&pl->node);
  54. + mutex_unlock(&phylink_mutex);
  55. +
  56. cancel_work_sync(&pl->resolve);
  57. kfree(pl);
  58. }
  59. @@ -900,4 +914,93 @@ int phylink_mii_ioctl(struct phylink *pl
  60. }
  61. EXPORT_SYMBOL_GPL(phylink_mii_ioctl);
  62. +
  63. +
  64. +void phylink_disable(struct phylink *pl)
  65. +{
  66. + set_bit(PHYLINK_DISABLE_LINK, &pl->phylink_disable_state);
  67. + flush_work(&pl->resolve);
  68. +
  69. + netif_carrier_off(pl->netdev);
  70. +}
  71. +EXPORT_SYMBOL_GPL(phylink_disable);
  72. +
  73. +void phylink_enable(struct phylink *pl)
  74. +{
  75. + clear_bit(PHYLINK_DISABLE_LINK, &pl->phylink_disable_state);
  76. + phylink_run_resolve(pl);
  77. +}
  78. +EXPORT_SYMBOL_GPL(phylink_enable);
  79. +
  80. +int phylink_set_link(struct phylink *pl, unsigned int mode, u8 port,
  81. + const unsigned long *support)
  82. +{
  83. + __ETHTOOL_DECLARE_LINK_MODE_MASK(mask);
  84. + int ret = 0;
  85. +
  86. + netdev_dbg(pl->netdev, "requesting link mode %s with support %*pb\n",
  87. + phylink_an_mode_str(mode),
  88. + __ETHTOOL_LINK_MODE_MASK_NBITS, support);
  89. +
  90. + if (mode == MLO_AN_FIXED)
  91. + return -EINVAL;
  92. +
  93. + linkmode_copy(mask, support);
  94. +
  95. + /* Ignore errors if we're expecting a PHY to attach later */
  96. + ret = phylink_validate_support(pl, mode, mask);
  97. + if (ret && mode != MLO_AN_PHY)
  98. + return ret;
  99. +
  100. + mutex_lock(&pl->config_mutex);
  101. + if (mode == MLO_AN_8023Z && pl->phydev) {
  102. + ret = -EINVAL;
  103. + } else {
  104. + bool changed = !bitmap_equal(pl->supported, mask,
  105. + __ETHTOOL_LINK_MODE_MASK_NBITS);
  106. + if (changed) {
  107. + linkmode_copy(pl->supported, mask);
  108. +
  109. + phylink_init_advert(pl, mode, mask,
  110. + pl->link_config.advertising);
  111. + }
  112. +
  113. + if (pl->link_an_mode != mode) {
  114. + pl->link_an_mode = mode;
  115. +
  116. + changed = true;
  117. +
  118. + netdev_info(pl->netdev, "switched to %s link mode\n",
  119. + phylink_an_mode_str(mode));
  120. + }
  121. +
  122. + pl->link_port = port;
  123. +
  124. + if (changed && !test_bit(PHYLINK_DISABLE_STOPPED,
  125. + &pl->phylink_disable_state))
  126. + phylink_mac_config(pl, &pl->link_config);
  127. + }
  128. + mutex_unlock(&pl->config_mutex);
  129. +
  130. + return ret;
  131. +}
  132. +EXPORT_SYMBOL_GPL(phylink_set_link);
  133. +
  134. +struct phylink *phylink_lookup_by_netdev(struct net_device *ndev)
  135. +{
  136. + struct phylink *pl, *found = NULL;
  137. +
  138. + mutex_lock(&phylink_mutex);
  139. + list_for_each_entry(pl, &phylinks, node)
  140. + if (pl->netdev == ndev) {
  141. + found = pl;
  142. + break;
  143. + }
  144. +
  145. + mutex_unlock(&phylink_mutex);
  146. +
  147. + return found;
  148. +}
  149. +EXPORT_SYMBOL_GPL(phylink_lookup_by_netdev);
  150. +
  151. MODULE_LICENSE("GPL");
  152. --- a/include/linux/phylink.h
  153. +++ b/include/linux/phylink.h
  154. @@ -88,6 +88,12 @@ int phylink_ethtool_ksettings_set(struct
  155. const struct ethtool_link_ksettings *);
  156. int phylink_mii_ioctl(struct phylink *, struct ifreq *, int);
  157. +int phylink_set_link(struct phylink *pl, unsigned int mode, u8 port,
  158. + const unsigned long *support);
  159. +void phylink_disable(struct phylink *pl);
  160. +void phylink_enable(struct phylink *pl);
  161. +struct phylink *phylink_lookup_by_netdev(struct net_device *ndev);
  162. +
  163. #define phylink_zero(bm) \
  164. bitmap_zero(bm, __ETHTOOL_LINK_MODE_MASK_NBITS)
  165. #define __phylink_do_bit(op, bm, mode) \