diff options
Diffstat (limited to 'target/linux/generic/pending-5.4/739-net-avoid-tx-fault-with-Nokia-GPON-module.patch')
-rw-r--r-- | target/linux/generic/pending-5.4/739-net-avoid-tx-fault-with-Nokia-GPON-module.patch | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/target/linux/generic/pending-5.4/739-net-avoid-tx-fault-with-Nokia-GPON-module.patch b/target/linux/generic/pending-5.4/739-net-avoid-tx-fault-with-Nokia-GPON-module.patch new file mode 100644 index 0000000000..b540e1dbc1 --- /dev/null +++ b/target/linux/generic/pending-5.4/739-net-avoid-tx-fault-with-Nokia-GPON-module.patch @@ -0,0 +1,108 @@ +From 283b211aa01bdae94dffb3121655dbb20bf237f4 Mon Sep 17 00:00:00 2001 +From: Russell King <rmk+kernel@armlinux.org.uk> +Date: Tue, 3 Dec 2019 15:22:05 +0000 +Subject: net: sfp: avoid tx-fault with Nokia GPON module + +The Nokia GPON module can hold tx-fault active while it is initialising +which can take up to 60s. Avoid this causing the module to be declared +faulty after the SFP MSA defined non-cooled module timeout. + +Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> +--- + drivers/net/phy/sfp.c | 42 ++++++++++++++++++++++++++++++------------ + 1 file changed, 30 insertions(+), 12 deletions(-) + +--- a/drivers/net/phy/sfp.c ++++ b/drivers/net/phy/sfp.c +@@ -153,10 +153,20 @@ static const enum gpiod_flags gpio_flags + GPIOD_ASIS, + }; + +-#define T_WAIT msecs_to_jiffies(50) +-#define T_INIT_JIFFIES msecs_to_jiffies(300) +-#define T_RESET_US 10 +-#define T_FAULT_RECOVER msecs_to_jiffies(1000) ++/* t_start_up (SFF-8431) or t_init (SFF-8472) is the time required for a ++ * non-cooled module to initialise its laser safety circuitry. We wait ++ * an initial T_WAIT period before we check the tx fault to give any PHY ++ * on board (for a copper SFP) time to initialise. ++ */ ++#define T_WAIT msecs_to_jiffies(50) ++#define T_START_UP msecs_to_jiffies(300) ++#define T_START_UP_BAD_GPON msecs_to_jiffies(60000) ++ ++/* t_reset is the time required to assert the TX_DISABLE signal to reset ++ * an indicated TX_FAULT. ++ */ ++#define T_RESET_US 10 ++#define T_FAULT_RECOVER msecs_to_jiffies(1000) + + /* SFP module presence detection is poor: the three MOD DEF signals are + * the same length on the PCB, which means it's possible for MOD DEF 0 to +@@ -216,6 +226,7 @@ struct sfp { + + struct sfp_eeprom_id id; + unsigned int module_power_mW; ++ unsigned int module_t_start_up; + + #if IS_ENABLED(CONFIG_HWMON) + struct sfp_diag diag; +@@ -1590,6 +1601,12 @@ static int sfp_sm_mod_probe(struct sfp * + if (ret < 0) + return ret; + ++ if (!memcmp(id.base.vendor_name, "ALCATELLUCENT ", 16) && ++ !memcmp(id.base.vendor_pn, "3FE46541AA ", 16)) ++ sfp->module_t_start_up = T_START_UP_BAD_GPON; ++ else ++ sfp->module_t_start_up = T_START_UP; ++ + return 0; + } + +@@ -1795,11 +1812,12 @@ static void sfp_sm_main(struct sfp *sfp, + break; + + if (sfp->state & SFP_F_TX_FAULT) { +- /* Wait t_init before indicating that the link is up, +- * provided the current state indicates no TX_FAULT. If +- * TX_FAULT clears before this time, that's fine too. ++ /* Wait up to t_init (SFF-8472) or t_start_up (SFF-8431) ++ * from the TX_DISABLE deassertion for the module to ++ * initialise, which is indicated by TX_FAULT ++ * deasserting. + */ +- timeout = T_INIT_JIFFIES; ++ timeout = sfp->module_t_start_up; + if (timeout > T_WAIT) + timeout -= T_WAIT; + else +@@ -1816,8 +1834,8 @@ static void sfp_sm_main(struct sfp *sfp, + + case SFP_S_INIT: + if (event == SFP_E_TIMEOUT && sfp->state & SFP_F_TX_FAULT) { +- /* TX_FAULT is still asserted after t_init, so assume +- * there is a fault. ++ /* TX_FAULT is still asserted after t_init or ++ * or t_start_up, so assume there is a fault. + */ + sfp_sm_fault(sfp, SFP_S_INIT_TX_FAULT, + sfp->sm_retries == 5); +@@ -1836,7 +1854,7 @@ static void sfp_sm_main(struct sfp *sfp, + case SFP_S_INIT_TX_FAULT: + if (event == SFP_E_TIMEOUT) { + sfp_module_tx_fault_reset(sfp); +- sfp_sm_next(sfp, SFP_S_INIT, T_INIT_JIFFIES); ++ sfp_sm_next(sfp, SFP_S_INIT, sfp->module_t_start_up); + } + break; + +@@ -1860,7 +1878,7 @@ static void sfp_sm_main(struct sfp *sfp, + case SFP_S_TX_FAULT: + if (event == SFP_E_TIMEOUT) { + sfp_module_tx_fault_reset(sfp); +- sfp_sm_next(sfp, SFP_S_REINIT, T_INIT_JIFFIES); ++ sfp_sm_next(sfp, SFP_S_REINIT, sfp->module_t_start_up); + } + break; + |