kernel: add backported phy/phylink/sfp patches
[openwrt/staging/jogo.git] / target / linux / generic / backport-4.19 / 723-v5.5-net-sfp-handle-module-remove-outside-state-machine.patch
diff --git a/target/linux/generic/backport-4.19/723-v5.5-net-sfp-handle-module-remove-outside-state-machine.patch b/target/linux/generic/backport-4.19/723-v5.5-net-sfp-handle-module-remove-outside-state-machine.patch
new file mode 100644 (file)
index 0000000..542aeae
--- /dev/null
@@ -0,0 +1,53 @@
+From d2591ea5520e2ee8fa557f96bb64c23cafac4b20 Mon Sep 17 00:00:00 2001
+From: Russell King <rmk+kernel@armlinux.org.uk>
+Date: Tue, 15 Oct 2019 10:33:13 +0100
+Subject: [PATCH 621/660] net: sfp: handle module remove outside state machine
+
+Removing a module resets the module state machine back to its initial
+state.  Rather than explicitly handling this in every state, handle it
+early on outside of the state machine.
+
+Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
+---
+ drivers/net/phy/sfp.c | 16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+--- a/drivers/net/phy/sfp.c
++++ b/drivers/net/phy/sfp.c
+@@ -1500,6 +1500,14 @@ static void sfp_sm_device(struct sfp *sf
+  */
+ static void sfp_sm_module(struct sfp *sfp, unsigned int event)
+ {
++      /* Handle remove event globally, it resets this state machine */
++      if (event == SFP_E_REMOVE) {
++              if (sfp->sm_mod_state > SFP_MOD_PROBE)
++                      sfp_sm_mod_remove(sfp);
++              sfp_sm_mod_next(sfp, SFP_MOD_EMPTY, 0);
++              return;
++      }
++
+       switch (sfp->sm_mod_state) {
+       default:
+               if (event == SFP_E_INSERT && sfp->attached) {
+@@ -1509,9 +1517,7 @@ static void sfp_sm_module(struct sfp *sf
+               break;
+       case SFP_MOD_PROBE:
+-              if (event == SFP_E_REMOVE) {
+-                      sfp_sm_mod_next(sfp, SFP_MOD_EMPTY, 0);
+-              } else if (event == SFP_E_TIMEOUT) {
++              if (event == SFP_E_TIMEOUT) {
+                       int val = sfp_sm_mod_probe(sfp);
+                       if (val == 0)
+@@ -1533,10 +1539,6 @@ static void sfp_sm_module(struct sfp *sf
+               /* fallthrough */
+       case SFP_MOD_PRESENT:
+       case SFP_MOD_ERROR:
+-              if (event == SFP_E_REMOVE) {
+-                      sfp_sm_mod_remove(sfp);
+-                      sfp_sm_mod_next(sfp, SFP_MOD_EMPTY, 0);
+-              }
+               break;
+       }
+ }