aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/pending-5.4/739-net-avoid-tx-fault-with-Nokia-GPON-module.patch
diff options
context:
space:
mode:
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.patch108
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;
+