Commit 26c97a2d authored by Russell King's avatar Russell King Committed by David S. Miller

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: default avatarRussell King <rmk+kernel@armlinux.org.uk>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e70ac628
...@@ -155,10 +155,20 @@ static const enum gpiod_flags gpio_flags[] = { ...@@ -155,10 +155,20 @@ static const enum gpiod_flags gpio_flags[] = {
GPIOD_ASIS, GPIOD_ASIS,
}; };
#define T_WAIT msecs_to_jiffies(50) /* t_start_up (SFF-8431) or t_init (SFF-8472) is the time required for a
#define T_INIT_JIFFIES msecs_to_jiffies(300) * non-cooled module to initialise its laser safety circuitry. We wait
#define T_RESET_US 10 * an initial T_WAIT period before we check the tx fault to give any PHY
#define T_FAULT_RECOVER msecs_to_jiffies(1000) * 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 /* 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 * the same length on the PCB, which means it's possible for MOD DEF 0 to
...@@ -218,6 +228,7 @@ struct sfp { ...@@ -218,6 +228,7 @@ struct sfp {
struct sfp_eeprom_id id; struct sfp_eeprom_id id;
unsigned int module_power_mW; unsigned int module_power_mW;
unsigned int module_t_start_up;
#if IS_ENABLED(CONFIG_HWMON) #if IS_ENABLED(CONFIG_HWMON)
struct sfp_diag diag; struct sfp_diag diag;
...@@ -1655,6 +1666,12 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report) ...@@ -1655,6 +1666,12 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
if (ret < 0) if (ret < 0)
return ret; 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; return 0;
} }
...@@ -1855,11 +1872,12 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event) ...@@ -1855,11 +1872,12 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
break; break;
if (sfp->state & SFP_F_TX_FAULT) { if (sfp->state & SFP_F_TX_FAULT) {
/* Wait t_init before indicating that the link is up, /* Wait up to t_init (SFF-8472) or t_start_up (SFF-8431)
* provided the current state indicates no TX_FAULT. If * from the TX_DISABLE deassertion for the module to
* TX_FAULT clears before this time, that's fine too. * initialise, which is indicated by TX_FAULT
* deasserting.
*/ */
timeout = T_INIT_JIFFIES; timeout = sfp->module_t_start_up;
if (timeout > T_WAIT) if (timeout > T_WAIT)
timeout -= T_WAIT; timeout -= T_WAIT;
else else
...@@ -1876,8 +1894,8 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event) ...@@ -1876,8 +1894,8 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
case SFP_S_INIT: case SFP_S_INIT:
if (event == SFP_E_TIMEOUT && sfp->state & SFP_F_TX_FAULT) { if (event == SFP_E_TIMEOUT && sfp->state & SFP_F_TX_FAULT) {
/* TX_FAULT is still asserted after t_init, so assume /* TX_FAULT is still asserted after t_init or
* there is a fault. * or t_start_up, so assume there is a fault.
*/ */
sfp_sm_fault(sfp, SFP_S_INIT_TX_FAULT, sfp_sm_fault(sfp, SFP_S_INIT_TX_FAULT,
sfp->sm_retries == 5); sfp->sm_retries == 5);
...@@ -1896,7 +1914,7 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event) ...@@ -1896,7 +1914,7 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
case SFP_S_INIT_TX_FAULT: case SFP_S_INIT_TX_FAULT:
if (event == SFP_E_TIMEOUT) { if (event == SFP_E_TIMEOUT) {
sfp_module_tx_fault_reset(sfp); 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; break;
...@@ -1920,7 +1938,7 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event) ...@@ -1920,7 +1938,7 @@ static void sfp_sm_main(struct sfp *sfp, unsigned int event)
case SFP_S_TX_FAULT: case SFP_S_TX_FAULT:
if (event == SFP_E_TIMEOUT) { if (event == SFP_E_TIMEOUT) {
sfp_module_tx_fault_reset(sfp); 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; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment