744-v5.5-net-sfp-soft-status-and-control-support.patch 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. From 40e0b3b15f7da92e6b065292b14af7b9bfb1c6e0 Mon Sep 17 00:00:00 2001
  2. From: Russell King <[email protected]>
  3. Date: Fri, 13 Sep 2019 23:00:35 +0100
  4. Subject: [PATCH 642/660] net: sfp: soft status and control support
  5. Add support for the soft status and control register, which allows
  6. TX_FAULT and RX_LOS to be monitored and TX_DISABLE to be set. We
  7. make use of this when the board does not support GPIOs for these
  8. signals.
  9. Signed-off-by: Russell King <[email protected]>
  10. ---
  11. drivers/net/phy/sfp.c | 110 ++++++++++++++++++++++++++++++++++--------
  12. include/linux/sfp.h | 4 ++
  13. 2 files changed, 94 insertions(+), 20 deletions(-)
  14. --- a/drivers/net/phy/sfp.c
  15. +++ b/drivers/net/phy/sfp.c
  16. @@ -201,7 +201,10 @@ struct sfp {
  17. struct gpio_desc *gpio[GPIO_MAX];
  18. int gpio_irq[GPIO_MAX];
  19. + bool need_poll;
  20. +
  21. struct mutex st_mutex; /* Protects state */
  22. + unsigned int state_soft_mask;
  23. unsigned int state;
  24. struct delayed_work poll;
  25. struct delayed_work timeout;
  26. @@ -395,24 +398,90 @@ static int sfp_i2c_configure(struct sfp
  27. }
  28. /* Interface */
  29. -static unsigned int sfp_get_state(struct sfp *sfp)
  30. +static int sfp_read(struct sfp *sfp, bool a2, u8 addr, void *buf, size_t len)
  31. {
  32. - return sfp->get_state(sfp);
  33. + return sfp->read(sfp, a2, addr, buf, len);
  34. }
  35. -static void sfp_set_state(struct sfp *sfp, unsigned int state)
  36. +static int sfp_write(struct sfp *sfp, bool a2, u8 addr, void *buf, size_t len)
  37. {
  38. - sfp->set_state(sfp, state);
  39. + return sfp->write(sfp, a2, addr, buf, len);
  40. }
  41. -static int sfp_read(struct sfp *sfp, bool a2, u8 addr, void *buf, size_t len)
  42. +static unsigned int sfp_soft_get_state(struct sfp *sfp)
  43. {
  44. - return sfp->read(sfp, a2, addr, buf, len);
  45. + unsigned int state = 0;
  46. + u8 status;
  47. +
  48. + if (sfp_read(sfp, true, SFP_STATUS, &status, sizeof(status)) ==
  49. + sizeof(status)) {
  50. + if (status & SFP_STATUS_RX_LOS)
  51. + state |= SFP_F_LOS;
  52. + if (status & SFP_STATUS_TX_FAULT)
  53. + state |= SFP_F_TX_FAULT;
  54. + }
  55. +
  56. + return state & sfp->state_soft_mask;
  57. }
  58. -static int sfp_write(struct sfp *sfp, bool a2, u8 addr, void *buf, size_t len)
  59. +static void sfp_soft_set_state(struct sfp *sfp, unsigned int state)
  60. {
  61. - return sfp->write(sfp, a2, addr, buf, len);
  62. + u8 status;
  63. +
  64. + if (sfp_read(sfp, true, SFP_STATUS, &status, sizeof(status)) ==
  65. + sizeof(status)) {
  66. + if (state & SFP_F_TX_DISABLE)
  67. + status |= SFP_STATUS_TX_DISABLE_FORCE;
  68. + else
  69. + status &= ~SFP_STATUS_TX_DISABLE_FORCE;
  70. +
  71. + sfp_write(sfp, true, SFP_STATUS, &status, sizeof(status));
  72. + }
  73. +}
  74. +
  75. +static void sfp_soft_start_poll(struct sfp *sfp)
  76. +{
  77. + const struct sfp_eeprom_id *id = &sfp->id;
  78. +
  79. + sfp->state_soft_mask = 0;
  80. + if (id->ext.enhopts & SFP_ENHOPTS_SOFT_TX_DISABLE &&
  81. + !sfp->gpio[GPIO_TX_DISABLE])
  82. + sfp->state_soft_mask |= SFP_F_TX_DISABLE;
  83. + if (id->ext.enhopts & SFP_ENHOPTS_SOFT_TX_FAULT &&
  84. + !sfp->gpio[GPIO_TX_FAULT])
  85. + sfp->state_soft_mask |= SFP_F_TX_FAULT;
  86. + if (id->ext.enhopts & SFP_ENHOPTS_SOFT_RX_LOS &&
  87. + !sfp->gpio[GPIO_LOS])
  88. + sfp->state_soft_mask |= SFP_F_LOS;
  89. +
  90. + if (sfp->state_soft_mask & (SFP_F_LOS | SFP_F_TX_FAULT) &&
  91. + !sfp->need_poll)
  92. + mod_delayed_work(system_wq, &sfp->poll, poll_jiffies);
  93. +}
  94. +
  95. +static void sfp_soft_stop_poll(struct sfp *sfp)
  96. +{
  97. + sfp->state_soft_mask = 0;
  98. +}
  99. +
  100. +static unsigned int sfp_get_state(struct sfp *sfp)
  101. +{
  102. + unsigned int state = sfp->get_state(sfp);
  103. +
  104. + if (state & SFP_F_PRESENT &&
  105. + sfp->state_soft_mask & (SFP_F_LOS | SFP_F_TX_FAULT))
  106. + state |= sfp_soft_get_state(sfp);
  107. +
  108. + return state;
  109. +}
  110. +
  111. +static void sfp_set_state(struct sfp *sfp, unsigned int state)
  112. +{
  113. + sfp->set_state(sfp, state);
  114. +
  115. + if (state & SFP_F_PRESENT &&
  116. + sfp->state_soft_mask & SFP_F_TX_DISABLE)
  117. + sfp_soft_set_state(sfp, state);
  118. }
  119. static unsigned int sfp_check(void *buf, size_t len)
  120. @@ -1407,11 +1476,6 @@ static void sfp_sm_fault(struct sfp *sfp
  121. }
  122. }
  123. -static void sfp_sm_mod_init(struct sfp *sfp)
  124. -{
  125. - sfp_module_tx_enable(sfp);
  126. -}
  127. -
  128. static void sfp_sm_probe_for_phy(struct sfp *sfp)
  129. {
  130. /* Setting the serdes link mode is guesswork: there's no
  131. @@ -1574,7 +1638,7 @@ static int sfp_sm_mod_probe(struct sfp *
  132. (int)sizeof(id.ext.datecode), id.ext.datecode);
  133. /* Check whether we support this module */
  134. - if (!sfp->type->module_supported(&sfp->id)) {
  135. + if (!sfp->type->module_supported(&id)) {
  136. dev_err(sfp->dev,
  137. "module is not supported - phys id 0x%02x 0x%02x\n",
  138. sfp->id.base.phys_id, sfp->id.base.phys_ext_id);
  139. @@ -1764,6 +1828,7 @@ static void sfp_sm_main(struct sfp *sfp,
  140. if (sfp->mod_phy)
  141. sfp_sm_phy_detach(sfp);
  142. sfp_module_tx_disable(sfp);
  143. + sfp_soft_stop_poll(sfp);
  144. sfp_sm_next(sfp, SFP_S_DOWN, 0);
  145. return;
  146. }
  147. @@ -1775,7 +1840,10 @@ static void sfp_sm_main(struct sfp *sfp,
  148. sfp->sm_dev_state != SFP_DEV_UP)
  149. break;
  150. - sfp_sm_mod_init(sfp);
  151. + if (!(sfp->id.ext.diagmon & SFP_DIAGMON_ADDRMODE))
  152. + sfp_soft_start_poll(sfp);
  153. +
  154. + sfp_module_tx_enable(sfp);
  155. /* Initialise the fault clearance retries */
  156. sfp->sm_retries = 5;
  157. @@ -2031,7 +2099,10 @@ static void sfp_poll(struct work_struct
  158. struct sfp *sfp = container_of(work, struct sfp, poll.work);
  159. sfp_check_state(sfp);
  160. - mod_delayed_work(system_wq, &sfp->poll, poll_jiffies);
  161. +
  162. + if (sfp->state_soft_mask & (SFP_F_LOS | SFP_F_TX_FAULT) ||
  163. + sfp->need_poll)
  164. + mod_delayed_work(system_wq, &sfp->poll, poll_jiffies);
  165. }
  166. static struct sfp *sfp_alloc(struct device *dev)
  167. @@ -2076,7 +2147,6 @@ static int sfp_probe(struct platform_dev
  168. const struct sff_data *sff;
  169. struct i2c_adapter *i2c;
  170. struct sfp *sfp;
  171. - bool poll = false;
  172. int err, i;
  173. sfp = sfp_alloc(&pdev->dev);
  174. @@ -2184,7 +2254,7 @@ static int sfp_probe(struct platform_dev
  175. sfp->gpio_irq[i] = gpiod_to_irq(sfp->gpio[i]);
  176. if (sfp->gpio_irq[i] < 0) {
  177. sfp->gpio_irq[i] = 0;
  178. - poll = true;
  179. + sfp->need_poll = true;
  180. continue;
  181. }
  182. @@ -2196,11 +2266,11 @@ static int sfp_probe(struct platform_dev
  183. dev_name(sfp->dev), sfp);
  184. if (err) {
  185. sfp->gpio_irq[i] = 0;
  186. - poll = true;
  187. + sfp->need_poll = true;
  188. }
  189. }
  190. - if (poll)
  191. + if (sfp->need_poll)
  192. mod_delayed_work(system_wq, &sfp->poll, poll_jiffies);
  193. /* We could have an issue in cases no Tx disable pin is available or
  194. --- a/include/linux/sfp.h
  195. +++ b/include/linux/sfp.h
  196. @@ -428,6 +428,10 @@ enum {
  197. SFP_TEC_CUR = 0x6c,
  198. SFP_STATUS = 0x6e,
  199. + SFP_STATUS_TX_DISABLE = BIT(7),
  200. + SFP_STATUS_TX_DISABLE_FORCE = BIT(6),
  201. + SFP_STATUS_TX_FAULT = BIT(2),
  202. + SFP_STATUS_RX_LOS = BIT(1),
  203. SFP_ALARM0 = 0x70,
  204. SFP_ALARM0_TEMP_HIGH = BIT(7),
  205. SFP_ALARM0_TEMP_LOW = BIT(6),