b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | From 283b211aa01bdae94dffb3121655dbb20bf237f4 Mon Sep 17 00:00:00 2001 |
| 2 | From: Russell King <rmk+kernel@armlinux.org.uk> |
| 3 | Date: Tue, 3 Dec 2019 15:22:05 +0000 |
| 4 | Subject: net: sfp: avoid tx-fault with Nokia GPON module |
| 5 | |
| 6 | The Nokia GPON module can hold tx-fault active while it is initialising |
| 7 | which can take up to 60s. Avoid this causing the module to be declared |
| 8 | faulty after the SFP MSA defined non-cooled module timeout. |
| 9 | |
| 10 | Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> |
| 11 | --- |
| 12 | drivers/net/phy/sfp.c | 42 ++++++++++++++++++++++++++++++------------ |
| 13 | 1 file changed, 30 insertions(+), 12 deletions(-) |
| 14 | |
| 15 | --- a/drivers/net/phy/sfp.c |
| 16 | +++ b/drivers/net/phy/sfp.c |
| 17 | @@ -155,10 +155,20 @@ static const enum gpiod_flags gpio_flags |
| 18 | GPIOD_ASIS, |
| 19 | }; |
| 20 | |
| 21 | -#define T_WAIT msecs_to_jiffies(50) |
| 22 | -#define T_INIT_JIFFIES msecs_to_jiffies(300) |
| 23 | -#define T_RESET_US 10 |
| 24 | -#define T_FAULT_RECOVER msecs_to_jiffies(1000) |
| 25 | +/* t_start_up (SFF-8431) or t_init (SFF-8472) is the time required for a |
| 26 | + * non-cooled module to initialise its laser safety circuitry. We wait |
| 27 | + * an initial T_WAIT period before we check the tx fault to give any PHY |
| 28 | + * on board (for a copper SFP) time to initialise. |
| 29 | + */ |
| 30 | +#define T_WAIT msecs_to_jiffies(50) |
| 31 | +#define T_START_UP msecs_to_jiffies(300) |
| 32 | +#define T_START_UP_BAD_GPON msecs_to_jiffies(60000) |
| 33 | + |
| 34 | +/* t_reset is the time required to assert the TX_DISABLE signal to reset |
| 35 | + * an indicated TX_FAULT. |
| 36 | + */ |
| 37 | +#define T_RESET_US 10 |
| 38 | +#define T_FAULT_RECOVER msecs_to_jiffies(1000) |
| 39 | |
| 40 | /* SFP module presence detection is poor: the three MOD DEF signals are |
| 41 | * the same length on the PCB, which means it's possible for MOD DEF 0 to |
| 42 | @@ -219,6 +229,7 @@ struct sfp { |
| 43 | |
| 44 | struct sfp_eeprom_id id; |
| 45 | unsigned int module_power_mW; |
| 46 | + unsigned int module_t_start_up; |
| 47 | |
| 48 | #if IS_ENABLED(CONFIG_HWMON) |
| 49 | struct sfp_diag diag; |
| 50 | @@ -1750,6 +1761,12 @@ static int sfp_sm_mod_probe(struct sfp * |
| 51 | if (ret < 0) |
| 52 | return ret; |
| 53 | |
| 54 | + if (!memcmp(id.base.vendor_name, "ALCATELLUCENT ", 16) && |
| 55 | + !memcmp(id.base.vendor_pn, "3FE46541AA ", 16)) |
| 56 | + sfp->module_t_start_up = T_START_UP_BAD_GPON; |
| 57 | + else |
| 58 | + sfp->module_t_start_up = T_START_UP; |
| 59 | + |
| 60 | return 0; |
| 61 | } |
| 62 | |
| 63 | @@ -1955,11 +1972,12 @@ static void sfp_sm_main(struct sfp *sfp, |
| 64 | break; |
| 65 | |
| 66 | if (sfp->state & SFP_F_TX_FAULT) { |
| 67 | - /* Wait t_init before indicating that the link is up, |
| 68 | - * provided the current state indicates no TX_FAULT. If |
| 69 | - * TX_FAULT clears before this time, that's fine too. |
| 70 | + /* Wait up to t_init (SFF-8472) or t_start_up (SFF-8431) |
| 71 | + * from the TX_DISABLE deassertion for the module to |
| 72 | + * initialise, which is indicated by TX_FAULT |
| 73 | + * deasserting. |
| 74 | */ |
| 75 | - timeout = T_INIT_JIFFIES; |
| 76 | + timeout = sfp->module_t_start_up; |
| 77 | if (timeout > T_WAIT) |
| 78 | timeout -= T_WAIT; |
| 79 | else |
| 80 | @@ -1976,8 +1994,8 @@ static void sfp_sm_main(struct sfp *sfp, |
| 81 | |
| 82 | case SFP_S_INIT: |
| 83 | if (event == SFP_E_TIMEOUT && sfp->state & SFP_F_TX_FAULT) { |
| 84 | - /* TX_FAULT is still asserted after t_init, so assume |
| 85 | - * there is a fault. |
| 86 | + /* TX_FAULT is still asserted after t_init or |
| 87 | + * or t_start_up, so assume there is a fault. |
| 88 | */ |
| 89 | sfp_sm_fault(sfp, SFP_S_INIT_TX_FAULT, |
| 90 | sfp->sm_retries == 5); |
| 91 | @@ -1996,7 +2014,7 @@ static void sfp_sm_main(struct sfp *sfp, |
| 92 | case SFP_S_INIT_TX_FAULT: |
| 93 | if (event == SFP_E_TIMEOUT) { |
| 94 | sfp_module_tx_fault_reset(sfp); |
| 95 | - sfp_sm_next(sfp, SFP_S_INIT, T_INIT_JIFFIES); |
| 96 | + sfp_sm_next(sfp, SFP_S_INIT, sfp->module_t_start_up); |
| 97 | } |
| 98 | break; |
| 99 | |
| 100 | @@ -2020,7 +2038,7 @@ static void sfp_sm_main(struct sfp *sfp, |
| 101 | case SFP_S_TX_FAULT: |
| 102 | if (event == SFP_E_TIMEOUT) { |
| 103 | sfp_module_tx_fault_reset(sfp); |
| 104 | - sfp_sm_next(sfp, SFP_S_REINIT, T_INIT_JIFFIES); |
| 105 | + sfp_sm_next(sfp, SFP_S_REINIT, sfp->module_t_start_up); |
| 106 | } |
| 107 | break; |
| 108 | |