737-v5.5-net-phy-add-core-phylib-sfp-support.patch 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. From eb156db588ac583cdae7b91eaac9c0ad3a358e63 Mon Sep 17 00:00:00 2001
  2. From: Russell King <[email protected]>
  3. Date: Sun, 15 Sep 2019 20:05:34 +0100
  4. Subject: [PATCH 635/660] net: phy: add core phylib sfp support
  5. Add core phylib help for supporting SFP sockets on PHYs. This provides
  6. a mechanism to inform the SFP layer about PHY up/down events, and also
  7. unregister the SFP bus when the PHY is going away.
  8. Signed-off-by: Russell King <[email protected]>
  9. ---
  10. drivers/net/phy/phy.c | 7 ++++
  11. drivers/net/phy/phy_device.c | 66 ++++++++++++++++++++++++++++++++++++
  12. include/linux/phy.h | 11 ++++++
  13. 3 files changed, 84 insertions(+)
  14. --- a/drivers/net/phy/phy.c
  15. +++ b/drivers/net/phy/phy.c
  16. @@ -30,6 +30,7 @@
  17. #include <linux/ethtool.h>
  18. #include <linux/phy.h>
  19. #include <linux/phy_led_triggers.h>
  20. +#include <linux/sfp.h>
  21. #include <linux/workqueue.h>
  22. #include <linux/mdio.h>
  23. #include <linux/io.h>
  24. @@ -871,6 +872,9 @@ void phy_stop(struct phy_device *phydev)
  25. if (phy_interrupt_is_valid(phydev))
  26. phy_disable_interrupts(phydev);
  27. + if (phydev->sfp_bus)
  28. + sfp_upstream_stop(phydev->sfp_bus);
  29. +
  30. phydev->state = PHY_HALTED;
  31. out_unlock:
  32. @@ -899,6 +903,9 @@ void phy_start(struct phy_device *phydev
  33. mutex_lock(&phydev->lock);
  34. + if (phydev->sfp_bus)
  35. + sfp_upstream_start(phydev->sfp_bus);
  36. +
  37. switch (phydev->state) {
  38. case PHY_STARTING:
  39. phydev->state = PHY_PENDING;
  40. --- a/drivers/net/phy/phy_device.c
  41. +++ b/drivers/net/phy/phy_device.c
  42. @@ -31,6 +31,7 @@
  43. #include <linux/ethtool.h>
  44. #include <linux/phy.h>
  45. #include <linux/phy_led_triggers.h>
  46. +#include <linux/sfp.h>
  47. #include <linux/mdio.h>
  48. #include <linux/io.h>
  49. #include <linux/uaccess.h>
  50. @@ -944,6 +945,65 @@ void phy_attached_print(struct phy_devic
  51. EXPORT_SYMBOL(phy_attached_print);
  52. /**
  53. + * phy_sfp_attach - attach the SFP bus to the PHY upstream network device
  54. + * @upstream: pointer to the phy device
  55. + * @bus: sfp bus representing cage being attached
  56. + *
  57. + * This is used to fill in the sfp_upstream_ops .attach member.
  58. + */
  59. +void phy_sfp_attach(void *upstream, struct sfp_bus *bus)
  60. +{
  61. + struct phy_device *phydev = upstream;
  62. +
  63. + if (phydev->attached_dev)
  64. + phydev->attached_dev->sfp_bus = bus;
  65. + phydev->sfp_bus_attached = true;
  66. +}
  67. +EXPORT_SYMBOL(phy_sfp_attach);
  68. +
  69. +/**
  70. + * phy_sfp_detach - detach the SFP bus from the PHY upstream network device
  71. + * @upstream: pointer to the phy device
  72. + * @bus: sfp bus representing cage being attached
  73. + *
  74. + * This is used to fill in the sfp_upstream_ops .detach member.
  75. + */
  76. +void phy_sfp_detach(void *upstream, struct sfp_bus *bus)
  77. +{
  78. + struct phy_device *phydev = upstream;
  79. +
  80. + if (phydev->attached_dev)
  81. + phydev->attached_dev->sfp_bus = NULL;
  82. + phydev->sfp_bus_attached = false;
  83. +}
  84. +EXPORT_SYMBOL(phy_sfp_detach);
  85. +
  86. +/**
  87. + * phy_sfp_probe - probe for a SFP cage attached to this PHY device
  88. + * @phydev: Pointer to phy_device
  89. + * @ops: SFP's upstream operations
  90. + */
  91. +int phy_sfp_probe(struct phy_device *phydev,
  92. + const struct sfp_upstream_ops *ops)
  93. +{
  94. + struct sfp_bus *bus;
  95. + int ret;
  96. +
  97. + if (phydev->mdio.dev.fwnode) {
  98. + bus = sfp_bus_find_fwnode(phydev->mdio.dev.fwnode);
  99. + if (IS_ERR(bus))
  100. + return PTR_ERR(bus);
  101. +
  102. + phydev->sfp_bus = bus;
  103. +
  104. + ret = sfp_bus_add_upstream(bus, phydev, ops);
  105. + sfp_bus_put(bus);
  106. + }
  107. + return 0;
  108. +}
  109. +EXPORT_SYMBOL(phy_sfp_probe);
  110. +
  111. +/**
  112. * phy_attach_direct - attach a network device to a given PHY device pointer
  113. * @dev: network device to attach
  114. * @phydev: Pointer to phy_device to attach
  115. @@ -1016,6 +1076,9 @@ int phy_attach_direct(struct net_device
  116. phydev->attached_dev = dev;
  117. dev->phydev = phydev;
  118. + if (phydev->sfp_bus_attached)
  119. + dev->sfp_bus = phydev->sfp_bus;
  120. +
  121. /* Some Ethernet drivers try to connect to a PHY device before
  122. * calling register_netdevice() -> netdev_register_kobject() and
  123. * does the dev->dev.kobj initialization. Here we only check for
  124. @@ -1950,6 +2013,9 @@ static int phy_remove(struct device *dev
  125. phydev->state = PHY_DOWN;
  126. mutex_unlock(&phydev->lock);
  127. + sfp_bus_del_upstream(phydev->sfp_bus);
  128. + phydev->sfp_bus = NULL;
  129. +
  130. if (phydev->drv && phydev->drv->remove) {
  131. phydev->drv->remove(phydev);
  132. --- a/include/linux/phy.h
  133. +++ b/include/linux/phy.h
  134. @@ -184,6 +184,8 @@ static inline const char *phy_modes(phy_
  135. struct device;
  136. struct phylink;
  137. +struct sfp_bus;
  138. +struct sfp_upstream_ops;
  139. struct sk_buff;
  140. /*
  141. @@ -382,6 +384,8 @@ struct phy_c45_device_ids {
  142. * irq: IRQ number of the PHY's interrupt (-1 if none)
  143. * phy_timer: The timer for handling the state machine
  144. * phy_queue: A work_queue for the phy_mac_interrupt
  145. + * sfp_bus_attached: flag indicating whether the SFP bus has been attached
  146. + * sfp_bus: SFP bus attached to this PHY's fiber port
  147. * attached_dev: The attached enet driver's device instance ptr
  148. * adjust_link: Callback for the enet controller to respond to
  149. * changes in the link state.
  150. @@ -471,6 +475,9 @@ struct phy_device {
  151. struct mutex lock;
  152. + /* This may be modified under the rtnl lock */
  153. + bool sfp_bus_attached;
  154. + struct sfp_bus *sfp_bus;
  155. struct phylink *phylink;
  156. struct net_device *attached_dev;
  157. @@ -1031,6 +1038,10 @@ int phy_suspend(struct phy_device *phyde
  158. int phy_resume(struct phy_device *phydev);
  159. int __phy_resume(struct phy_device *phydev);
  160. int phy_loopback(struct phy_device *phydev, bool enable);
  161. +void phy_sfp_attach(void *upstream, struct sfp_bus *bus);
  162. +void phy_sfp_detach(void *upstream, struct sfp_bus *bus);
  163. +int phy_sfp_probe(struct phy_device *phydev,
  164. + const struct sfp_upstream_ops *ops);
  165. struct phy_device *phy_attach(struct net_device *dev, const char *bus_id,
  166. phy_interface_t interface);
  167. struct phy_device *phy_find_first(struct mii_bus *bus);