792-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. From 90ef0a7b0622c62758b2638604927867775479ea Mon Sep 17 00:00:00 2001
  2. From: "Russell King (Oracle)" <[email protected]>
  3. Date: Thu, 13 Jul 2023 09:42:07 +0100
  4. Subject: [PATCH] net: phylink: add pcs_enable()/pcs_disable() methods
  5. Add phylink PCS enable/disable callbacks that will allow us to place
  6. IEEE 802.3 register compliant PCS in power-down mode while not being
  7. used.
  8. Signed-off-by: Russell King (Oracle) <[email protected]>
  9. Signed-off-by: David S. Miller <[email protected]>
  10. ---
  11. drivers/net/phy/phylink.c | 48 +++++++++++++++++++++++++++++++--------
  12. include/linux/phylink.h | 16 +++++++++++++
  13. 2 files changed, 55 insertions(+), 9 deletions(-)
  14. --- a/drivers/net/phy/phylink.c
  15. +++ b/drivers/net/phy/phylink.c
  16. @@ -34,6 +34,10 @@ enum {
  17. PHYLINK_DISABLE_STOPPED,
  18. PHYLINK_DISABLE_LINK,
  19. PHYLINK_DISABLE_MAC_WOL,
  20. +
  21. + PCS_STATE_DOWN = 0,
  22. + PCS_STATE_STARTING,
  23. + PCS_STATE_STARTED,
  24. };
  25. /**
  26. @@ -71,6 +75,7 @@ struct phylink {
  27. struct mutex state_mutex;
  28. struct phylink_link_state phy_state;
  29. struct work_struct resolve;
  30. + unsigned int pcs_state;
  31. bool mac_link_dropped;
  32. bool using_mac_select_pcs;
  33. @@ -990,6 +995,22 @@ static void phylink_mac_pcs_an_restart(s
  34. }
  35. }
  36. +static void phylink_pcs_disable(struct phylink_pcs *pcs)
  37. +{
  38. + if (pcs && pcs->ops->pcs_disable)
  39. + pcs->ops->pcs_disable(pcs);
  40. +}
  41. +
  42. +static int phylink_pcs_enable(struct phylink_pcs *pcs)
  43. +{
  44. + int err = 0;
  45. +
  46. + if (pcs && pcs->ops->pcs_enable)
  47. + err = pcs->ops->pcs_enable(pcs);
  48. +
  49. + return err;
  50. +}
  51. +
  52. static void phylink_major_config(struct phylink *pl, bool restart,
  53. const struct phylink_link_state *state)
  54. {
  55. @@ -1026,11 +1047,16 @@ static void phylink_major_config(struct
  56. /* If we have a new PCS, switch to the new PCS after preparing the MAC
  57. * for the change.
  58. */
  59. - if (pcs_changed)
  60. + if (pcs_changed) {
  61. + phylink_pcs_disable(pl->pcs);
  62. pl->pcs = pcs;
  63. + }
  64. phylink_mac_config(pl, state);
  65. + if (pl->pcs_state == PCS_STATE_STARTING || pcs_changed)
  66. + phylink_pcs_enable(pl->pcs);
  67. +
  68. if (pl->pcs) {
  69. err = pl->pcs->ops->pcs_config(pl->pcs, pl->cur_link_an_mode,
  70. state->interface,
  71. @@ -1502,6 +1528,7 @@ struct phylink *phylink_create(struct ph
  72. pl->link_config.speed = SPEED_UNKNOWN;
  73. pl->link_config.duplex = DUPLEX_UNKNOWN;
  74. pl->link_config.an_enabled = true;
  75. + pl->pcs_state = PCS_STATE_DOWN;
  76. pl->mac_ops = mac_ops;
  77. __set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
  78. timer_setup(&pl->link_poll, phylink_fixed_poll, 0);
  79. @@ -1903,6 +1930,8 @@ void phylink_start(struct phylink *pl)
  80. if (pl->netdev)
  81. netif_carrier_off(pl->netdev);
  82. + pl->pcs_state = PCS_STATE_STARTING;
  83. +
  84. /* Apply the link configuration to the MAC when starting. This allows
  85. * a fixed-link to start with the correct parameters, and also
  86. * ensures that we set the appropriate advertisement for Serdes links.
  87. @@ -1913,6 +1942,8 @@ void phylink_start(struct phylink *pl)
  88. */
  89. phylink_mac_initial_config(pl, true);
  90. + pl->pcs_state = PCS_STATE_STARTED;
  91. +
  92. phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_STOPPED);
  93. if (pl->cfg_link_an_mode == MLO_AN_FIXED && pl->link_gpio) {
  94. @@ -1931,15 +1962,9 @@ void phylink_start(struct phylink *pl)
  95. poll = true;
  96. }
  97. - switch (pl->cfg_link_an_mode) {
  98. - case MLO_AN_FIXED:
  99. + if (pl->cfg_link_an_mode == MLO_AN_FIXED)
  100. poll |= pl->config->poll_fixed_state;
  101. - break;
  102. - case MLO_AN_INBAND:
  103. - if (pl->pcs)
  104. - poll |= pl->pcs->poll;
  105. - break;
  106. - }
  107. +
  108. if (poll)
  109. mod_timer(&pl->link_poll, jiffies + HZ);
  110. if (pl->phydev)
  111. @@ -1976,6 +2001,10 @@ void phylink_stop(struct phylink *pl)
  112. }
  113. phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_STOPPED);
  114. +
  115. + pl->pcs_state = PCS_STATE_DOWN;
  116. +
  117. + phylink_pcs_disable(pl->pcs);
  118. }
  119. EXPORT_SYMBOL_GPL(phylink_stop);
  120. --- a/include/linux/phylink.h
  121. +++ b/include/linux/phylink.h
  122. @@ -446,6 +446,8 @@ struct phylink_pcs {
  123. /**
  124. * struct phylink_pcs_ops - MAC PCS operations structure.
  125. * @pcs_validate: validate the link configuration.
  126. + * @pcs_enable: enable the PCS.
  127. + * @pcs_disable: disable the PCS.
  128. * @pcs_get_state: read the current MAC PCS link state from the hardware.
  129. * @pcs_config: configure the MAC PCS for the selected mode and state.
  130. * @pcs_an_restart: restart 802.3z BaseX autonegotiation.
  131. @@ -455,6 +457,8 @@ struct phylink_pcs {
  132. struct phylink_pcs_ops {
  133. int (*pcs_validate)(struct phylink_pcs *pcs, unsigned long *supported,
  134. const struct phylink_link_state *state);
  135. + int (*pcs_enable)(struct phylink_pcs *pcs);
  136. + void (*pcs_disable)(struct phylink_pcs *pcs);
  137. void (*pcs_get_state)(struct phylink_pcs *pcs,
  138. struct phylink_link_state *state);
  139. int (*pcs_config)(struct phylink_pcs *pcs, unsigned int mode,
  140. @@ -485,6 +489,18 @@ int pcs_validate(struct phylink_pcs *pcs
  141. const struct phylink_link_state *state);
  142. /**
  143. + * pcs_enable() - enable the PCS.
  144. + * @pcs: a pointer to a &struct phylink_pcs.
  145. + */
  146. +int pcs_enable(struct phylink_pcs *pcs);
  147. +
  148. +/**
  149. + * pcs_disable() - disable the PCS.
  150. + * @pcs: a pointer to a &struct phylink_pcs.
  151. + */
  152. +void pcs_disable(struct phylink_pcs *pcs);
  153. +
  154. +/**
  155. * pcs_get_state() - Read the current inband link state from the hardware
  156. * @pcs: a pointer to a &struct phylink_pcs.
  157. * @state: a pointer to a &struct phylink_link_state.