400-phy-provide-a-hook-for-link-up-link-down-events.patch 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. From: Russell King <[email protected]>
  2. Date: Sun, 12 Feb 2017 17:27:17 +0100
  3. Subject: [PATCH] phy: provide a hook for link up/link down events
  4. Sometimes, we need to do additional work between the PHY coming up and
  5. marking the carrier present - for example, we may need to wait for the
  6. PHY to MAC link to finish negotiation. This changes phylib to provide
  7. a notification function pointer which avoids the built-in
  8. netif_carrier_on() and netif_carrier_off() functions.
  9. Standard ->adjust_link functionality is provided by hooking a helper
  10. into the new ->phy_link_change method.
  11. Signed-off-by: Russell King <[email protected]>
  12. ---
  13. --- a/drivers/net/phy/phy.c
  14. +++ b/drivers/net/phy/phy.c
  15. @@ -991,6 +991,16 @@ void phy_start(struct phy_device *phydev
  16. }
  17. EXPORT_SYMBOL(phy_start);
  18. +static void phy_link_up(struct phy_device *phydev)
  19. +{
  20. + phydev->phy_link_change(phydev, true, true);
  21. +}
  22. +
  23. +static void phy_link_down(struct phy_device *phydev, bool do_carrier)
  24. +{
  25. + phydev->phy_link_change(phydev, false, do_carrier);
  26. +}
  27. +
  28. /**
  29. * phy_state_machine - Handle the state machine
  30. * @work: work_struct that describes the work to be done
  31. @@ -1032,8 +1042,7 @@ void phy_state_machine(struct work_struc
  32. /* If the link is down, give up on negotiation for now */
  33. if (!phydev->link) {
  34. phydev->state = PHY_NOLINK;
  35. - netif_carrier_off(phydev->attached_dev);
  36. - phydev->adjust_link(phydev->attached_dev);
  37. + phy_link_down(phydev, true);
  38. break;
  39. }
  40. @@ -1045,9 +1054,7 @@ void phy_state_machine(struct work_struc
  41. /* If AN is done, we're running */
  42. if (err > 0) {
  43. phydev->state = PHY_RUNNING;
  44. - netif_carrier_on(phydev->attached_dev);
  45. - phydev->adjust_link(phydev->attached_dev);
  46. -
  47. + phy_link_up(phydev);
  48. } else if (0 == phydev->link_timeout--)
  49. needs_aneg = true;
  50. break;
  51. @@ -1072,8 +1079,7 @@ void phy_state_machine(struct work_struc
  52. }
  53. }
  54. phydev->state = PHY_RUNNING;
  55. - netif_carrier_on(phydev->attached_dev);
  56. - phydev->adjust_link(phydev->attached_dev);
  57. + phy_link_up(phydev);
  58. }
  59. break;
  60. case PHY_FORCING:
  61. @@ -1083,13 +1089,12 @@ void phy_state_machine(struct work_struc
  62. if (phydev->link) {
  63. phydev->state = PHY_RUNNING;
  64. - netif_carrier_on(phydev->attached_dev);
  65. + phy_link_up(phydev);
  66. } else {
  67. if (0 == phydev->link_timeout--)
  68. needs_aneg = true;
  69. + phy_link_down(phydev, false);
  70. }
  71. -
  72. - phydev->adjust_link(phydev->attached_dev);
  73. break;
  74. case PHY_RUNNING:
  75. /* Only register a CHANGE if we are polling and link changed
  76. @@ -1112,14 +1117,12 @@ void phy_state_machine(struct work_struc
  77. if (phydev->link) {
  78. phydev->state = PHY_RUNNING;
  79. - netif_carrier_on(phydev->attached_dev);
  80. + phy_link_up(phydev);
  81. } else {
  82. phydev->state = PHY_NOLINK;
  83. - netif_carrier_off(phydev->attached_dev);
  84. + phy_link_down(phydev, true);
  85. }
  86. - phydev->adjust_link(phydev->attached_dev);
  87. -
  88. if (phy_interrupt_is_valid(phydev))
  89. err = phy_config_interrupt(phydev,
  90. PHY_INTERRUPT_ENABLED);
  91. @@ -1127,8 +1130,7 @@ void phy_state_machine(struct work_struc
  92. case PHY_HALTED:
  93. if (phydev->link) {
  94. phydev->link = 0;
  95. - netif_carrier_off(phydev->attached_dev);
  96. - phydev->adjust_link(phydev->attached_dev);
  97. + phy_link_down(phydev, true);
  98. do_suspend = true;
  99. }
  100. break;
  101. @@ -1148,11 +1150,11 @@ void phy_state_machine(struct work_struc
  102. if (phydev->link) {
  103. phydev->state = PHY_RUNNING;
  104. - netif_carrier_on(phydev->attached_dev);
  105. + phy_link_up(phydev);
  106. } else {
  107. phydev->state = PHY_NOLINK;
  108. + phy_link_down(phydev, false);
  109. }
  110. - phydev->adjust_link(phydev->attached_dev);
  111. } else {
  112. phydev->state = PHY_AN;
  113. phydev->link_timeout = PHY_AN_TIMEOUT;
  114. @@ -1164,11 +1166,11 @@ void phy_state_machine(struct work_struc
  115. if (phydev->link) {
  116. phydev->state = PHY_RUNNING;
  117. - netif_carrier_on(phydev->attached_dev);
  118. + phy_link_up(phydev);
  119. } else {
  120. phydev->state = PHY_NOLINK;
  121. + phy_link_down(phydev, false);
  122. }
  123. - phydev->adjust_link(phydev->attached_dev);
  124. }
  125. break;
  126. }
  127. --- a/drivers/net/phy/phy_device.c
  128. +++ b/drivers/net/phy/phy_device.c
  129. @@ -645,6 +645,19 @@ struct phy_device *phy_find_first(struct
  130. }
  131. EXPORT_SYMBOL(phy_find_first);
  132. +static void phy_link_change(struct phy_device *phydev, bool up, bool do_carrier)
  133. +{
  134. + struct net_device *netdev = phydev->attached_dev;
  135. +
  136. + if (do_carrier) {
  137. + if (up)
  138. + netif_carrier_on(netdev);
  139. + else
  140. + netif_carrier_off(netdev);
  141. + }
  142. + phydev->adjust_link(netdev);
  143. +}
  144. +
  145. /**
  146. * phy_prepare_link - prepares the PHY layer to monitor link status
  147. * @phydev: target phy_device struct
  148. @@ -910,6 +923,7 @@ int phy_attach_direct(struct net_device
  149. goto error;
  150. }
  151. + phydev->phy_link_change = phy_link_change;
  152. phydev->attached_dev = dev;
  153. dev->phydev = phydev;
  154. --- a/include/linux/phy.h
  155. +++ b/include/linux/phy.h
  156. @@ -429,6 +429,7 @@ struct phy_device {
  157. u8 mdix;
  158. + void (*phy_link_change)(struct phy_device *, bool up, bool do_carrier);
  159. void (*adjust_link)(struct net_device *dev);
  160. };
  161. #define to_phy_device(d) container_of(to_mdio_device(d), \