openwrt/target/linux/generic/backport-5.4/735-v5.5-net-sfp-allow-sfp-...

111 lines
3.7 KiB
Diff

From fb56cd08880aff8fb030e684fa4311bef712a499 Mon Sep 17 00:00:00 2001
From: Russell King <rmk+kernel@armlinux.org.uk>
Date: Tue, 5 Nov 2019 13:02:30 +0000
Subject: [PATCH 633/660] net: sfp: allow sfp to probe slow to initialise GPON
modules
Some GPON modules (e.g. Huawei MA5671A) take a significant amount of
time to start responding on the I2C bus, contary to the SFF
specifications.
Work around this by implementing a two-level timeout strategy, where
we initially quickly retry for the module, and then use a slower retry
after we exceed a maximum number of quick attempts.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
drivers/net/phy/sfp.c | 38 ++++++++++++++++++++++++++++----------
1 file changed, 28 insertions(+), 10 deletions(-)
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -167,9 +167,12 @@ static const enum gpiod_flags gpio_flags
* The SFF-8472 specifies t_serial ("Time from power on until module is
* ready for data transmission over the two wire serial bus.") as 300ms.
*/
-#define T_SERIAL msecs_to_jiffies(300)
-#define T_HPOWER_LEVEL msecs_to_jiffies(300)
-#define T_PROBE_RETRY msecs_to_jiffies(100)
+#define T_SERIAL msecs_to_jiffies(300)
+#define T_HPOWER_LEVEL msecs_to_jiffies(300)
+#define T_PROBE_RETRY_INIT msecs_to_jiffies(100)
+#define R_PROBE_RETRY_INIT 10
+#define T_PROBE_RETRY_SLOW msecs_to_jiffies(5000)
+#define R_PROBE_RETRY_SLOW 12
/* SFP modules appear to always have their PHY configured for bus address
* 0x56 (which with mdio-i2c, translates to a PHY address of 22).
@@ -204,6 +207,8 @@ struct sfp {
struct delayed_work timeout;
struct mutex sm_mutex; /* Protects state machine */
unsigned char sm_mod_state;
+ unsigned char sm_mod_tries_init;
+ unsigned char sm_mod_tries;
unsigned char sm_dev_state;
unsigned short sm_state;
unsigned int sm_retries;
@@ -1457,7 +1462,7 @@ static int sfp_sm_mod_hpower(struct sfp
return 0;
}
-static int sfp_sm_mod_probe(struct sfp *sfp)
+static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
{
/* SFP module inserted - read I2C data */
struct sfp_eeprom_id id;
@@ -1467,7 +1472,8 @@ static int sfp_sm_mod_probe(struct sfp *
ret = sfp_read(sfp, false, 0, &id, sizeof(id));
if (ret < 0) {
- dev_err(sfp->dev, "failed to read EEPROM: %d\n", ret);
+ if (report)
+ dev_err(sfp->dev, "failed to read EEPROM: %d\n", ret);
return -EAGAIN;
}
@@ -1614,8 +1620,11 @@ static void sfp_sm_module(struct sfp *sf
switch (sfp->sm_mod_state) {
default:
- if (event == SFP_E_INSERT)
+ if (event == SFP_E_INSERT) {
sfp_sm_mod_next(sfp, SFP_MOD_PROBE, T_SERIAL);
+ sfp->sm_mod_tries_init = R_PROBE_RETRY_INIT;
+ sfp->sm_mod_tries = R_PROBE_RETRY_SLOW;
+ }
break;
case SFP_MOD_PROBE:
@@ -1623,10 +1632,19 @@ static void sfp_sm_module(struct sfp *sf
if (event != SFP_E_TIMEOUT)
break;
- err = sfp_sm_mod_probe(sfp);
+ err = sfp_sm_mod_probe(sfp, sfp->sm_mod_tries == 1);
if (err == -EAGAIN) {
- sfp_sm_set_timer(sfp, T_PROBE_RETRY);
- break;
+ if (sfp->sm_mod_tries_init &&
+ --sfp->sm_mod_tries_init) {
+ sfp_sm_set_timer(sfp, T_PROBE_RETRY_INIT);
+ break;
+ } else if (sfp->sm_mod_tries && --sfp->sm_mod_tries) {
+ if (sfp->sm_mod_tries == R_PROBE_RETRY_SLOW - 1)
+ dev_warn(sfp->dev,
+ "please wait, module slow to respond\n");
+ sfp_sm_set_timer(sfp, T_PROBE_RETRY_SLOW);
+ break;
+ }
}
if (err < 0) {
sfp_sm_mod_next(sfp, SFP_MOD_ERROR, 0);
@@ -1661,7 +1679,7 @@ static void sfp_sm_module(struct sfp *sf
sfp_module_remove(sfp->sfp_bus);
sfp_sm_mod_next(sfp, SFP_MOD_ERROR, 0);
} else {
- sfp_sm_set_timer(sfp, T_PROBE_RETRY);
+ sfp_sm_set_timer(sfp, T_PROBE_RETRY_INIT);
}
break;
}