developer | 53810fa | 2022-04-19 10:14:08 +0800 | [diff] [blame] | 1 | From f0b4f847673299577c29b71d3f3acd3c313d81b7 Mon Sep 17 00:00:00 2001 |
| 2 | From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org> |
| 3 | Date: Mon, 25 Jan 2021 16:02:28 +0100 |
| 4 | Subject: net: sfp: add mode quirk for GPON module Ubiquiti U-Fiber Instant |
| 5 | MIME-Version: 1.0 |
| 6 | Content-Type: text/plain; charset=UTF-8 |
| 7 | Content-Transfer-Encoding: 8bit |
| 8 | |
| 9 | The Ubiquiti U-Fiber Instant SFP GPON module has nonsensical information |
| 10 | stored in its EEPROM. It claims to support all transceiver types including |
| 11 | 10G Ethernet. Clear all claimed modes and set only 1000baseX_Full, which is |
| 12 | the only one supported. |
| 13 | |
| 14 | This module has also phys_id set to SFF, and the SFP subsystem currently |
| 15 | does not allow to use SFP modules detected as SFFs. Add exception for this |
| 16 | module so it can be detected as supported. |
| 17 | |
| 18 | This change finally allows to detect and use SFP GPON module Ubiquiti |
| 19 | U-Fiber Instant on Linux system. |
| 20 | |
| 21 | EEPROM content of this SFP module is (where XX is serial number): |
| 22 | |
| 23 | 00: 02 04 0b ff ff ff ff ff ff ff ff 03 0c 00 14 c8 ???........??.?? |
| 24 | 10: 00 00 00 00 55 42 4e 54 20 20 20 20 20 20 20 20 ....UBNT |
| 25 | 20: 20 20 20 20 00 18 e8 29 55 46 2d 49 4e 53 54 41 .??)UF-INSTA |
| 26 | 30: 4e 54 20 20 20 20 20 20 34 20 20 20 05 1e 00 36 NT 4 ??.6 |
| 27 | 40: 00 06 00 00 55 42 4e 54 XX XX XX XX XX XX XX XX .?..UBNTXXXXXXXX |
| 28 | 50: 20 20 20 20 31 34 30 31 32 33 20 20 60 80 02 41 140123 `??A |
| 29 | |
| 30 | Signed-off-by: Pali Rohár <pali@kernel.org> |
| 31 | Signed-off-by: Jakub Kicinski <kuba@kernel.org> |
| 32 | --- |
| 33 | drivers/net/phy/sfp-bus.c | 15 +++++++++++++++ |
| 34 | drivers/net/phy/sfp.c | 17 +++++++++++++++-- |
| 35 | 2 files changed, 30 insertions(+), 2 deletions(-) |
| 36 | |
| 37 | --- a/drivers/net/phy/sfp-bus.c |
| 38 | +++ b/drivers/net/phy/sfp-bus.c |
| 39 | @@ -44,6 +44,17 @@ static void sfp_quirk_2500basex(const st |
| 40 | phylink_set(modes, 2500baseX_Full); |
| 41 | } |
| 42 | |
| 43 | +static void sfp_quirk_ubnt_uf_instant(const struct sfp_eeprom_id *id, |
| 44 | + unsigned long *modes) |
| 45 | +{ |
| 46 | + /* Ubiquiti U-Fiber Instant module claims that support all transceiver |
| 47 | + * types including 10G Ethernet which is not truth. So clear all claimed |
| 48 | + * modes and set only one mode which module supports: 1000baseX_Full. |
| 49 | + */ |
| 50 | + phylink_zero(modes); |
| 51 | + phylink_set(modes, 1000baseX_Full); |
| 52 | +} |
| 53 | + |
| 54 | static const struct sfp_quirk sfp_quirks[] = { |
| 55 | { |
| 56 | // Alcatel Lucent G-010S-P can operate at 2500base-X, but |
| 57 | @@ -63,6 +74,10 @@ static const struct sfp_quirk sfp_quirks |
| 58 | .vendor = "HUAWEI", |
| 59 | .part = "MA5671A", |
| 60 | .modes = sfp_quirk_2500basex, |
| 61 | + }, { |
| 62 | + .vendor = "UBNT", |
| 63 | + .part = "UF-INSTANT", |
| 64 | + .modes = sfp_quirk_ubnt_uf_instant, |
| 65 | }, |
| 66 | }; |
| 67 | |
| 68 | --- a/drivers/net/phy/sfp.c |
| 69 | +++ b/drivers/net/phy/sfp.c |
| 70 | @@ -273,8 +273,21 @@ static const struct sff_data sff_data = |
| 71 | |
| 72 | static bool sfp_module_supported(const struct sfp_eeprom_id *id) |
| 73 | { |
| 74 | - return id->base.phys_id == SFF8024_ID_SFP && |
| 75 | - id->base.phys_ext_id == SFP_PHYS_EXT_ID_SFP; |
| 76 | + if (id->base.phys_id == SFF8024_ID_SFP && |
| 77 | + id->base.phys_ext_id == SFP_PHYS_EXT_ID_SFP) |
| 78 | + return true; |
| 79 | + |
| 80 | + /* SFP GPON module Ubiquiti U-Fiber Instant has in its EEPROM stored |
| 81 | + * phys id SFF instead of SFP. Therefore mark this module explicitly |
| 82 | + * as supported based on vendor name and pn match. |
| 83 | + */ |
| 84 | + if (id->base.phys_id == SFF8024_ID_SFF_8472 && |
| 85 | + id->base.phys_ext_id == SFP_PHYS_EXT_ID_SFP && |
| 86 | + !memcmp(id->base.vendor_name, "UBNT ", 16) && |
| 87 | + !memcmp(id->base.vendor_pn, "UF-INSTANT ", 16)) |
| 88 | + return true; |
| 89 | + |
| 90 | + return false; |
| 91 | } |
| 92 | |
| 93 | static const struct sff_data sfp_data = { |