1 From a4648a1957cd79bc389538aa0472db39a56e3df6 Mon Sep 17 00:00:00 2001
2 From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
3 Date: Fri, 26 Aug 2022 08:43:30 +0100
4 Subject: [PATCH 1/6] net: sfp: move quirk handling into sfp.c
6 We need to handle more quirks than just those which affect the link
7 modes of the module. Move the quirk lookup into sfp.c, and pass the
10 Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
12 drivers/net/phy/sfp-bus.c | 98 ++-------------------------------------
13 drivers/net/phy/sfp.c | 94 ++++++++++++++++++++++++++++++++++++-
14 drivers/net/phy/sfp.h | 9 +++-
15 3 files changed, 104 insertions(+), 97 deletions(-)
17 --- a/drivers/net/phy/sfp-bus.c
18 +++ b/drivers/net/phy/sfp-bus.c
26 - void (*modes)(const struct sfp_eeprom_id *id, unsigned long *modes);
30 * struct sfp_bus - internal representation of a sfp bus
32 @@ -38,93 +32,6 @@ struct sfp_bus {
36 -static void sfp_quirk_2500basex(const struct sfp_eeprom_id *id,
37 - unsigned long *modes)
39 - phylink_set(modes, 2500baseX_Full);
42 -static void sfp_quirk_ubnt_uf_instant(const struct sfp_eeprom_id *id,
43 - unsigned long *modes)
45 - /* Ubiquiti U-Fiber Instant module claims that support all transceiver
46 - * types including 10G Ethernet which is not truth. So clear all claimed
47 - * modes and set only one mode which module supports: 1000baseX_Full.
49 - phylink_zero(modes);
50 - phylink_set(modes, 1000baseX_Full);
53 -static const struct sfp_quirk sfp_quirks[] = {
55 - // Alcatel Lucent G-010S-P can operate at 2500base-X, but
56 - // incorrectly report 2500MBd NRZ in their EEPROM
57 - .vendor = "ALCATELLUCENT",
59 - .modes = sfp_quirk_2500basex,
61 - // Alcatel Lucent G-010S-A can operate at 2500base-X, but
62 - // report 3.2GBd NRZ in their EEPROM
63 - .vendor = "ALCATELLUCENT",
64 - .part = "3FE46541AA",
65 - .modes = sfp_quirk_2500basex,
67 - // Huawei MA5671A can operate at 2500base-X, but report 1.2GBd
68 - // NRZ in their EEPROM
71 - .modes = sfp_quirk_2500basex,
73 - // Lantech 8330-262D-E can operate at 2500base-X, but
74 - // incorrectly report 2500MBd NRZ in their EEPROM
75 - .vendor = "Lantech",
76 - .part = "8330-262D-E",
77 - .modes = sfp_quirk_2500basex,
80 - .part = "UF-INSTANT",
81 - .modes = sfp_quirk_ubnt_uf_instant,
85 -static size_t sfp_strlen(const char *str, size_t maxlen)
89 - /* Trailing characters should be filled with space chars */
90 - for (i = 0, size = 0; i < maxlen; i++)
97 -static bool sfp_match(const char *qs, const char *str, size_t len)
101 - if (strlen(qs) != len)
103 - return !strncmp(qs, str, len);
106 -static const struct sfp_quirk *sfp_lookup_quirk(const struct sfp_eeprom_id *id)
108 - const struct sfp_quirk *q;
112 - vs = sfp_strlen(id->base.vendor_name, ARRAY_SIZE(id->base.vendor_name));
113 - ps = sfp_strlen(id->base.vendor_pn, ARRAY_SIZE(id->base.vendor_pn));
115 - for (i = 0, q = sfp_quirks; i < ARRAY_SIZE(sfp_quirks); i++, q++)
116 - if (sfp_match(q->vendor, id->base.vendor_name, vs) &&
117 - sfp_match(q->part, id->base.vendor_pn, ps))
124 * sfp_parse_port() - Parse the EEPROM base ID, setting the port type
125 * @bus: a pointer to the &struct sfp_bus structure for the sfp module
126 @@ -786,12 +693,13 @@ void sfp_link_down(struct sfp_bus *bus)
128 EXPORT_SYMBOL_GPL(sfp_link_down);
130 -int sfp_module_insert(struct sfp_bus *bus, const struct sfp_eeprom_id *id)
131 +int sfp_module_insert(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
132 + const struct sfp_quirk *quirk)
134 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
137 - bus->sfp_quirk = sfp_lookup_quirk(id);
138 + bus->sfp_quirk = quirk;
140 if (ops && ops->module_insert)
141 ret = ops->module_insert(bus->upstream, id);
142 --- a/drivers/net/phy/sfp.c
143 +++ b/drivers/net/phy/sfp.c
144 @@ -252,6 +252,8 @@ struct sfp {
145 unsigned int module_t_start_up;
146 bool tx_fault_ignore;
148 + const struct sfp_quirk *quirk;
150 #if IS_ENABLED(CONFIG_HWMON)
151 struct sfp_diag diag;
152 struct delayed_work hwmon_probe;
153 @@ -308,6 +310,93 @@ static const struct of_device_id sfp_of_
155 MODULE_DEVICE_TABLE(of, sfp_of_match);
157 +static void sfp_quirk_2500basex(const struct sfp_eeprom_id *id,
158 + unsigned long *modes)
160 + linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, modes);
163 +static void sfp_quirk_ubnt_uf_instant(const struct sfp_eeprom_id *id,
164 + unsigned long *modes)
166 + /* Ubiquiti U-Fiber Instant module claims that support all transceiver
167 + * types including 10G Ethernet which is not truth. So clear all claimed
168 + * modes and set only one mode which module supports: 1000baseX_Full.
170 + linkmode_zero(modes);
171 + linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, modes);
174 +static const struct sfp_quirk sfp_quirks[] = {
176 + // Alcatel Lucent G-010S-P can operate at 2500base-X, but
177 + // incorrectly report 2500MBd NRZ in their EEPROM
178 + .vendor = "ALCATELLUCENT",
180 + .modes = sfp_quirk_2500basex,
182 + // Alcatel Lucent G-010S-A can operate at 2500base-X, but
183 + // report 3.2GBd NRZ in their EEPROM
184 + .vendor = "ALCATELLUCENT",
185 + .part = "3FE46541AA",
186 + .modes = sfp_quirk_2500basex,
188 + // Huawei MA5671A can operate at 2500base-X, but report 1.2GBd
189 + // NRZ in their EEPROM
190 + .vendor = "HUAWEI",
192 + .modes = sfp_quirk_2500basex,
194 + // Lantech 8330-262D-E can operate at 2500base-X, but
195 + // incorrectly report 2500MBd NRZ in their EEPROM
196 + .vendor = "Lantech",
197 + .part = "8330-262D-E",
198 + .modes = sfp_quirk_2500basex,
201 + .part = "UF-INSTANT",
202 + .modes = sfp_quirk_ubnt_uf_instant,
206 +static size_t sfp_strlen(const char *str, size_t maxlen)
210 + /* Trailing characters should be filled with space chars */
211 + for (i = 0, size = 0; i < maxlen; i++)
218 +static bool sfp_match(const char *qs, const char *str, size_t len)
222 + if (strlen(qs) != len)
224 + return !strncmp(qs, str, len);
227 +static const struct sfp_quirk *sfp_lookup_quirk(const struct sfp_eeprom_id *id)
229 + const struct sfp_quirk *q;
233 + vs = sfp_strlen(id->base.vendor_name, ARRAY_SIZE(id->base.vendor_name));
234 + ps = sfp_strlen(id->base.vendor_pn, ARRAY_SIZE(id->base.vendor_pn));
236 + for (i = 0, q = sfp_quirks; i < ARRAY_SIZE(sfp_quirks); i++, q++)
237 + if (sfp_match(q->vendor, id->base.vendor_name, vs) &&
238 + sfp_match(q->part, id->base.vendor_pn, ps))
244 static unsigned long poll_jiffies;
246 static unsigned int sfp_gpio_get_state(struct sfp *sfp)
247 @@ -1952,6 +2041,8 @@ static int sfp_sm_mod_probe(struct sfp *
249 sfp->tx_fault_ignore = false;
251 + sfp->quirk = sfp_lookup_quirk(&id);
256 @@ -2063,7 +2154,8 @@ static void sfp_sm_module(struct sfp *sf
259 /* Report the module insertion to the upstream device */
260 - err = sfp_module_insert(sfp->sfp_bus, &sfp->id);
261 + err = sfp_module_insert(sfp->sfp_bus, &sfp->id,
264 sfp_sm_mod_next(sfp, SFP_MOD_ERROR, 0);
266 --- a/drivers/net/phy/sfp.h
267 +++ b/drivers/net/phy/sfp.h
273 + const char *vendor;
275 + void (*modes)(const struct sfp_eeprom_id *id, unsigned long *modes);
278 struct sfp_socket_ops {
279 void (*attach)(struct sfp *sfp);
280 void (*detach)(struct sfp *sfp);
281 @@ -23,7 +29,8 @@ int sfp_add_phy(struct sfp_bus *bus, str
282 void sfp_remove_phy(struct sfp_bus *bus);
283 void sfp_link_up(struct sfp_bus *bus);
284 void sfp_link_down(struct sfp_bus *bus);
285 -int sfp_module_insert(struct sfp_bus *bus, const struct sfp_eeprom_id *id);
286 +int sfp_module_insert(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
287 + const struct sfp_quirk *quirk);
288 void sfp_module_remove(struct sfp_bus *bus);
289 int sfp_module_start(struct sfp_bus *bus);
290 void sfp_module_stop(struct sfp_bus *bus);