1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | #include <linux/export.h> |
3 | #include <linux/kref.h> |
4 | #include <linux/list.h> |
5 | #include <linux/mutex.h> |
6 | #include <linux/phylink.h> |
7 | #include <linux/property.h> |
8 | #include <linux/rtnetlink.h> |
9 | #include <linux/slab.h> |
10 | |
11 | #include "sfp.h" |
12 | |
13 | /** |
14 | * struct sfp_bus - internal representation of a sfp bus |
15 | */ |
16 | struct sfp_bus { |
17 | /* private: */ |
18 | struct kref kref; |
19 | struct list_head node; |
20 | const struct fwnode_handle *fwnode; |
21 | |
22 | const struct sfp_socket_ops *socket_ops; |
23 | struct device *sfp_dev; |
24 | struct sfp *sfp; |
25 | const struct sfp_quirk *sfp_quirk; |
26 | |
27 | const struct sfp_upstream_ops *upstream_ops; |
28 | void *upstream; |
29 | struct phy_device *phydev; |
30 | |
31 | bool registered; |
32 | bool started; |
33 | }; |
34 | |
35 | /** |
36 | * sfp_parse_port() - Parse the EEPROM base ID, setting the port type |
37 | * @bus: a pointer to the &struct sfp_bus structure for the sfp module |
38 | * @id: a pointer to the module's &struct sfp_eeprom_id |
39 | * @support: optional pointer to an array of unsigned long for the |
40 | * ethtool support mask |
41 | * |
42 | * Parse the EEPROM identification given in @id, and return one of |
43 | * %PORT_TP, %PORT_FIBRE or %PORT_OTHER. If @support is non-%NULL, |
44 | * also set the ethtool %ETHTOOL_LINK_MODE_xxx_BIT corresponding with |
45 | * the connector type. |
46 | * |
47 | * If the port type is not known, returns %PORT_OTHER. |
48 | */ |
49 | int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id, |
50 | unsigned long *support) |
51 | { |
52 | int port; |
53 | |
54 | /* port is the physical connector, set this from the connector field. */ |
55 | switch (id->base.connector) { |
56 | case SFF8024_CONNECTOR_SC: |
57 | case SFF8024_CONNECTOR_FIBERJACK: |
58 | case SFF8024_CONNECTOR_LC: |
59 | case SFF8024_CONNECTOR_MT_RJ: |
60 | case SFF8024_CONNECTOR_MU: |
61 | case SFF8024_CONNECTOR_OPTICAL_PIGTAIL: |
62 | case SFF8024_CONNECTOR_MPO_1X12: |
63 | case SFF8024_CONNECTOR_MPO_2X16: |
64 | port = PORT_FIBRE; |
65 | break; |
66 | |
67 | case SFF8024_CONNECTOR_RJ45: |
68 | port = PORT_TP; |
69 | break; |
70 | |
71 | case SFF8024_CONNECTOR_COPPER_PIGTAIL: |
72 | port = PORT_DA; |
73 | break; |
74 | |
75 | case SFF8024_CONNECTOR_UNSPEC: |
76 | if (id->base.e1000_base_t) { |
77 | port = PORT_TP; |
78 | break; |
79 | } |
80 | fallthrough; |
81 | case SFF8024_CONNECTOR_SG: /* guess */ |
82 | case SFF8024_CONNECTOR_HSSDC_II: |
83 | case SFF8024_CONNECTOR_NOSEPARATE: |
84 | case SFF8024_CONNECTOR_MXC_2X16: |
85 | port = PORT_OTHER; |
86 | break; |
87 | default: |
88 | dev_warn(bus->sfp_dev, "SFP: unknown connector id 0x%02x\n" , |
89 | id->base.connector); |
90 | port = PORT_OTHER; |
91 | break; |
92 | } |
93 | |
94 | if (support) { |
95 | switch (port) { |
96 | case PORT_FIBRE: |
97 | phylink_set(support, FIBRE); |
98 | break; |
99 | |
100 | case PORT_TP: |
101 | phylink_set(support, TP); |
102 | break; |
103 | } |
104 | } |
105 | |
106 | return port; |
107 | } |
108 | EXPORT_SYMBOL_GPL(sfp_parse_port); |
109 | |
110 | /** |
111 | * sfp_may_have_phy() - indicate whether the module may have a PHY |
112 | * @bus: a pointer to the &struct sfp_bus structure for the sfp module |
113 | * @id: a pointer to the module's &struct sfp_eeprom_id |
114 | * |
115 | * Parse the EEPROM identification given in @id, and return whether |
116 | * this module may have a PHY. |
117 | */ |
118 | bool sfp_may_have_phy(struct sfp_bus *bus, const struct sfp_eeprom_id *id) |
119 | { |
120 | if (id->base.e1000_base_t) |
121 | return true; |
122 | |
123 | if (id->base.phys_id != SFF8024_ID_DWDM_SFP) { |
124 | switch (id->base.extended_cc) { |
125 | case SFF8024_ECC_10GBASE_T_SFI: |
126 | case SFF8024_ECC_10GBASE_T_SR: |
127 | case SFF8024_ECC_5GBASE_T: |
128 | case SFF8024_ECC_2_5GBASE_T: |
129 | return true; |
130 | } |
131 | } |
132 | |
133 | return false; |
134 | } |
135 | EXPORT_SYMBOL_GPL(sfp_may_have_phy); |
136 | |
137 | /** |
138 | * sfp_parse_support() - Parse the eeprom id for supported link modes |
139 | * @bus: a pointer to the &struct sfp_bus structure for the sfp module |
140 | * @id: a pointer to the module's &struct sfp_eeprom_id |
141 | * @support: pointer to an array of unsigned long for the ethtool support mask |
142 | * @interfaces: pointer to an array of unsigned long for phy interface modes |
143 | * mask |
144 | * |
145 | * Parse the EEPROM identification information and derive the supported |
146 | * ethtool link modes for the module. |
147 | */ |
148 | void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id, |
149 | unsigned long *support, unsigned long *interfaces) |
150 | { |
151 | unsigned int br_min, br_nom, br_max; |
152 | __ETHTOOL_DECLARE_LINK_MODE_MASK(modes) = { 0, }; |
153 | |
154 | phylink_set(modes, Autoneg); |
155 | phylink_set(modes, Pause); |
156 | phylink_set(modes, Asym_Pause); |
157 | |
158 | /* Decode the bitrate information to MBd */ |
159 | br_min = br_nom = br_max = 0; |
160 | if (id->base.br_nominal) { |
161 | if (id->base.br_nominal != 255) { |
162 | br_nom = id->base.br_nominal * 100; |
163 | br_min = br_nom - id->base.br_nominal * id->ext.br_min; |
164 | br_max = br_nom + id->base.br_nominal * id->ext.br_max; |
165 | } else if (id->ext.br_max) { |
166 | br_nom = 250 * id->ext.br_max; |
167 | br_max = br_nom + br_nom * id->ext.br_min / 100; |
168 | br_min = br_nom - br_nom * id->ext.br_min / 100; |
169 | } |
170 | |
171 | /* When using passive cables, in case neither BR,min nor BR,max |
172 | * are specified, set br_min to 0 as the nominal value is then |
173 | * used as the maximum. |
174 | */ |
175 | if (br_min == br_max && id->base.sfp_ct_passive) |
176 | br_min = 0; |
177 | } |
178 | |
179 | /* Set ethtool support from the compliance fields. */ |
180 | if (id->base.e10g_base_sr) { |
181 | phylink_set(modes, 10000baseSR_Full); |
182 | __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); |
183 | } |
184 | if (id->base.e10g_base_lr) { |
185 | phylink_set(modes, 10000baseLR_Full); |
186 | __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); |
187 | } |
188 | if (id->base.e10g_base_lrm) { |
189 | phylink_set(modes, 10000baseLRM_Full); |
190 | __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); |
191 | } |
192 | if (id->base.e10g_base_er) { |
193 | phylink_set(modes, 10000baseER_Full); |
194 | __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); |
195 | } |
196 | if (id->base.e1000_base_sx || |
197 | id->base.e1000_base_lx || |
198 | id->base.e1000_base_cx) { |
199 | phylink_set(modes, 1000baseX_Full); |
200 | __set_bit(PHY_INTERFACE_MODE_1000BASEX, interfaces); |
201 | } |
202 | if (id->base.e1000_base_t) { |
203 | phylink_set(modes, 1000baseT_Half); |
204 | phylink_set(modes, 1000baseT_Full); |
205 | __set_bit(PHY_INTERFACE_MODE_1000BASEX, interfaces); |
206 | __set_bit(PHY_INTERFACE_MODE_SGMII, interfaces); |
207 | } |
208 | |
209 | /* 1000Base-PX or 1000Base-BX10 */ |
210 | if ((id->base.e_base_px || id->base.e_base_bx10) && |
211 | br_min <= 1300 && br_max >= 1200) { |
212 | phylink_set(modes, 1000baseX_Full); |
213 | __set_bit(PHY_INTERFACE_MODE_1000BASEX, interfaces); |
214 | } |
215 | |
216 | /* 100Base-FX, 100Base-LX, 100Base-PX, 100Base-BX10 */ |
217 | if (id->base.e100_base_fx || id->base.e100_base_lx) { |
218 | phylink_set(modes, 100baseFX_Full); |
219 | __set_bit(PHY_INTERFACE_MODE_100BASEX, interfaces); |
220 | } |
221 | if ((id->base.e_base_px || id->base.e_base_bx10) && br_nom == 100) { |
222 | phylink_set(modes, 100baseFX_Full); |
223 | __set_bit(PHY_INTERFACE_MODE_100BASEX, interfaces); |
224 | } |
225 | |
226 | /* For active or passive cables, select the link modes |
227 | * based on the bit rates and the cable compliance bytes. |
228 | */ |
229 | if ((id->base.sfp_ct_passive || id->base.sfp_ct_active) && br_nom) { |
230 | /* This may look odd, but some manufacturers use 12000MBd */ |
231 | if (br_min <= 12000 && br_max >= 10300) { |
232 | phylink_set(modes, 10000baseCR_Full); |
233 | __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); |
234 | } |
235 | if (br_min <= 3200 && br_max >= 3100) { |
236 | phylink_set(modes, 2500baseX_Full); |
237 | __set_bit(PHY_INTERFACE_MODE_2500BASEX, interfaces); |
238 | } |
239 | if (br_min <= 1300 && br_max >= 1200) { |
240 | phylink_set(modes, 1000baseX_Full); |
241 | __set_bit(PHY_INTERFACE_MODE_1000BASEX, interfaces); |
242 | } |
243 | } |
244 | if (id->base.sfp_ct_passive) { |
245 | if (id->base.passive.sff8431_app_e) { |
246 | phylink_set(modes, 10000baseCR_Full); |
247 | __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); |
248 | } |
249 | } |
250 | if (id->base.sfp_ct_active) { |
251 | if (id->base.active.sff8431_app_e || |
252 | id->base.active.sff8431_lim) { |
253 | phylink_set(modes, 10000baseCR_Full); |
254 | __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); |
255 | } |
256 | } |
257 | |
258 | switch (id->base.extended_cc) { |
259 | case SFF8024_ECC_UNSPEC: |
260 | break; |
261 | case SFF8024_ECC_100G_25GAUI_C2M_AOC: |
262 | if (br_min <= 28000 && br_max >= 25000) { |
263 | /* 25GBASE-R, possibly with FEC */ |
264 | __set_bit(PHY_INTERFACE_MODE_25GBASER, interfaces); |
265 | /* There is currently no link mode for 25000base |
266 | * with unspecified range, reuse SR. |
267 | */ |
268 | phylink_set(modes, 25000baseSR_Full); |
269 | } |
270 | break; |
271 | case SFF8024_ECC_100GBASE_SR4_25GBASE_SR: |
272 | phylink_set(modes, 100000baseSR4_Full); |
273 | phylink_set(modes, 25000baseSR_Full); |
274 | __set_bit(PHY_INTERFACE_MODE_25GBASER, interfaces); |
275 | break; |
276 | case SFF8024_ECC_100GBASE_LR4_25GBASE_LR: |
277 | case SFF8024_ECC_100GBASE_ER4_25GBASE_ER: |
278 | phylink_set(modes, 100000baseLR4_ER4_Full); |
279 | break; |
280 | case SFF8024_ECC_100GBASE_CR4: |
281 | phylink_set(modes, 100000baseCR4_Full); |
282 | fallthrough; |
283 | case SFF8024_ECC_25GBASE_CR_S: |
284 | case SFF8024_ECC_25GBASE_CR_N: |
285 | phylink_set(modes, 25000baseCR_Full); |
286 | __set_bit(PHY_INTERFACE_MODE_25GBASER, interfaces); |
287 | break; |
288 | case SFF8024_ECC_10GBASE_T_SFI: |
289 | case SFF8024_ECC_10GBASE_T_SR: |
290 | phylink_set(modes, 10000baseT_Full); |
291 | __set_bit(PHY_INTERFACE_MODE_10GBASER, interfaces); |
292 | break; |
293 | case SFF8024_ECC_5GBASE_T: |
294 | phylink_set(modes, 5000baseT_Full); |
295 | __set_bit(PHY_INTERFACE_MODE_5GBASER, interfaces); |
296 | break; |
297 | case SFF8024_ECC_2_5GBASE_T: |
298 | phylink_set(modes, 2500baseT_Full); |
299 | __set_bit(PHY_INTERFACE_MODE_2500BASEX, interfaces); |
300 | break; |
301 | default: |
302 | dev_warn(bus->sfp_dev, |
303 | "Unknown/unsupported extended compliance code: 0x%02x\n" , |
304 | id->base.extended_cc); |
305 | break; |
306 | } |
307 | |
308 | /* For fibre channel SFP, derive possible BaseX modes */ |
309 | if (id->base.fc_speed_100 || |
310 | id->base.fc_speed_200 || |
311 | id->base.fc_speed_400) { |
312 | if (id->base.br_nominal >= 31) { |
313 | phylink_set(modes, 2500baseX_Full); |
314 | __set_bit(PHY_INTERFACE_MODE_2500BASEX, interfaces); |
315 | } |
316 | if (id->base.br_nominal >= 12) { |
317 | phylink_set(modes, 1000baseX_Full); |
318 | __set_bit(PHY_INTERFACE_MODE_1000BASEX, interfaces); |
319 | } |
320 | } |
321 | |
322 | /* If we haven't discovered any modes that this module supports, try |
323 | * the bitrate to determine supported modes. Some BiDi modules (eg, |
324 | * 1310nm/1550nm) are not 1000BASE-BX compliant due to the differing |
325 | * wavelengths, so do not set any transceiver bits. |
326 | * |
327 | * Do the same for modules supporting 2500BASE-X. Note that some |
328 | * modules use 2500Mbaud rather than 3100 or 3200Mbaud for |
329 | * 2500BASE-X, so we allow some slack here. |
330 | */ |
331 | if (bitmap_empty(src: modes, nbits: __ETHTOOL_LINK_MODE_MASK_NBITS) && br_nom) { |
332 | if (br_min <= 1300 && br_max >= 1200) { |
333 | phylink_set(modes, 1000baseX_Full); |
334 | __set_bit(PHY_INTERFACE_MODE_1000BASEX, interfaces); |
335 | } |
336 | if (br_min <= 3200 && br_max >= 2500) { |
337 | phylink_set(modes, 2500baseX_Full); |
338 | __set_bit(PHY_INTERFACE_MODE_2500BASEX, interfaces); |
339 | } |
340 | } |
341 | |
342 | if (bus->sfp_quirk && bus->sfp_quirk->modes) |
343 | bus->sfp_quirk->modes(id, modes, interfaces); |
344 | |
345 | linkmode_or(dst: support, a: support, b: modes); |
346 | } |
347 | EXPORT_SYMBOL_GPL(sfp_parse_support); |
348 | |
349 | /** |
350 | * sfp_select_interface() - Select appropriate phy_interface_t mode |
351 | * @bus: a pointer to the &struct sfp_bus structure for the sfp module |
352 | * @link_modes: ethtool link modes mask |
353 | * |
354 | * Derive the phy_interface_t mode for the SFP module from the link |
355 | * modes mask. |
356 | */ |
357 | phy_interface_t sfp_select_interface(struct sfp_bus *bus, |
358 | unsigned long *link_modes) |
359 | { |
360 | if (phylink_test(link_modes, 25000baseCR_Full) || |
361 | phylink_test(link_modes, 25000baseKR_Full) || |
362 | phylink_test(link_modes, 25000baseSR_Full)) |
363 | return PHY_INTERFACE_MODE_25GBASER; |
364 | |
365 | if (phylink_test(link_modes, 10000baseCR_Full) || |
366 | phylink_test(link_modes, 10000baseSR_Full) || |
367 | phylink_test(link_modes, 10000baseLR_Full) || |
368 | phylink_test(link_modes, 10000baseLRM_Full) || |
369 | phylink_test(link_modes, 10000baseER_Full) || |
370 | phylink_test(link_modes, 10000baseT_Full)) |
371 | return PHY_INTERFACE_MODE_10GBASER; |
372 | |
373 | if (phylink_test(link_modes, 5000baseT_Full)) |
374 | return PHY_INTERFACE_MODE_5GBASER; |
375 | |
376 | if (phylink_test(link_modes, 2500baseX_Full)) |
377 | return PHY_INTERFACE_MODE_2500BASEX; |
378 | |
379 | if (phylink_test(link_modes, 1000baseT_Half) || |
380 | phylink_test(link_modes, 1000baseT_Full)) |
381 | return PHY_INTERFACE_MODE_SGMII; |
382 | |
383 | if (phylink_test(link_modes, 1000baseX_Full)) |
384 | return PHY_INTERFACE_MODE_1000BASEX; |
385 | |
386 | if (phylink_test(link_modes, 100baseFX_Full)) |
387 | return PHY_INTERFACE_MODE_100BASEX; |
388 | |
389 | dev_warn(bus->sfp_dev, "Unable to ascertain link mode\n" ); |
390 | |
391 | return PHY_INTERFACE_MODE_NA; |
392 | } |
393 | EXPORT_SYMBOL_GPL(sfp_select_interface); |
394 | |
395 | static LIST_HEAD(sfp_buses); |
396 | static DEFINE_MUTEX(sfp_mutex); |
397 | |
398 | static const struct sfp_upstream_ops *sfp_get_upstream_ops(struct sfp_bus *bus) |
399 | { |
400 | return bus->registered ? bus->upstream_ops : NULL; |
401 | } |
402 | |
403 | static struct sfp_bus *sfp_bus_get(const struct fwnode_handle *fwnode) |
404 | { |
405 | struct sfp_bus *sfp, *new, *found = NULL; |
406 | |
407 | new = kzalloc(size: sizeof(*new), GFP_KERNEL); |
408 | |
409 | mutex_lock(&sfp_mutex); |
410 | |
411 | list_for_each_entry(sfp, &sfp_buses, node) { |
412 | if (sfp->fwnode == fwnode) { |
413 | kref_get(kref: &sfp->kref); |
414 | found = sfp; |
415 | break; |
416 | } |
417 | } |
418 | |
419 | if (!found && new) { |
420 | kref_init(kref: &new->kref); |
421 | new->fwnode = fwnode; |
422 | list_add(new: &new->node, head: &sfp_buses); |
423 | found = new; |
424 | new = NULL; |
425 | } |
426 | |
427 | mutex_unlock(lock: &sfp_mutex); |
428 | |
429 | kfree(objp: new); |
430 | |
431 | return found; |
432 | } |
433 | |
434 | static void sfp_bus_release(struct kref *kref) |
435 | { |
436 | struct sfp_bus *bus = container_of(kref, struct sfp_bus, kref); |
437 | |
438 | list_del(entry: &bus->node); |
439 | mutex_unlock(lock: &sfp_mutex); |
440 | kfree(objp: bus); |
441 | } |
442 | |
443 | /** |
444 | * sfp_bus_put() - put a reference on the &struct sfp_bus |
445 | * @bus: the &struct sfp_bus found via sfp_bus_find_fwnode() |
446 | * |
447 | * Put a reference on the &struct sfp_bus and free the underlying structure |
448 | * if this was the last reference. |
449 | */ |
450 | void sfp_bus_put(struct sfp_bus *bus) |
451 | { |
452 | if (bus) |
453 | kref_put_mutex(kref: &bus->kref, release: sfp_bus_release, lock: &sfp_mutex); |
454 | } |
455 | EXPORT_SYMBOL_GPL(sfp_bus_put); |
456 | |
457 | static int sfp_register_bus(struct sfp_bus *bus) |
458 | { |
459 | const struct sfp_upstream_ops *ops = bus->upstream_ops; |
460 | int ret; |
461 | |
462 | if (ops) { |
463 | if (ops->link_down) |
464 | ops->link_down(bus->upstream); |
465 | if (ops->connect_phy && bus->phydev) { |
466 | ret = ops->connect_phy(bus->upstream, bus->phydev); |
467 | if (ret) |
468 | return ret; |
469 | } |
470 | } |
471 | bus->registered = true; |
472 | bus->socket_ops->attach(bus->sfp); |
473 | if (bus->started) |
474 | bus->socket_ops->start(bus->sfp); |
475 | bus->upstream_ops->attach(bus->upstream, bus); |
476 | return 0; |
477 | } |
478 | |
479 | static void sfp_unregister_bus(struct sfp_bus *bus) |
480 | { |
481 | const struct sfp_upstream_ops *ops = bus->upstream_ops; |
482 | |
483 | if (bus->registered) { |
484 | bus->upstream_ops->detach(bus->upstream, bus); |
485 | if (bus->started) |
486 | bus->socket_ops->stop(bus->sfp); |
487 | bus->socket_ops->detach(bus->sfp); |
488 | if (bus->phydev && ops && ops->disconnect_phy) |
489 | ops->disconnect_phy(bus->upstream); |
490 | } |
491 | bus->registered = false; |
492 | } |
493 | |
494 | /** |
495 | * sfp_get_module_info() - Get the ethtool_modinfo for a SFP module |
496 | * @bus: a pointer to the &struct sfp_bus structure for the sfp module |
497 | * @modinfo: a &struct ethtool_modinfo |
498 | * |
499 | * Fill in the type and eeprom_len parameters in @modinfo for a module on |
500 | * the sfp bus specified by @bus. |
501 | * |
502 | * Returns 0 on success or a negative errno number. |
503 | */ |
504 | int sfp_get_module_info(struct sfp_bus *bus, struct ethtool_modinfo *modinfo) |
505 | { |
506 | return bus->socket_ops->module_info(bus->sfp, modinfo); |
507 | } |
508 | EXPORT_SYMBOL_GPL(sfp_get_module_info); |
509 | |
510 | /** |
511 | * sfp_get_module_eeprom() - Read the SFP module EEPROM |
512 | * @bus: a pointer to the &struct sfp_bus structure for the sfp module |
513 | * @ee: a &struct ethtool_eeprom |
514 | * @data: buffer to contain the EEPROM data (must be at least @ee->len bytes) |
515 | * |
516 | * Read the EEPROM as specified by the supplied @ee. See the documentation |
517 | * for &struct ethtool_eeprom for the region to be read. |
518 | * |
519 | * Returns 0 on success or a negative errno number. |
520 | */ |
521 | int sfp_get_module_eeprom(struct sfp_bus *bus, struct ethtool_eeprom *ee, |
522 | u8 *data) |
523 | { |
524 | return bus->socket_ops->module_eeprom(bus->sfp, ee, data); |
525 | } |
526 | EXPORT_SYMBOL_GPL(sfp_get_module_eeprom); |
527 | |
528 | /** |
529 | * sfp_get_module_eeprom_by_page() - Read a page from the SFP module EEPROM |
530 | * @bus: a pointer to the &struct sfp_bus structure for the sfp module |
531 | * @page: a &struct ethtool_module_eeprom |
532 | * @extack: extack for reporting problems |
533 | * |
534 | * Read an EEPROM page as specified by the supplied @page. See the |
535 | * documentation for &struct ethtool_module_eeprom for the page to be read. |
536 | * |
537 | * Returns 0 on success or a negative errno number. More error |
538 | * information might be provided via extack |
539 | */ |
540 | int sfp_get_module_eeprom_by_page(struct sfp_bus *bus, |
541 | const struct ethtool_module_eeprom *page, |
542 | struct netlink_ext_ack *extack) |
543 | { |
544 | return bus->socket_ops->module_eeprom_by_page(bus->sfp, page, extack); |
545 | } |
546 | EXPORT_SYMBOL_GPL(sfp_get_module_eeprom_by_page); |
547 | |
548 | /** |
549 | * sfp_upstream_start() - Inform the SFP that the network device is up |
550 | * @bus: a pointer to the &struct sfp_bus structure for the sfp module |
551 | * |
552 | * Inform the SFP socket that the network device is now up, so that the |
553 | * module can be enabled by allowing TX_DISABLE to be deasserted. This |
554 | * should be called from the network device driver's &struct net_device_ops |
555 | * ndo_open() method. |
556 | */ |
557 | void sfp_upstream_start(struct sfp_bus *bus) |
558 | { |
559 | if (bus->registered) |
560 | bus->socket_ops->start(bus->sfp); |
561 | bus->started = true; |
562 | } |
563 | EXPORT_SYMBOL_GPL(sfp_upstream_start); |
564 | |
565 | /** |
566 | * sfp_upstream_stop() - Inform the SFP that the network device is down |
567 | * @bus: a pointer to the &struct sfp_bus structure for the sfp module |
568 | * |
569 | * Inform the SFP socket that the network device is now up, so that the |
570 | * module can be disabled by asserting TX_DISABLE, disabling the laser |
571 | * in optical modules. This should be called from the network device |
572 | * driver's &struct net_device_ops ndo_stop() method. |
573 | */ |
574 | void sfp_upstream_stop(struct sfp_bus *bus) |
575 | { |
576 | if (bus->registered) |
577 | bus->socket_ops->stop(bus->sfp); |
578 | bus->started = false; |
579 | } |
580 | EXPORT_SYMBOL_GPL(sfp_upstream_stop); |
581 | |
582 | static void sfp_upstream_clear(struct sfp_bus *bus) |
583 | { |
584 | bus->upstream_ops = NULL; |
585 | bus->upstream = NULL; |
586 | } |
587 | |
588 | /** |
589 | * sfp_upstream_set_signal_rate() - set data signalling rate |
590 | * @bus: a pointer to the &struct sfp_bus structure for the sfp module |
591 | * @rate_kbd: signalling rate in units of 1000 baud |
592 | * |
593 | * Configure the rate select settings on the SFP module for the signalling |
594 | * rate (not the same as the data rate). |
595 | * |
596 | * Locks that may be held: |
597 | * Phylink's state_mutex |
598 | * rtnl lock |
599 | * SFP's sm_mutex |
600 | */ |
601 | void sfp_upstream_set_signal_rate(struct sfp_bus *bus, unsigned int rate_kbd) |
602 | { |
603 | if (bus->registered) |
604 | bus->socket_ops->set_signal_rate(bus->sfp, rate_kbd); |
605 | } |
606 | EXPORT_SYMBOL_GPL(sfp_upstream_set_signal_rate); |
607 | |
608 | /** |
609 | * sfp_bus_find_fwnode() - parse and locate the SFP bus from fwnode |
610 | * @fwnode: firmware node for the parent device (MAC or PHY) |
611 | * |
612 | * Parse the parent device's firmware node for a SFP bus, and locate |
613 | * the sfp_bus structure, incrementing its reference count. This must |
614 | * be put via sfp_bus_put() when done. |
615 | * |
616 | * Returns: |
617 | * - on success, a pointer to the sfp_bus structure, |
618 | * - %NULL if no SFP is specified, |
619 | * - on failure, an error pointer value: |
620 | * |
621 | * - corresponding to the errors detailed for |
622 | * fwnode_property_get_reference_args(). |
623 | * - %-ENOMEM if we failed to allocate the bus. |
624 | * - an error from the upstream's connect_phy() method. |
625 | */ |
626 | struct sfp_bus *sfp_bus_find_fwnode(const struct fwnode_handle *fwnode) |
627 | { |
628 | struct fwnode_reference_args ref; |
629 | struct sfp_bus *bus; |
630 | int ret; |
631 | |
632 | ret = fwnode_property_get_reference_args(fwnode, prop: "sfp" , NULL, |
633 | nargs: 0, index: 0, args: &ref); |
634 | if (ret == -ENOENT) |
635 | return NULL; |
636 | else if (ret < 0) |
637 | return ERR_PTR(error: ret); |
638 | |
639 | if (!fwnode_device_is_available(fwnode: ref.fwnode)) { |
640 | fwnode_handle_put(fwnode: ref.fwnode); |
641 | return NULL; |
642 | } |
643 | |
644 | bus = sfp_bus_get(fwnode: ref.fwnode); |
645 | fwnode_handle_put(fwnode: ref.fwnode); |
646 | if (!bus) |
647 | return ERR_PTR(error: -ENOMEM); |
648 | |
649 | return bus; |
650 | } |
651 | EXPORT_SYMBOL_GPL(sfp_bus_find_fwnode); |
652 | |
653 | /** |
654 | * sfp_bus_add_upstream() - parse and register the neighbouring device |
655 | * @bus: the &struct sfp_bus found via sfp_bus_find_fwnode() |
656 | * @upstream: the upstream private data |
657 | * @ops: the upstream's &struct sfp_upstream_ops |
658 | * |
659 | * Add upstream driver for the SFP bus, and if the bus is complete, register |
660 | * the SFP bus using sfp_register_upstream(). This takes a reference on the |
661 | * bus, so it is safe to put the bus after this call. |
662 | * |
663 | * Returns: |
664 | * - on success, a pointer to the sfp_bus structure, |
665 | * - %NULL if no SFP is specified, |
666 | * - on failure, an error pointer value: |
667 | * |
668 | * - corresponding to the errors detailed for |
669 | * fwnode_property_get_reference_args(). |
670 | * - %-ENOMEM if we failed to allocate the bus. |
671 | * - an error from the upstream's connect_phy() method. |
672 | */ |
673 | int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream, |
674 | const struct sfp_upstream_ops *ops) |
675 | { |
676 | int ret; |
677 | |
678 | /* If no bus, return success */ |
679 | if (!bus) |
680 | return 0; |
681 | |
682 | rtnl_lock(); |
683 | kref_get(kref: &bus->kref); |
684 | bus->upstream_ops = ops; |
685 | bus->upstream = upstream; |
686 | |
687 | if (bus->sfp) { |
688 | ret = sfp_register_bus(bus); |
689 | if (ret) |
690 | sfp_upstream_clear(bus); |
691 | } else { |
692 | ret = 0; |
693 | } |
694 | rtnl_unlock(); |
695 | |
696 | if (ret) |
697 | sfp_bus_put(bus); |
698 | |
699 | return ret; |
700 | } |
701 | EXPORT_SYMBOL_GPL(sfp_bus_add_upstream); |
702 | |
703 | /** |
704 | * sfp_bus_del_upstream() - Delete a sfp bus |
705 | * @bus: a pointer to the &struct sfp_bus structure for the sfp module |
706 | * |
707 | * Delete a previously registered upstream connection for the SFP |
708 | * module. @bus should have been added by sfp_bus_add_upstream(). |
709 | */ |
710 | void sfp_bus_del_upstream(struct sfp_bus *bus) |
711 | { |
712 | if (bus) { |
713 | rtnl_lock(); |
714 | if (bus->sfp) |
715 | sfp_unregister_bus(bus); |
716 | sfp_upstream_clear(bus); |
717 | rtnl_unlock(); |
718 | |
719 | sfp_bus_put(bus); |
720 | } |
721 | } |
722 | EXPORT_SYMBOL_GPL(sfp_bus_del_upstream); |
723 | |
724 | /* Socket driver entry points */ |
725 | int sfp_add_phy(struct sfp_bus *bus, struct phy_device *phydev) |
726 | { |
727 | const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus); |
728 | int ret = 0; |
729 | |
730 | if (ops && ops->connect_phy) |
731 | ret = ops->connect_phy(bus->upstream, phydev); |
732 | |
733 | if (ret == 0) |
734 | bus->phydev = phydev; |
735 | |
736 | return ret; |
737 | } |
738 | EXPORT_SYMBOL_GPL(sfp_add_phy); |
739 | |
740 | void sfp_remove_phy(struct sfp_bus *bus) |
741 | { |
742 | const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus); |
743 | |
744 | if (ops && ops->disconnect_phy) |
745 | ops->disconnect_phy(bus->upstream); |
746 | bus->phydev = NULL; |
747 | } |
748 | EXPORT_SYMBOL_GPL(sfp_remove_phy); |
749 | |
750 | void sfp_link_up(struct sfp_bus *bus) |
751 | { |
752 | const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus); |
753 | |
754 | if (ops && ops->link_up) |
755 | ops->link_up(bus->upstream); |
756 | } |
757 | EXPORT_SYMBOL_GPL(sfp_link_up); |
758 | |
759 | void sfp_link_down(struct sfp_bus *bus) |
760 | { |
761 | const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus); |
762 | |
763 | if (ops && ops->link_down) |
764 | ops->link_down(bus->upstream); |
765 | } |
766 | EXPORT_SYMBOL_GPL(sfp_link_down); |
767 | |
768 | int sfp_module_insert(struct sfp_bus *bus, const struct sfp_eeprom_id *id, |
769 | const struct sfp_quirk *quirk) |
770 | { |
771 | const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus); |
772 | int ret = 0; |
773 | |
774 | bus->sfp_quirk = quirk; |
775 | |
776 | if (ops && ops->module_insert) |
777 | ret = ops->module_insert(bus->upstream, id); |
778 | |
779 | return ret; |
780 | } |
781 | EXPORT_SYMBOL_GPL(sfp_module_insert); |
782 | |
783 | void sfp_module_remove(struct sfp_bus *bus) |
784 | { |
785 | const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus); |
786 | |
787 | if (ops && ops->module_remove) |
788 | ops->module_remove(bus->upstream); |
789 | |
790 | bus->sfp_quirk = NULL; |
791 | } |
792 | EXPORT_SYMBOL_GPL(sfp_module_remove); |
793 | |
794 | int sfp_module_start(struct sfp_bus *bus) |
795 | { |
796 | const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus); |
797 | int ret = 0; |
798 | |
799 | if (ops && ops->module_start) |
800 | ret = ops->module_start(bus->upstream); |
801 | |
802 | return ret; |
803 | } |
804 | EXPORT_SYMBOL_GPL(sfp_module_start); |
805 | |
806 | void sfp_module_stop(struct sfp_bus *bus) |
807 | { |
808 | const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus); |
809 | |
810 | if (ops && ops->module_stop) |
811 | ops->module_stop(bus->upstream); |
812 | } |
813 | EXPORT_SYMBOL_GPL(sfp_module_stop); |
814 | |
815 | static void sfp_socket_clear(struct sfp_bus *bus) |
816 | { |
817 | bus->sfp_dev = NULL; |
818 | bus->sfp = NULL; |
819 | bus->socket_ops = NULL; |
820 | } |
821 | |
822 | struct sfp_bus *sfp_register_socket(struct device *dev, struct sfp *sfp, |
823 | const struct sfp_socket_ops *ops) |
824 | { |
825 | struct sfp_bus *bus = sfp_bus_get(fwnode: dev->fwnode); |
826 | int ret = 0; |
827 | |
828 | if (bus) { |
829 | rtnl_lock(); |
830 | bus->sfp_dev = dev; |
831 | bus->sfp = sfp; |
832 | bus->socket_ops = ops; |
833 | |
834 | if (bus->upstream_ops) { |
835 | ret = sfp_register_bus(bus); |
836 | if (ret) |
837 | sfp_socket_clear(bus); |
838 | } |
839 | rtnl_unlock(); |
840 | } |
841 | |
842 | if (ret) { |
843 | sfp_bus_put(bus); |
844 | bus = NULL; |
845 | } |
846 | |
847 | return bus; |
848 | } |
849 | EXPORT_SYMBOL_GPL(sfp_register_socket); |
850 | |
851 | void sfp_unregister_socket(struct sfp_bus *bus) |
852 | { |
853 | rtnl_lock(); |
854 | if (bus->upstream_ops) |
855 | sfp_unregister_bus(bus); |
856 | sfp_socket_clear(bus); |
857 | rtnl_unlock(); |
858 | |
859 | sfp_bus_put(bus); |
860 | } |
861 | EXPORT_SYMBOL_GPL(sfp_unregister_socket); |
862 | |