1 From 23571c7b96437483d28a990c906cc81f5f66374e Mon Sep 17 00:00:00 2001
2 From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
3 Date: Tue, 13 Sep 2022 20:06:32 +0100
4 Subject: [PATCH 1/1] 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>
11 Signed-off-by: Jakub Kicinski <kuba@kernel.org>
13 drivers/net/phy/sfp-bus.c | 98 ++-------------------------------------
14 drivers/net/phy/sfp.c | 94 ++++++++++++++++++++++++++++++++++++-
15 drivers/net/phy/sfp.h | 9 +++-
16 3 files changed, 104 insertions(+), 97 deletions(-)
18 --- a/drivers/net/phy/sfp-bus.c
19 +++ b/drivers/net/phy/sfp-bus.c
27 - void (*modes)(const struct sfp_eeprom_id *id, unsigned long *modes);
31 * struct sfp_bus - internal representation of a sfp bus
33 @@ -38,93 +32,6 @@ struct sfp_bus {
37 -static void sfp_quirk_2500basex(const struct sfp_eeprom_id *id,
38 - unsigned long *modes)
40 - phylink_set(modes, 2500baseX_Full);
43 -static void sfp_quirk_ubnt_uf_instant(const struct sfp_eeprom_id *id,
44 - unsigned long *modes)
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.
50 - phylink_zero(modes);
51 - phylink_set(modes, 1000baseX_Full);
54 -static const struct sfp_quirk sfp_quirks[] = {
56 - // Alcatel Lucent G-010S-P can operate at 2500base-X, but
57 - // incorrectly report 2500MBd NRZ in their EEPROM
58 - .vendor = "ALCATELLUCENT",
60 - .modes = sfp_quirk_2500basex,
62 - // Alcatel Lucent G-010S-A can operate at 2500base-X, but
63 - // report 3.2GBd NRZ in their EEPROM
64 - .vendor = "ALCATELLUCENT",
65 - .part = "3FE46541AA",
66 - .modes = sfp_quirk_2500basex,
68 - // Huawei MA5671A can operate at 2500base-X, but report 1.2GBd
69 - // NRZ in their EEPROM
72 - .modes = sfp_quirk_2500basex,
74 - // Lantech 8330-262D-E can operate at 2500base-X, but
75 - // incorrectly report 2500MBd NRZ in their EEPROM
76 - .vendor = "Lantech",
77 - .part = "8330-262D-E",
78 - .modes = sfp_quirk_2500basex,
81 - .part = "UF-INSTANT",
82 - .modes = sfp_quirk_ubnt_uf_instant,
86 -static size_t sfp_strlen(const char *str, size_t maxlen)
90 - /* Trailing characters should be filled with space chars */
91 - for (i = 0, size = 0; i < maxlen; i++)
98 -static bool sfp_match(const char *qs, const char *str, size_t len)
102 - if (strlen(qs) != len)
104 - return !strncmp(qs, str, len);
107 -static const struct sfp_quirk *sfp_lookup_quirk(const struct sfp_eeprom_id *id)
109 - const struct sfp_quirk *q;
113 - vs = sfp_strlen(id->base.vendor_name, ARRAY_SIZE(id->base.vendor_name));
114 - ps = sfp_strlen(id->base.vendor_pn, ARRAY_SIZE(id->base.vendor_pn));
116 - for (i = 0, q = sfp_quirks; i < ARRAY_SIZE(sfp_quirks); i++, q++)
117 - if (sfp_match(q->vendor, id->base.vendor_name, vs) &&
118 - sfp_match(q->part, id->base.vendor_pn, ps))
125 * sfp_parse_port() - Parse the EEPROM base ID, setting the port type
126 * @bus: a pointer to the &struct sfp_bus structure for the sfp module
127 @@ -786,12 +693,13 @@ void sfp_link_down(struct sfp_bus *bus)
129 EXPORT_SYMBOL_GPL(sfp_link_down);
131 -int sfp_module_insert(struct sfp_bus *bus, const struct sfp_eeprom_id *id)
132 +int sfp_module_insert(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
133 + const struct sfp_quirk *quirk)
135 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
138 - bus->sfp_quirk = sfp_lookup_quirk(id);
139 + bus->sfp_quirk = quirk;
141 if (ops && ops->module_insert)
142 ret = ops->module_insert(bus->upstream, id);
143 --- a/drivers/net/phy/sfp.c
144 +++ b/drivers/net/phy/sfp.c
145 @@ -253,6 +253,8 @@ struct sfp {
146 unsigned int module_t_start_up;
147 bool tx_fault_ignore;
149 + const struct sfp_quirk *quirk;
151 #if IS_ENABLED(CONFIG_HWMON)
152 struct sfp_diag diag;
153 struct delayed_work hwmon_probe;
154 @@ -309,6 +311,93 @@ static const struct of_device_id sfp_of_
156 MODULE_DEVICE_TABLE(of, sfp_of_match);
158 +static void sfp_quirk_2500basex(const struct sfp_eeprom_id *id,
159 + unsigned long *modes)
161 + linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, modes);
164 +static void sfp_quirk_ubnt_uf_instant(const struct sfp_eeprom_id *id,
165 + unsigned long *modes)
167 + /* Ubiquiti U-Fiber Instant module claims that support all transceiver
168 + * types including 10G Ethernet which is not truth. So clear all claimed
169 + * modes and set only one mode which module supports: 1000baseX_Full.
171 + linkmode_zero(modes);
172 + linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, modes);
175 +static const struct sfp_quirk sfp_quirks[] = {
177 + // Alcatel Lucent G-010S-P can operate at 2500base-X, but
178 + // incorrectly report 2500MBd NRZ in their EEPROM
179 + .vendor = "ALCATELLUCENT",
181 + .modes = sfp_quirk_2500basex,
183 + // Alcatel Lucent G-010S-A can operate at 2500base-X, but
184 + // report 3.2GBd NRZ in their EEPROM
185 + .vendor = "ALCATELLUCENT",
186 + .part = "3FE46541AA",
187 + .modes = sfp_quirk_2500basex,
189 + // Huawei MA5671A can operate at 2500base-X, but report 1.2GBd
190 + // NRZ in their EEPROM
191 + .vendor = "HUAWEI",
193 + .modes = sfp_quirk_2500basex,
195 + // Lantech 8330-262D-E can operate at 2500base-X, but
196 + // incorrectly report 2500MBd NRZ in their EEPROM
197 + .vendor = "Lantech",
198 + .part = "8330-262D-E",
199 + .modes = sfp_quirk_2500basex,
202 + .part = "UF-INSTANT",
203 + .modes = sfp_quirk_ubnt_uf_instant,
207 +static size_t sfp_strlen(const char *str, size_t maxlen)
211 + /* Trailing characters should be filled with space chars */
212 + for (i = 0, size = 0; i < maxlen; i++)
219 +static bool sfp_match(const char *qs, const char *str, size_t len)
223 + if (strlen(qs) != len)
225 + return !strncmp(qs, str, len);
228 +static const struct sfp_quirk *sfp_lookup_quirk(const struct sfp_eeprom_id *id)
230 + const struct sfp_quirk *q;
234 + vs = sfp_strlen(id->base.vendor_name, ARRAY_SIZE(id->base.vendor_name));
235 + ps = sfp_strlen(id->base.vendor_pn, ARRAY_SIZE(id->base.vendor_pn));
237 + for (i = 0, q = sfp_quirks; i < ARRAY_SIZE(sfp_quirks); i++, q++)
238 + if (sfp_match(q->vendor, id->base.vendor_name, vs) &&
239 + sfp_match(q->part, id->base.vendor_pn, ps))
245 static unsigned long poll_jiffies;
247 static unsigned int sfp_gpio_get_state(struct sfp *sfp)
248 @@ -1964,6 +2053,8 @@ static int sfp_sm_mod_probe(struct sfp *
250 sfp->tx_fault_ignore = false;
252 + sfp->quirk = sfp_lookup_quirk(&id);
257 @@ -2075,7 +2166,8 @@ static void sfp_sm_module(struct sfp *sf
260 /* Report the module insertion to the upstream device */
261 - err = sfp_module_insert(sfp->sfp_bus, &sfp->id);
262 + err = sfp_module_insert(sfp->sfp_bus, &sfp->id,
265 sfp_sm_mod_next(sfp, SFP_MOD_ERROR, 0);
267 --- a/drivers/net/phy/sfp.h
268 +++ b/drivers/net/phy/sfp.h
274 + const char *vendor;
276 + void (*modes)(const struct sfp_eeprom_id *id, unsigned long *modes);
279 struct sfp_socket_ops {
280 void (*attach)(struct sfp *sfp);
281 void (*detach)(struct sfp *sfp);
282 @@ -23,7 +29,8 @@ int sfp_add_phy(struct sfp_bus *bus, str
283 void sfp_remove_phy(struct sfp_bus *bus);
284 void sfp_link_up(struct sfp_bus *bus);
285 void sfp_link_down(struct sfp_bus *bus);
286 -int sfp_module_insert(struct sfp_bus *bus, const struct sfp_eeprom_id *id);
287 +int sfp_module_insert(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
288 + const struct sfp_quirk *quirk);
289 void sfp_module_remove(struct sfp_bus *bus);
290 int sfp_module_start(struct sfp_bus *bus);
291 void sfp_module_stop(struct sfp_bus *bus);