aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/backport-5.4/735-v5.5-net-sfp-allow-sfp-to-probe-slow-to-initialise-GPON-m.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/generic/backport-5.4/735-v5.5-net-sfp-allow-sfp-to-probe-slow-to-initialise-GPON-m.patch')
-rw-r--r--target/linux/generic/backport-5.4/735-v5.5-net-sfp-allow-sfp-to-probe-slow-to-initialise-GPON-m.patch110
1 files changed, 110 insertions, 0 deletions
diff --git a/target/linux/generic/backport-5.4/735-v5.5-net-sfp-allow-sfp-to-probe-slow-to-initialise-GPON-m.patch b/target/linux/generic/backport-5.4/735-v5.5-net-sfp-allow-sfp-to-probe-slow-to-initialise-GPON-m.patch
new file mode 100644
index 0000000000..6cbd0864f7
--- /dev/null
+++ b/target/linux/generic/backport-5.4/735-v5.5-net-sfp-allow-sfp-to-probe-slow-to-initialise-GPON-m.patch
@@ -0,0 +1,110 @@
+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
+@@ -165,9 +165,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).
+@@ -202,6 +205,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;
+@@ -1392,7 +1397,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;
+@@ -1402,7 +1407,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;
+ }
+
+@@ -1549,8 +1555,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:
+@@ -1558,10 +1567,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);
+@@ -1596,7 +1614,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;
+ }