mvebu: SFP backports for GPON modules
authorMarek Behún <marek.behun@nic.cz>
Sat, 8 Jan 2022 18:56:02 +0000 (19:56 +0100)
committerChristian Lamparter <chunkeey@gmail.com>
Sat, 26 Mar 2022 20:26:07 +0000 (21:26 +0100)
This backports the following upstream Linux patches
  net: sfp: add mode quirk for GPON module Ubiquiti U-Fiber Instant
  net: sfp: relax bitrate-derived mode check
  net: sfp: cope with SFPs that set both LOS normal and LOS inverted
for 5.4 for mvebu platform.

This fixes GPON modules:
  Ubiquiti U-Fiber Instant SFP GPON
  VSOL V2801F
  CarlitoxxPro CPGOS03-0490 v2.0

Signed-off-by: Marek Behún <marek.behun@nic.cz>
15 files changed:
target/linux/generic/backport-5.4/768-net-sfp-cope-with-SFPs-that-set-both-LOS-normal-and-.patch [new file with mode: 0644]
target/linux/generic/backport-5.4/852-v5.10-0001-net-sfp-VSOL-V2801F-CarlitoxxPro-CPGOS03-0490-v2.0-w.patch
target/linux/generic/backport-5.4/852-v5.10-0002-net-sfp-add-workaround-for-Realtek-RTL8672-and-RTL96.patch
target/linux/generic/pending-5.4/739-net-avoid-tx-fault-with-Nokia-GPON-module.patch
target/linux/generic/pending-5.4/740-net-sfp-remove-incomplete-100BASE-FX-and-100BASE-LX-.patch
target/linux/generic/pending-5.4/743-net-sfp-add-module-start-stop-upstream-notifications.patch
target/linux/generic/pending-5.4/753-net-sfp-add-support-for-Clause-45-PHYs.patch
target/linux/generic/pending-5.4/754-net-sfp-fix-unbind.patch
target/linux/generic/pending-5.4/755-net-sfp-fix-hwmon.patch
target/linux/generic/pending-5.4/756-net-sfp-use-a-definition-for-the-fault-recovery-atte.patch
target/linux/generic/pending-5.4/757-net-sfp-rename-sm_retries.patch
target/linux/generic/pending-5.4/758-net-sfp-error-handling-for-phy-probe.patch
target/linux/generic/pending-5.4/759-net-sfp-re-attempt-probing-for-phy.patch
target/linux/generic/pending-5.4/771-net-sfp-add-mode-quirk-Ubiquiti-UFiber-Instant.patch [new file with mode: 0644]
target/linux/generic/pending-5.4/772-net-sfp-relax-bitrate-devided-check.patch [new file with mode: 0644]

diff --git a/target/linux/generic/backport-5.4/768-net-sfp-cope-with-SFPs-that-set-both-LOS-normal-and-.patch b/target/linux/generic/backport-5.4/768-net-sfp-cope-with-SFPs-that-set-both-LOS-normal-and-.patch
new file mode 100644 (file)
index 0000000..fbbaae1
--- /dev/null
@@ -0,0 +1,94 @@
+From da5bc1832b325b15e4cca3b63861ecf48be870ef Mon Sep 17 00:00:00 2001
+From: Russell King <rmk+kernel@armlinux.org.uk>
+Date: Sun, 10 Jan 2021 10:58:32 +0000
+Subject: [PATCH] net: sfp: cope with SFPs that set both LOS normal and LOS
+ inverted
+
+The SFP MSA defines two option bits in byte 65 to indicate how the
+Rx_LOS signal on SFP pin 8 behaves:
+
+bit 2 - Loss of Signal implemented, signal inverted from standard
+        definition in SFP MSA (often called "Signal Detect").
+bit 1 - Loss of Signal implemented, signal as defined in SFP MSA
+        (often called "Rx_LOS").
+
+Clearly, setting both bits results in a meaningless situation: it would
+mean that LOS is implemented in both the normal sense (1 = signal loss)
+and inverted sense (0 = signal loss).
+
+Unfortunately, there are modules out there which set both bits, which
+will be initially interpret as "inverted" sense, and then, if the LOS
+signal changes state, we will toggle between LINK_UP and WAIT_LOS
+states.
+
+Change our LOS handling to give well defined behaviour: only interpret
+these bits as meaningful if exactly one is set, otherwise treat it as
+if LOS is not implemented.
+
+Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://lore.kernel.org/r/E1kyYQa-0004iR-CU@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/sfp.c | 36 ++++++++++++++++++++++--------------
+ 1 file changed, 22 insertions(+), 14 deletions(-)
+
+--- a/drivers/net/phy/sfp.c
++++ b/drivers/net/phy/sfp.c
+@@ -1430,15 +1430,19 @@ static void sfp_sm_link_down(struct sfp
+ static void sfp_sm_link_check_los(struct sfp *sfp)
+ {
+-      unsigned int los = sfp->state & SFP_F_LOS;
++      const __be16 los_inverted = cpu_to_be16(SFP_OPTIONS_LOS_INVERTED);
++      const __be16 los_normal = cpu_to_be16(SFP_OPTIONS_LOS_NORMAL);
++      __be16 los_options = sfp->id.ext.options & (los_inverted | los_normal);
++      bool los = false;
+       /* If neither SFP_OPTIONS_LOS_INVERTED nor SFP_OPTIONS_LOS_NORMAL
+-       * are set, we assume that no LOS signal is available.
++       * are set, we assume that no LOS signal is available. If both are
++       * set, we assume LOS is not implemented (and is meaningless.)
+        */
+-      if (sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_LOS_INVERTED))
+-              los ^= SFP_F_LOS;
+-      else if (!(sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_LOS_NORMAL)))
+-              los = 0;
++      if (los_options == los_inverted)
++              los = !(sfp->state & SFP_F_LOS);
++      else if (los_options == los_normal)
++              los = !!(sfp->state & SFP_F_LOS);
+       if (los)
+               sfp_sm_next(sfp, SFP_S_WAIT_LOS, 0);
+@@ -1448,18 +1452,22 @@ static void sfp_sm_link_check_los(struct
+ static bool sfp_los_event_active(struct sfp *sfp, unsigned int event)
+ {
+-      return (sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_LOS_INVERTED) &&
+-              event == SFP_E_LOS_LOW) ||
+-             (sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_LOS_NORMAL) &&
+-              event == SFP_E_LOS_HIGH);
++      const __be16 los_inverted = cpu_to_be16(SFP_OPTIONS_LOS_INVERTED);
++      const __be16 los_normal = cpu_to_be16(SFP_OPTIONS_LOS_NORMAL);
++      __be16 los_options = sfp->id.ext.options & (los_inverted | los_normal);
++
++      return (los_options == los_inverted && event == SFP_E_LOS_LOW) ||
++             (los_options == los_normal && event == SFP_E_LOS_HIGH);
+ }
+ static bool sfp_los_event_inactive(struct sfp *sfp, unsigned int event)
+ {
+-      return (sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_LOS_INVERTED) &&
+-              event == SFP_E_LOS_HIGH) ||
+-             (sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_LOS_NORMAL) &&
+-              event == SFP_E_LOS_LOW);
++      const __be16 los_inverted = cpu_to_be16(SFP_OPTIONS_LOS_INVERTED);
++      const __be16 los_normal = cpu_to_be16(SFP_OPTIONS_LOS_NORMAL);
++      __be16 los_options = sfp->id.ext.options & (los_inverted | los_normal);
++
++      return (los_options == los_inverted && event == SFP_E_LOS_HIGH) ||
++             (los_options == los_normal && event == SFP_E_LOS_LOW);
+ }
+ static void sfp_sm_fault(struct sfp *sfp, unsigned int next_state, bool warn)
index 1901054a100df0a59b97da4e9f04d53711962c1c..39f4b273aee639702737bdfcc6c88b2cb9258d21 100644 (file)
@@ -68,7 +68,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
  
                msgs[1].len = this_len;
  
-@@ -1569,6 +1579,28 @@ static int sfp_sm_mod_hpower(struct sfp
+@@ -1577,6 +1587,28 @@ static int sfp_sm_mod_hpower(struct sfp
        return 0;
  }
  
@@ -97,7 +97,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
  static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
  {
        /* SFP module inserted - read I2C data */
-@@ -1577,14 +1609,20 @@ static int sfp_sm_mod_probe(struct sfp *
+@@ -1585,14 +1617,20 @@ static int sfp_sm_mod_probe(struct sfp *
        u8 check;
        int ret;
  
@@ -120,7 +120,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
                dev_err(sfp->dev, "EEPROM short read: %d\n", ret);
                return -EAGAIN;
        }
-@@ -1612,6 +1650,21 @@ static int sfp_sm_mod_probe(struct sfp *
+@@ -1620,6 +1658,21 @@ static int sfp_sm_mod_probe(struct sfp *
                }
        }
  
index 27ae97cee74a20fc099cb0a4fe3324becc25dbba..8c9528428006be052f221f1bf43b7004ec94ab6b 100644 (file)
@@ -102,7 +102,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
        err = sfp_read(sfp, true, 0, &sfp->diag, sizeof(sfp->diag));
        if (err < 0) {
                if (sfp->hwmon_tries--) {
-@@ -1579,26 +1585,30 @@ static int sfp_sm_mod_hpower(struct sfp
+@@ -1587,26 +1593,30 @@ static int sfp_sm_mod_hpower(struct sfp
        return 0;
  }
  
@@ -149,7 +149,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  }
  
  static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
-@@ -1609,11 +1619,11 @@ static int sfp_sm_mod_probe(struct sfp *
+@@ -1617,11 +1627,11 @@ static int sfp_sm_mod_probe(struct sfp *
        u8 check;
        int ret;
  
@@ -165,7 +165,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  
        ret = sfp_read(sfp, false, 0, &id.base, sizeof(id.base));
        if (ret < 0) {
-@@ -1627,6 +1637,33 @@ static int sfp_sm_mod_probe(struct sfp *
+@@ -1635,6 +1645,33 @@ static int sfp_sm_mod_probe(struct sfp *
                return -EAGAIN;
        }
  
@@ -199,7 +199,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
        /* Cotsworks do not seem to update the checksums when they
         * do the final programming with the final module part number,
         * serial number and date code.
-@@ -1650,9 +1687,6 @@ static int sfp_sm_mod_probe(struct sfp *
+@@ -1658,9 +1695,6 @@ static int sfp_sm_mod_probe(struct sfp *
                }
        }
  
index 6648d10c81deda7c8a8491e95610ec3a9c712cc2..4c5f99acc54c2782b1c8b9be01090827c31499ca 100644 (file)
@@ -47,7 +47,7 @@ Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
  
  #if IS_ENABLED(CONFIG_HWMON)
        struct sfp_diag diag;
-@@ -1742,6 +1753,12 @@ static int sfp_sm_mod_probe(struct sfp *
+@@ -1750,6 +1761,12 @@ static int sfp_sm_mod_probe(struct sfp *
        if (ret < 0)
                return ret;
  
@@ -60,7 +60,7 @@ Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
        return 0;
  }
  
-@@ -1947,11 +1964,12 @@ static void sfp_sm_main(struct sfp *sfp,
+@@ -1955,11 +1972,12 @@ static void sfp_sm_main(struct sfp *sfp,
                        break;
  
                if (sfp->state & SFP_F_TX_FAULT) {
@@ -77,7 +77,7 @@ Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
                        if (timeout > T_WAIT)
                                timeout -= T_WAIT;
                        else
-@@ -1968,8 +1986,8 @@ static void sfp_sm_main(struct sfp *sfp,
+@@ -1976,8 +1994,8 @@ static void sfp_sm_main(struct sfp *sfp,
  
        case SFP_S_INIT:
                if (event == SFP_E_TIMEOUT && sfp->state & SFP_F_TX_FAULT) {
@@ -88,7 +88,7 @@ Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
                         */
                        sfp_sm_fault(sfp, SFP_S_INIT_TX_FAULT,
                                     sfp->sm_retries == 5);
-@@ -1988,7 +2006,7 @@ static void sfp_sm_main(struct sfp *sfp,
+@@ -1996,7 +2014,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);
@@ -97,7 +97,7 @@ Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
                }
                break;
  
-@@ -2012,7 +2030,7 @@ static void sfp_sm_main(struct sfp *sfp,
+@@ -2020,7 +2038,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);
index 1abc34e94b7ea34e8d4c81a202431c1e4c2c1828..e439d19517639ed1c84a86c1d86d529756a50e8c 100644 (file)
@@ -30,7 +30,7 @@ Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
        if (phylink_test(link_modes, 1000baseX_Full))
 --- a/drivers/net/phy/sfp.c
 +++ b/drivers/net/phy/sfp.c
-@@ -1505,18 +1505,7 @@ static void sfp_sm_fault(struct sfp *sfp
+@@ -1513,18 +1513,7 @@ static void sfp_sm_fault(struct sfp *sfp
  
  static void sfp_sm_probe_for_phy(struct sfp *sfp)
  {
index ba1b5b582205bdffcd8d36bb36c202148fd64db8..50200135ddae599a03945a8f61cf95ce707b348e 100644 (file)
@@ -78,7 +78,7 @@ Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
        [SFP_S_WAIT] = "wait",
        [SFP_S_INIT] = "init",
        [SFP_S_INIT_TX_FAULT] = "init_tx_fault",
-@@ -1918,6 +1920,8 @@ static void sfp_sm_main(struct sfp *sfp,
+@@ -1926,6 +1928,8 @@ static void sfp_sm_main(struct sfp *sfp,
                if (sfp->sm_state == SFP_S_LINK_UP &&
                    sfp->sm_dev_state == SFP_DEV_UP)
                        sfp_sm_link_down(sfp);
@@ -87,7 +87,7 @@ Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
                if (sfp->mod_phy)
                        sfp_sm_phy_detach(sfp);
                sfp_module_tx_disable(sfp);
-@@ -1985,6 +1989,10 @@ static void sfp_sm_main(struct sfp *sfp,
+@@ -1993,6 +1997,10 @@ static void sfp_sm_main(struct sfp *sfp,
                         * clear.  Probe for the PHY and check the LOS state.
                         */
                        sfp_sm_probe_for_phy(sfp);
index dcd1ba7ef3f8a76fbbcf2861503ac79a75a56031..f7c4bc11053f5f027b8e3b9a95944fe26c2c0284 100644 (file)
@@ -43,7 +43,7 @@ Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
        err = sfp_add_phy(sfp->sfp_bus, phy);
        if (err) {
                phy_device_remove(phy);
-@@ -1503,10 +1510,32 @@ static void sfp_sm_fault(struct sfp *sfp
+@@ -1511,10 +1518,32 @@ static void sfp_sm_fault(struct sfp *sfp
        }
  }
  
@@ -78,7 +78,7 @@ Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
  }
  
  static int sfp_module_parse_power(struct sfp *sfp)
-@@ -1566,6 +1595,13 @@ static int sfp_sm_mod_hpower(struct sfp
+@@ -1574,6 +1603,13 @@ static int sfp_sm_mod_hpower(struct sfp
                return -EAGAIN;
        }
  
index c31922e021b95157694c586b54d16232ff6e9e75..6872973385659a1316b96e6fa0080db3dab2e70a 100644 (file)
@@ -15,7 +15,7 @@ Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
 
 --- a/drivers/net/phy/sfp.c
 +++ b/drivers/net/phy/sfp.c
-@@ -2431,6 +2431,10 @@ static int sfp_remove(struct platform_de
+@@ -2439,6 +2439,10 @@ static int sfp_remove(struct platform_de
  
        sfp_unregister_socket(sfp->sfp_bus);
  
index a18e4801a25f1a628d54761b04b71baaa04e0186..be3b19b0ec358462ad6fed42eedea7c3680110a2 100644 (file)
@@ -15,7 +15,7 @@ Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
 
 --- a/drivers/net/phy/sfp.c
 +++ b/drivers/net/phy/sfp.c
-@@ -1883,6 +1883,10 @@ static void sfp_sm_module(struct sfp *sf
+@@ -1891,6 +1891,10 @@ static void sfp_sm_module(struct sfp *sf
                        break;
                }
  
@@ -26,7 +26,7 @@ Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
                sfp_sm_mod_next(sfp, SFP_MOD_WAITDEV, 0);
                /* fall through */
        case SFP_MOD_WAITDEV:
-@@ -1932,15 +1936,6 @@ static void sfp_sm_module(struct sfp *sf
+@@ -1940,15 +1944,6 @@ static void sfp_sm_module(struct sfp *sf
        case SFP_MOD_ERROR:
                break;
        }
index ba4f8c40c490c2292ae4c874a7bd58737e15a3f6..c8e3cf5e4f87f4a61e2640b23fe6fada3718f6b8 100644 (file)
@@ -26,7 +26,7 @@ Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
  /* 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
   * connect before the I2C bus on MOD DEF 1/2.
-@@ -1972,7 +1980,7 @@ static void sfp_sm_main(struct sfp *sfp,
+@@ -1980,7 +1988,7 @@ static void sfp_sm_main(struct sfp *sfp,
                sfp_module_tx_enable(sfp);
  
                /* Initialise the fault clearance retries */
@@ -35,7 +35,7 @@ Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
  
                /* We need to check the TX_FAULT state, which is not defined
                 * while TX_DISABLE is asserted. The earliest we want to do
-@@ -2012,7 +2020,7 @@ static void sfp_sm_main(struct sfp *sfp,
+@@ -2020,7 +2028,7 @@ static void sfp_sm_main(struct sfp *sfp,
                         * or t_start_up, so assume there is a fault.
                         */
                        sfp_sm_fault(sfp, SFP_S_INIT_TX_FAULT,
@@ -44,7 +44,7 @@ Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
                } else if (event == SFP_E_TIMEOUT || event == SFP_E_TX_CLEAR) {
        init_done:      /* TX_FAULT deasserted or we timed out with TX_FAULT
                         * clear.  Probe for the PHY and check the LOS state.
-@@ -2025,7 +2033,7 @@ static void sfp_sm_main(struct sfp *sfp,
+@@ -2033,7 +2041,7 @@ static void sfp_sm_main(struct sfp *sfp,
                        sfp_sm_link_check_los(sfp);
  
                        /* Reset the fault retry count */
index 13f3b6ccff5fcc7f54ff2f545d5b80fd167e903d..a8d3f324438abc47a0af97783b248b51f443f2a2 100644 (file)
@@ -22,7 +22,7 @@ Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
  
        struct sfp_eeprom_id id;
        unsigned int module_power_mW;
-@@ -1506,7 +1506,7 @@ static bool sfp_los_event_inactive(struc
+@@ -1514,7 +1514,7 @@ static bool sfp_los_event_inactive(struc
  
  static void sfp_sm_fault(struct sfp *sfp, unsigned int next_state, bool warn)
  {
@@ -31,7 +31,7 @@ Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
                dev_err(sfp->dev,
                        "module persistently indicates fault, disabling\n");
                sfp_sm_next(sfp, SFP_S_TX_DISABLE, 0);
-@@ -1980,7 +1980,7 @@ static void sfp_sm_main(struct sfp *sfp,
+@@ -1988,7 +1988,7 @@ static void sfp_sm_main(struct sfp *sfp,
                sfp_module_tx_enable(sfp);
  
                /* Initialise the fault clearance retries */
@@ -40,7 +40,7 @@ Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
  
                /* We need to check the TX_FAULT state, which is not defined
                 * while TX_DISABLE is asserted. The earliest we want to do
-@@ -2020,7 +2020,7 @@ static void sfp_sm_main(struct sfp *sfp,
+@@ -2028,7 +2028,7 @@ static void sfp_sm_main(struct sfp *sfp,
                         * or t_start_up, so assume there is a fault.
                         */
                        sfp_sm_fault(sfp, SFP_S_INIT_TX_FAULT,
@@ -49,7 +49,7 @@ Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
                } else if (event == SFP_E_TIMEOUT || event == SFP_E_TX_CLEAR) {
        init_done:      /* TX_FAULT deasserted or we timed out with TX_FAULT
                         * clear.  Probe for the PHY and check the LOS state.
-@@ -2033,7 +2033,7 @@ static void sfp_sm_main(struct sfp *sfp,
+@@ -2041,7 +2041,7 @@ static void sfp_sm_main(struct sfp *sfp,
                        sfp_sm_link_check_los(sfp);
  
                        /* Reset the fault retry count */
index dfa772dc72141a9635121ac305764cc985c4e9c6..5964ed5c5fe47eae18cf42a6a868e877808eeb34 100644 (file)
@@ -55,7 +55,7 @@ Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
  }
  
  static void sfp_sm_link_up(struct sfp *sfp)
-@@ -1529,21 +1531,24 @@ static void sfp_sm_fault(struct sfp *sfp
+@@ -1537,21 +1539,24 @@ static void sfp_sm_fault(struct sfp *sfp
   * Clause 45 copper SFP+ modules (10G) appear to switch their interface
   * mode according to the negotiated line speed.
   */
@@ -83,7 +83,7 @@ Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
  }
  
  static int sfp_module_parse_power(struct sfp *sfp)
-@@ -2025,7 +2030,10 @@ static void sfp_sm_main(struct sfp *sfp,
+@@ -2033,7 +2038,10 @@ static void sfp_sm_main(struct sfp *sfp,
        init_done:      /* TX_FAULT deasserted or we timed out with TX_FAULT
                         * clear.  Probe for the PHY and check the LOS state.
                         */
index aebb6b03989265e834820707e184b786d517ddd8..27e218739869db806066c3e988e10f2050cc72cc 100644 (file)
@@ -69,7 +69,7 @@ Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
        if (IS_ERR(phy)) {
                dev_err(sfp->dev, "mdiobus scan returned %ld\n", PTR_ERR(phy));
                return PTR_ERR(phy);
-@@ -1954,6 +1961,7 @@ static void sfp_sm_module(struct sfp *sf
+@@ -1962,6 +1969,7 @@ static void sfp_sm_module(struct sfp *sf
  static void sfp_sm_main(struct sfp *sfp, unsigned int event)
  {
        unsigned long timeout;
@@ -77,7 +77,7 @@ Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
  
        /* Some events are global */
        if (sfp->sm_state != SFP_S_DOWN &&
-@@ -2027,22 +2035,39 @@ static void sfp_sm_main(struct sfp *sfp,
+@@ -2035,22 +2043,39 @@ static void sfp_sm_main(struct sfp *sfp,
                        sfp_sm_fault(sfp, SFP_S_INIT_TX_FAULT,
                                     sfp->sm_fault_retries == N_FAULT_INIT);
                } else if (event == SFP_E_TIMEOUT || event == SFP_E_TX_CLEAR) {
diff --git a/target/linux/generic/pending-5.4/771-net-sfp-add-mode-quirk-Ubiquiti-UFiber-Instant.patch b/target/linux/generic/pending-5.4/771-net-sfp-add-mode-quirk-Ubiquiti-UFiber-Instant.patch
new file mode 100644 (file)
index 0000000..e48b474
--- /dev/null
@@ -0,0 +1,93 @@
+From f0b4f847673299577c29b71d3f3acd3c313d81b7 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Mon, 25 Jan 2021 16:02:28 +0100
+Subject: net: sfp: add mode quirk for GPON module Ubiquiti U-Fiber Instant
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The Ubiquiti U-Fiber Instant SFP GPON module has nonsensical information
+stored in its EEPROM. It claims to support all transceiver types including
+10G Ethernet. Clear all claimed modes and set only 1000baseX_Full, which is
+the only one supported.
+
+This module has also phys_id set to SFF, and the SFP subsystem currently
+does not allow to use SFP modules detected as SFFs. Add exception for this
+module so it can be detected as supported.
+
+This change finally allows to detect and use SFP GPON module Ubiquiti
+U-Fiber Instant on Linux system.
+
+EEPROM content of this SFP module is (where XX is serial number):
+
+00: 02 04 0b ff ff ff ff ff ff ff ff 03 0c 00 14 c8    ???........??.??
+10: 00 00 00 00 55 42 4e 54 20 20 20 20 20 20 20 20    ....UBNT
+20: 20 20 20 20 00 18 e8 29 55 46 2d 49 4e 53 54 41        .??)UF-INSTA
+30: 4e 54 20 20 20 20 20 20 34 20 20 20 05 1e 00 36    NT      4   ??.6
+40: 00 06 00 00 55 42 4e 54 XX XX XX XX XX XX XX XX    .?..UBNTXXXXXXXX
+50: 20 20 20 20 31 34 30 31 32 33 20 20 60 80 02 41        140123  `??A
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/phy/sfp-bus.c | 15 +++++++++++++++
+ drivers/net/phy/sfp.c     | 17 +++++++++++++++--
+ 2 files changed, 30 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/phy/sfp-bus.c
++++ b/drivers/net/phy/sfp-bus.c
+@@ -44,6 +44,17 @@ static void sfp_quirk_2500basex(const st
+       phylink_set(modes, 2500baseX_Full);
+ }
++static void sfp_quirk_ubnt_uf_instant(const struct sfp_eeprom_id *id,
++                                    unsigned long *modes)
++{
++      /* Ubiquiti U-Fiber Instant module claims that support all transceiver
++       * types including 10G Ethernet which is not truth. So clear all claimed
++       * modes and set only one mode which module supports: 1000baseX_Full.
++       */
++      phylink_zero(modes);
++      phylink_set(modes, 1000baseX_Full);
++}
++
+ static const struct sfp_quirk sfp_quirks[] = {
+       {
+               // Alcatel Lucent G-010S-P can operate at 2500base-X, but
+@@ -63,6 +74,10 @@ static const struct sfp_quirk sfp_quirks
+               .vendor = "HUAWEI",
+               .part = "MA5671A",
+               .modes = sfp_quirk_2500basex,
++      }, {
++              .vendor = "UBNT",
++              .part = "UF-INSTANT",
++              .modes = sfp_quirk_ubnt_uf_instant,
+       },
+ };
+--- a/drivers/net/phy/sfp.c
++++ b/drivers/net/phy/sfp.c
+@@ -273,8 +273,21 @@ static const struct sff_data sff_data =
+ static bool sfp_module_supported(const struct sfp_eeprom_id *id)
+ {
+-      return id->base.phys_id == SFF8024_ID_SFP &&
+-             id->base.phys_ext_id == SFP_PHYS_EXT_ID_SFP;
++      if (id->base.phys_id == SFF8024_ID_SFP &&
++          id->base.phys_ext_id == SFP_PHYS_EXT_ID_SFP)
++              return true;
++
++      /* SFP GPON module Ubiquiti U-Fiber Instant has in its EEPROM stored
++       * phys id SFF instead of SFP. Therefore mark this module explicitly
++       * as supported based on vendor name and pn match.
++       */
++      if (id->base.phys_id == SFF8024_ID_SFF_8472 &&
++          id->base.phys_ext_id == SFP_PHYS_EXT_ID_SFP &&
++          !memcmp(id->base.vendor_name, "UBNT            ", 16) &&
++          !memcmp(id->base.vendor_pn, "UF-INSTANT      ", 16))
++              return true;
++
++      return false;
+ }
+ static const struct sff_data sfp_data = {
diff --git a/target/linux/generic/pending-5.4/772-net-sfp-relax-bitrate-devided-check.patch b/target/linux/generic/pending-5.4/772-net-sfp-relax-bitrate-devided-check.patch
new file mode 100644 (file)
index 0000000..672d2d0
--- /dev/null
@@ -0,0 +1,44 @@
+From 7a77233ec6d114322e2c4f71b4e26dbecd9ea8a7 Mon Sep 17 00:00:00 2001
+From: Russell King <rmk+kernel@armlinux.org.uk>
+Date: Wed, 9 Dec 2020 11:22:54 +0000
+Subject: net: sfp: relax bitrate-derived mode check
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Do not check the encoding when deriving 1000BASE-X from the bitrate
+when no other modes are discovered. Some GPON modules (VSOL V2801F
+and CarlitoxxPro CPGOS03-0490 v2.0) indicate NRZ encoding with a
+1200Mbaud bitrate, but should be driven with 1000BASE-X on the host
+side.
+
+Tested-by: Pali Rohár <pali@kernel.org>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/phy/sfp-bus.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/phy/sfp-bus.c
++++ b/drivers/net/phy/sfp-bus.c
+@@ -349,14 +349,13 @@ void sfp_parse_support(struct sfp_bus *b
+       }
+       /* If we haven't discovered any modes that this module supports, try
+-       * the encoding and bitrate to determine supported modes. Some BiDi
+-       * modules (eg, 1310nm/1550nm) are not 1000BASE-BX compliant due to
+-       * the differing wavelengths, so do not set any transceiver bits.
++       * the bitrate to determine supported modes. Some BiDi modules (eg,
++       * 1310nm/1550nm) are not 1000BASE-BX compliant due to the differing
++       * wavelengths, so do not set any transceiver bits.
+        */
+       if (bitmap_empty(modes, __ETHTOOL_LINK_MODE_MASK_NBITS)) {
+-              /* If the encoding and bit rate allows 1000baseX */
+-              if (id->base.encoding == SFF8024_ENCODING_8B10B && br_nom &&
+-                  br_min <= 1300 && br_max >= 1200)
++              /* If the bit rate allows 1000baseX */
++              if (br_nom && br_min <= 1300 && br_max >= 1200)
+                       phylink_set(modes, 1000baseX_Full);
+       }