8d43ccb3e922d1fc1051f0a61a7084f6fe1564b0
[openwrt/staging/svanheule.git] / target / linux / generic / pending-5.15 / 770-net-sfp-move-quirk-handling-into-sfp.c.patch
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
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 ---
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(-)
16
17 --- a/drivers/net/phy/sfp-bus.c
18 +++ b/drivers/net/phy/sfp-bus.c
19 @@ -10,12 +10,6 @@
20
21 #include "sfp.h"
22
23 -struct sfp_quirk {
24 - const char *vendor;
25 - const char *part;
26 - void (*modes)(const struct sfp_eeprom_id *id, unsigned long *modes);
27 -};
28 -
29 /**
30 * struct sfp_bus - internal representation of a sfp bus
31 */
32 @@ -38,93 +32,6 @@ struct sfp_bus {
33 bool started;
34 };
35
36 -static void sfp_quirk_2500basex(const struct sfp_eeprom_id *id,
37 - unsigned long *modes)
38 -{
39 - phylink_set(modes, 2500baseX_Full);
40 -}
41 -
42 -static void sfp_quirk_ubnt_uf_instant(const struct sfp_eeprom_id *id,
43 - unsigned long *modes)
44 -{
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.
48 - */
49 - phylink_zero(modes);
50 - phylink_set(modes, 1000baseX_Full);
51 -}
52 -
53 -static const struct sfp_quirk sfp_quirks[] = {
54 - {
55 - // Alcatel Lucent G-010S-P can operate at 2500base-X, but
56 - // incorrectly report 2500MBd NRZ in their EEPROM
57 - .vendor = "ALCATELLUCENT",
58 - .part = "G010SP",
59 - .modes = sfp_quirk_2500basex,
60 - }, {
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,
66 - }, {
67 - // Huawei MA5671A can operate at 2500base-X, but report 1.2GBd
68 - // NRZ in their EEPROM
69 - .vendor = "HUAWEI",
70 - .part = "MA5671A",
71 - .modes = sfp_quirk_2500basex,
72 - }, {
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,
78 - }, {
79 - .vendor = "UBNT",
80 - .part = "UF-INSTANT",
81 - .modes = sfp_quirk_ubnt_uf_instant,
82 - },
83 -};
84 -
85 -static size_t sfp_strlen(const char *str, size_t maxlen)
86 -{
87 - size_t size, i;
88 -
89 - /* Trailing characters should be filled with space chars */
90 - for (i = 0, size = 0; i < maxlen; i++)
91 - if (str[i] != ' ')
92 - size = i + 1;
93 -
94 - return size;
95 -}
96 -
97 -static bool sfp_match(const char *qs, const char *str, size_t len)
98 -{
99 - if (!qs)
100 - return true;
101 - if (strlen(qs) != len)
102 - return false;
103 - return !strncmp(qs, str, len);
104 -}
105 -
106 -static const struct sfp_quirk *sfp_lookup_quirk(const struct sfp_eeprom_id *id)
107 -{
108 - const struct sfp_quirk *q;
109 - unsigned int i;
110 - size_t vs, ps;
111 -
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));
114 -
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))
118 - return q;
119 -
120 - return NULL;
121 -}
122 -
123 /**
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)
127 }
128 EXPORT_SYMBOL_GPL(sfp_link_down);
129
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)
133 {
134 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
135 int ret = 0;
136
137 - bus->sfp_quirk = sfp_lookup_quirk(id);
138 + bus->sfp_quirk = quirk;
139
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;
147
148 + const struct sfp_quirk *quirk;
149 +
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_
154 };
155 MODULE_DEVICE_TABLE(of, sfp_of_match);
156
157 +static void sfp_quirk_2500basex(const struct sfp_eeprom_id *id,
158 + unsigned long *modes)
159 +{
160 + linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, modes);
161 +}
162 +
163 +static void sfp_quirk_ubnt_uf_instant(const struct sfp_eeprom_id *id,
164 + unsigned long *modes)
165 +{
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.
169 + */
170 + linkmode_zero(modes);
171 + linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, modes);
172 +}
173 +
174 +static const struct sfp_quirk sfp_quirks[] = {
175 + {
176 + // Alcatel Lucent G-010S-P can operate at 2500base-X, but
177 + // incorrectly report 2500MBd NRZ in their EEPROM
178 + .vendor = "ALCATELLUCENT",
179 + .part = "G010SP",
180 + .modes = sfp_quirk_2500basex,
181 + }, {
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,
187 + }, {
188 + // Huawei MA5671A can operate at 2500base-X, but report 1.2GBd
189 + // NRZ in their EEPROM
190 + .vendor = "HUAWEI",
191 + .part = "MA5671A",
192 + .modes = sfp_quirk_2500basex,
193 + }, {
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,
199 + }, {
200 + .vendor = "UBNT",
201 + .part = "UF-INSTANT",
202 + .modes = sfp_quirk_ubnt_uf_instant,
203 + },
204 +};
205 +
206 +static size_t sfp_strlen(const char *str, size_t maxlen)
207 +{
208 + size_t size, i;
209 +
210 + /* Trailing characters should be filled with space chars */
211 + for (i = 0, size = 0; i < maxlen; i++)
212 + if (str[i] != ' ')
213 + size = i + 1;
214 +
215 + return size;
216 +}
217 +
218 +static bool sfp_match(const char *qs, const char *str, size_t len)
219 +{
220 + if (!qs)
221 + return true;
222 + if (strlen(qs) != len)
223 + return false;
224 + return !strncmp(qs, str, len);
225 +}
226 +
227 +static const struct sfp_quirk *sfp_lookup_quirk(const struct sfp_eeprom_id *id)
228 +{
229 + const struct sfp_quirk *q;
230 + unsigned int i;
231 + size_t vs, ps;
232 +
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));
235 +
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))
239 + return q;
240 +
241 + return NULL;
242 +}
243 +
244 static unsigned long poll_jiffies;
245
246 static unsigned int sfp_gpio_get_state(struct sfp *sfp)
247 @@ -1952,6 +2041,8 @@ static int sfp_sm_mod_probe(struct sfp *
248 else
249 sfp->tx_fault_ignore = false;
250
251 + sfp->quirk = sfp_lookup_quirk(&id);
252 +
253 return 0;
254 }
255
256 @@ -2063,7 +2154,8 @@ static void sfp_sm_module(struct sfp *sf
257 break;
258
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,
262 + sfp->quirk);
263 if (err < 0) {
264 sfp_sm_mod_next(sfp, SFP_MOD_ERROR, 0);
265 break;
266 --- a/drivers/net/phy/sfp.h
267 +++ b/drivers/net/phy/sfp.h
268 @@ -6,6 +6,12 @@
269
270 struct sfp;
271
272 +struct sfp_quirk {
273 + const char *vendor;
274 + const char *part;
275 + void (*modes)(const struct sfp_eeprom_id *id, unsigned long *modes);
276 +};
277 +
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);