kernel: bump 5.15 to 5.15.116
[openwrt/openwrt.git] / target / linux / generic / backport-5.15 / 784-v6.1-net-sfp-move-quirk-handling-into-sfp.c.patch
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
5
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
8 quirk to sfp-bus.c
9
10 Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
11 Signed-off-by: Jakub Kicinski <kuba@kernel.org>
12 ---
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(-)
17
18 --- a/drivers/net/phy/sfp-bus.c
19 +++ b/drivers/net/phy/sfp-bus.c
20 @@ -10,12 +10,6 @@
21
22 #include "sfp.h"
23
24 -struct sfp_quirk {
25 - const char *vendor;
26 - const char *part;
27 - void (*modes)(const struct sfp_eeprom_id *id, unsigned long *modes);
28 -};
29 -
30 /**
31 * struct sfp_bus - internal representation of a sfp bus
32 */
33 @@ -38,93 +32,6 @@ struct sfp_bus {
34 bool started;
35 };
36
37 -static void sfp_quirk_2500basex(const struct sfp_eeprom_id *id,
38 - unsigned long *modes)
39 -{
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 - // incorrectly report 2500MBd NRZ in their EEPROM
58 - .vendor = "ALCATELLUCENT",
59 - .part = "G010SP",
60 - .modes = sfp_quirk_2500basex,
61 - }, {
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,
67 - }, {
68 - // Huawei MA5671A can operate at 2500base-X, but report 1.2GBd
69 - // NRZ in their EEPROM
70 - .vendor = "HUAWEI",
71 - .part = "MA5671A",
72 - .modes = sfp_quirk_2500basex,
73 - }, {
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,
79 - }, {
80 - .vendor = "UBNT",
81 - .part = "UF-INSTANT",
82 - .modes = sfp_quirk_ubnt_uf_instant,
83 - },
84 -};
85 -
86 -static size_t sfp_strlen(const char *str, size_t maxlen)
87 -{
88 - size_t size, i;
89 -
90 - /* Trailing characters should be filled with space chars */
91 - for (i = 0, size = 0; i < maxlen; i++)
92 - if (str[i] != ' ')
93 - size = i + 1;
94 -
95 - return size;
96 -}
97 -
98 -static bool sfp_match(const char *qs, const char *str, size_t len)
99 -{
100 - if (!qs)
101 - return true;
102 - if (strlen(qs) != len)
103 - return false;
104 - return !strncmp(qs, str, len);
105 -}
106 -
107 -static const struct sfp_quirk *sfp_lookup_quirk(const struct sfp_eeprom_id *id)
108 -{
109 - const struct sfp_quirk *q;
110 - unsigned int i;
111 - size_t vs, ps;
112 -
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));
115 -
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))
119 - return q;
120 -
121 - return NULL;
122 -}
123 -
124 /**
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)
128 }
129 EXPORT_SYMBOL_GPL(sfp_link_down);
130
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)
134 {
135 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
136 int ret = 0;
137
138 - bus->sfp_quirk = sfp_lookup_quirk(id);
139 + bus->sfp_quirk = quirk;
140
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 @@ -259,6 +259,8 @@ struct sfp {
146 unsigned int module_t_start_up;
147 bool tx_fault_ignore;
148
149 + const struct sfp_quirk *quirk;
150 +
151 #if IS_ENABLED(CONFIG_HWMON)
152 struct sfp_diag diag;
153 struct delayed_work hwmon_probe;
154 @@ -315,6 +317,93 @@ static const struct of_device_id sfp_of_
155 };
156 MODULE_DEVICE_TABLE(of, sfp_of_match);
157
158 +static void sfp_quirk_2500basex(const struct sfp_eeprom_id *id,
159 + unsigned long *modes)
160 +{
161 + linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, modes);
162 +}
163 +
164 +static void sfp_quirk_ubnt_uf_instant(const struct sfp_eeprom_id *id,
165 + unsigned long *modes)
166 +{
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.
170 + */
171 + linkmode_zero(modes);
172 + linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, modes);
173 +}
174 +
175 +static const struct sfp_quirk sfp_quirks[] = {
176 + {
177 + // Alcatel Lucent G-010S-P can operate at 2500base-X, but
178 + // incorrectly report 2500MBd NRZ in their EEPROM
179 + .vendor = "ALCATELLUCENT",
180 + .part = "G010SP",
181 + .modes = sfp_quirk_2500basex,
182 + }, {
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,
188 + }, {
189 + // Huawei MA5671A can operate at 2500base-X, but report 1.2GBd
190 + // NRZ in their EEPROM
191 + .vendor = "HUAWEI",
192 + .part = "MA5671A",
193 + .modes = sfp_quirk_2500basex,
194 + }, {
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,
200 + }, {
201 + .vendor = "UBNT",
202 + .part = "UF-INSTANT",
203 + .modes = sfp_quirk_ubnt_uf_instant,
204 + },
205 +};
206 +
207 +static size_t sfp_strlen(const char *str, size_t maxlen)
208 +{
209 + size_t size, i;
210 +
211 + /* Trailing characters should be filled with space chars */
212 + for (i = 0, size = 0; i < maxlen; i++)
213 + if (str[i] != ' ')
214 + size = i + 1;
215 +
216 + return size;
217 +}
218 +
219 +static bool sfp_match(const char *qs, const char *str, size_t len)
220 +{
221 + if (!qs)
222 + return true;
223 + if (strlen(qs) != len)
224 + return false;
225 + return !strncmp(qs, str, len);
226 +}
227 +
228 +static const struct sfp_quirk *sfp_lookup_quirk(const struct sfp_eeprom_id *id)
229 +{
230 + const struct sfp_quirk *q;
231 + unsigned int i;
232 + size_t vs, ps;
233 +
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));
236 +
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))
240 + return q;
241 +
242 + return NULL;
243 +}
244 +
245 static unsigned long poll_jiffies;
246
247 static unsigned int sfp_gpio_get_state(struct sfp *sfp)
248 @@ -1966,6 +2055,8 @@ static int sfp_sm_mod_probe(struct sfp *
249 else
250 sfp->tx_fault_ignore = false;
251
252 + sfp->quirk = sfp_lookup_quirk(&id);
253 +
254 return 0;
255 }
256
257 @@ -2077,7 +2168,8 @@ static void sfp_sm_module(struct sfp *sf
258 break;
259
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,
263 + sfp->quirk);
264 if (err < 0) {
265 sfp_sm_mod_next(sfp, SFP_MOD_ERROR, 0);
266 break;
267 --- a/drivers/net/phy/sfp.h
268 +++ b/drivers/net/phy/sfp.h
269 @@ -6,6 +6,12 @@
270
271 struct sfp;
272
273 +struct sfp_quirk {
274 + const char *vendor;
275 + const char *part;
276 + void (*modes)(const struct sfp_eeprom_id *id, unsigned long *modes);
277 +};
278 +
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);