mvebu: SFP backports for GPON modules

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>
This commit is contained in:
Marek Behún 2022-01-08 19:56:02 +01:00 committed by Christian Lamparter
parent 52de8bf86e
commit 0e5350db43
15 changed files with 262 additions and 31 deletions

View File

@ -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)

View 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 *
}
}

View 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 *
}
}

View 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);

View 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)
{

View 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);

View 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;
}

View 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);

View 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;
}

View 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 */

View 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 */

View 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.
*/

View 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) {

View File

@ -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 = {

View File

@ -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);
}