]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blob - drivers/net/phy/sfp-bus.c
c5398a02344050ef256bc7eaddf39bf4ff6b17a1
[mirror_ubuntu-hirsute-kernel.git] / drivers / net / phy / sfp-bus.c
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 struct fwnode_handle *fwnode;
21
22 const struct sfp_socket_ops *socket_ops;
23 struct device *sfp_dev;
24 struct sfp *sfp;
25
26 const struct sfp_upstream_ops *upstream_ops;
27 void *upstream;
28 struct phy_device *phydev;
29
30 bool registered;
31 bool started;
32 };
33
34 /**
35 * sfp_parse_port() - Parse the EEPROM base ID, setting the port type
36 * @bus: a pointer to the &struct sfp_bus structure for the sfp module
37 * @id: a pointer to the module's &struct sfp_eeprom_id
38 * @support: optional pointer to an array of unsigned long for the
39 * ethtool support mask
40 *
41 * Parse the EEPROM identification given in @id, and return one of
42 * %PORT_TP, %PORT_FIBRE or %PORT_OTHER. If @support is non-%NULL,
43 * also set the ethtool %ETHTOOL_LINK_MODE_xxx_BIT corresponding with
44 * the connector type.
45 *
46 * If the port type is not known, returns %PORT_OTHER.
47 */
48 int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
49 unsigned long *support)
50 {
51 int port;
52
53 /* port is the physical connector, set this from the connector field. */
54 switch (id->base.connector) {
55 case SFP_CONNECTOR_SC:
56 case SFP_CONNECTOR_FIBERJACK:
57 case SFP_CONNECTOR_LC:
58 case SFP_CONNECTOR_MT_RJ:
59 case SFP_CONNECTOR_MU:
60 case SFP_CONNECTOR_OPTICAL_PIGTAIL:
61 port = PORT_FIBRE;
62 break;
63
64 case SFP_CONNECTOR_RJ45:
65 port = PORT_TP;
66 break;
67
68 case SFP_CONNECTOR_COPPER_PIGTAIL:
69 port = PORT_DA;
70 break;
71
72 case SFP_CONNECTOR_UNSPEC:
73 if (id->base.e1000_base_t) {
74 port = PORT_TP;
75 break;
76 }
77 /* fallthrough */
78 case SFP_CONNECTOR_SG: /* guess */
79 case SFP_CONNECTOR_MPO_1X12:
80 case SFP_CONNECTOR_MPO_2X16:
81 case SFP_CONNECTOR_HSSDC_II:
82 case SFP_CONNECTOR_NOSEPARATE:
83 case SFP_CONNECTOR_MXC_2X16:
84 port = PORT_OTHER;
85 break;
86 default:
87 dev_warn(bus->sfp_dev, "SFP: unknown connector id 0x%02x\n",
88 id->base.connector);
89 port = PORT_OTHER;
90 break;
91 }
92
93 if (support) {
94 switch (port) {
95 case PORT_FIBRE:
96 phylink_set(support, FIBRE);
97 break;
98
99 case PORT_TP:
100 phylink_set(support, TP);
101 break;
102 }
103 }
104
105 return port;
106 }
107 EXPORT_SYMBOL_GPL(sfp_parse_port);
108
109 /**
110 * sfp_parse_support() - Parse the eeprom id for supported link modes
111 * @bus: a pointer to the &struct sfp_bus structure for the sfp module
112 * @id: a pointer to the module's &struct sfp_eeprom_id
113 * @support: pointer to an array of unsigned long for the ethtool support mask
114 *
115 * Parse the EEPROM identification information and derive the supported
116 * ethtool link modes for the module.
117 */
118 void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
119 unsigned long *support)
120 {
121 unsigned int br_min, br_nom, br_max;
122 __ETHTOOL_DECLARE_LINK_MODE_MASK(modes) = { 0, };
123
124 /* Decode the bitrate information to MBd */
125 br_min = br_nom = br_max = 0;
126 if (id->base.br_nominal) {
127 if (id->base.br_nominal != 255) {
128 br_nom = id->base.br_nominal * 100;
129 br_min = br_nom - id->base.br_nominal * id->ext.br_min;
130 br_max = br_nom + id->base.br_nominal * id->ext.br_max;
131 } else if (id->ext.br_max) {
132 br_nom = 250 * id->ext.br_max;
133 br_max = br_nom + br_nom * id->ext.br_min / 100;
134 br_min = br_nom - br_nom * id->ext.br_min / 100;
135 }
136
137 /* When using passive cables, in case neither BR,min nor BR,max
138 * are specified, set br_min to 0 as the nominal value is then
139 * used as the maximum.
140 */
141 if (br_min == br_max && id->base.sfp_ct_passive)
142 br_min = 0;
143 }
144
145 /* Set ethtool support from the compliance fields. */
146 if (id->base.e10g_base_sr)
147 phylink_set(modes, 10000baseSR_Full);
148 if (id->base.e10g_base_lr)
149 phylink_set(modes, 10000baseLR_Full);
150 if (id->base.e10g_base_lrm)
151 phylink_set(modes, 10000baseLRM_Full);
152 if (id->base.e10g_base_er)
153 phylink_set(modes, 10000baseER_Full);
154 if (id->base.e1000_base_sx ||
155 id->base.e1000_base_lx ||
156 id->base.e1000_base_cx)
157 phylink_set(modes, 1000baseX_Full);
158 if (id->base.e1000_base_t) {
159 phylink_set(modes, 1000baseT_Half);
160 phylink_set(modes, 1000baseT_Full);
161 }
162
163 /* 1000Base-PX or 1000Base-BX10 */
164 if ((id->base.e_base_px || id->base.e_base_bx10) &&
165 br_min <= 1300 && br_max >= 1200)
166 phylink_set(modes, 1000baseX_Full);
167
168 /* For active or passive cables, select the link modes
169 * based on the bit rates and the cable compliance bytes.
170 */
171 if ((id->base.sfp_ct_passive || id->base.sfp_ct_active) && br_nom) {
172 /* This may look odd, but some manufacturers use 12000MBd */
173 if (br_min <= 12000 && br_max >= 10300)
174 phylink_set(modes, 10000baseCR_Full);
175 if (br_min <= 3200 && br_max >= 3100)
176 phylink_set(modes, 2500baseX_Full);
177 if (br_min <= 1300 && br_max >= 1200)
178 phylink_set(modes, 1000baseX_Full);
179 }
180 if (id->base.sfp_ct_passive) {
181 if (id->base.passive.sff8431_app_e)
182 phylink_set(modes, 10000baseCR_Full);
183 }
184 if (id->base.sfp_ct_active) {
185 if (id->base.active.sff8431_app_e ||
186 id->base.active.sff8431_lim) {
187 phylink_set(modes, 10000baseCR_Full);
188 }
189 }
190
191 switch (id->base.extended_cc) {
192 case 0x00: /* Unspecified */
193 break;
194 case 0x02: /* 100Gbase-SR4 or 25Gbase-SR */
195 phylink_set(modes, 100000baseSR4_Full);
196 phylink_set(modes, 25000baseSR_Full);
197 break;
198 case 0x03: /* 100Gbase-LR4 or 25Gbase-LR */
199 case 0x04: /* 100Gbase-ER4 or 25Gbase-ER */
200 phylink_set(modes, 100000baseLR4_ER4_Full);
201 break;
202 case 0x0b: /* 100Gbase-CR4 or 25Gbase-CR CA-L */
203 case 0x0c: /* 25Gbase-CR CA-S */
204 case 0x0d: /* 25Gbase-CR CA-N */
205 phylink_set(modes, 100000baseCR4_Full);
206 phylink_set(modes, 25000baseCR_Full);
207 break;
208 default:
209 dev_warn(bus->sfp_dev,
210 "Unknown/unsupported extended compliance code: 0x%02x\n",
211 id->base.extended_cc);
212 break;
213 }
214
215 /* For fibre channel SFP, derive possible BaseX modes */
216 if (id->base.fc_speed_100 ||
217 id->base.fc_speed_200 ||
218 id->base.fc_speed_400) {
219 if (id->base.br_nominal >= 31)
220 phylink_set(modes, 2500baseX_Full);
221 if (id->base.br_nominal >= 12)
222 phylink_set(modes, 1000baseX_Full);
223 }
224
225 /* If we haven't discovered any modes that this module supports, try
226 * the encoding and bitrate to determine supported modes. Some BiDi
227 * modules (eg, 1310nm/1550nm) are not 1000BASE-BX compliant due to
228 * the differing wavelengths, so do not set any transceiver bits.
229 */
230 if (bitmap_empty(modes, __ETHTOOL_LINK_MODE_MASK_NBITS)) {
231 /* If the encoding and bit rate allows 1000baseX */
232 if (id->base.encoding == SFP_ENCODING_8B10B && br_nom &&
233 br_min <= 1300 && br_max >= 1200)
234 phylink_set(modes, 1000baseX_Full);
235 }
236
237 bitmap_or(support, support, modes, __ETHTOOL_LINK_MODE_MASK_NBITS);
238
239 phylink_set(support, Autoneg);
240 phylink_set(support, Pause);
241 phylink_set(support, Asym_Pause);
242 }
243 EXPORT_SYMBOL_GPL(sfp_parse_support);
244
245 /**
246 * sfp_select_interface() - Select appropriate phy_interface_t mode
247 * @bus: a pointer to the &struct sfp_bus structure for the sfp module
248 * @id: a pointer to the module's &struct sfp_eeprom_id
249 * @link_modes: ethtool link modes mask
250 *
251 * Derive the phy_interface_t mode for the information found in the
252 * module's identifying EEPROM and the link modes mask. There is no
253 * standard or defined way to derive this information, so we decide
254 * based upon the link mode mask.
255 */
256 phy_interface_t sfp_select_interface(struct sfp_bus *bus,
257 const struct sfp_eeprom_id *id,
258 unsigned long *link_modes)
259 {
260 if (phylink_test(link_modes, 10000baseCR_Full) ||
261 phylink_test(link_modes, 10000baseSR_Full) ||
262 phylink_test(link_modes, 10000baseLR_Full) ||
263 phylink_test(link_modes, 10000baseLRM_Full) ||
264 phylink_test(link_modes, 10000baseER_Full))
265 return PHY_INTERFACE_MODE_10GKR;
266
267 if (phylink_test(link_modes, 2500baseX_Full))
268 return PHY_INTERFACE_MODE_2500BASEX;
269
270 if (id->base.e1000_base_t ||
271 id->base.e100_base_lx ||
272 id->base.e100_base_fx)
273 return PHY_INTERFACE_MODE_SGMII;
274
275 if (phylink_test(link_modes, 1000baseX_Full))
276 return PHY_INTERFACE_MODE_1000BASEX;
277
278 dev_warn(bus->sfp_dev, "Unable to ascertain link mode\n");
279
280 return PHY_INTERFACE_MODE_NA;
281 }
282 EXPORT_SYMBOL_GPL(sfp_select_interface);
283
284 static LIST_HEAD(sfp_buses);
285 static DEFINE_MUTEX(sfp_mutex);
286
287 static const struct sfp_upstream_ops *sfp_get_upstream_ops(struct sfp_bus *bus)
288 {
289 return bus->registered ? bus->upstream_ops : NULL;
290 }
291
292 static struct sfp_bus *sfp_bus_get(struct fwnode_handle *fwnode)
293 {
294 struct sfp_bus *sfp, *new, *found = NULL;
295
296 new = kzalloc(sizeof(*new), GFP_KERNEL);
297
298 mutex_lock(&sfp_mutex);
299
300 list_for_each_entry(sfp, &sfp_buses, node) {
301 if (sfp->fwnode == fwnode) {
302 kref_get(&sfp->kref);
303 found = sfp;
304 break;
305 }
306 }
307
308 if (!found && new) {
309 kref_init(&new->kref);
310 new->fwnode = fwnode;
311 list_add(&new->node, &sfp_buses);
312 found = new;
313 new = NULL;
314 }
315
316 mutex_unlock(&sfp_mutex);
317
318 kfree(new);
319
320 return found;
321 }
322
323 static void sfp_bus_release(struct kref *kref)
324 {
325 struct sfp_bus *bus = container_of(kref, struct sfp_bus, kref);
326
327 list_del(&bus->node);
328 mutex_unlock(&sfp_mutex);
329 kfree(bus);
330 }
331
332 /**
333 * sfp_bus_put() - put a reference on the &struct sfp_bus
334 * @bus: the &struct sfp_bus found via sfp_bus_find_fwnode()
335 *
336 * Put a reference on the &struct sfp_bus and free the underlying structure
337 * if this was the last reference.
338 */
339 void sfp_bus_put(struct sfp_bus *bus)
340 {
341 if (bus)
342 kref_put_mutex(&bus->kref, sfp_bus_release, &sfp_mutex);
343 }
344 EXPORT_SYMBOL_GPL(sfp_bus_put);
345
346 static int sfp_register_bus(struct sfp_bus *bus)
347 {
348 const struct sfp_upstream_ops *ops = bus->upstream_ops;
349 int ret;
350
351 if (ops) {
352 if (ops->link_down)
353 ops->link_down(bus->upstream);
354 if (ops->connect_phy && bus->phydev) {
355 ret = ops->connect_phy(bus->upstream, bus->phydev);
356 if (ret)
357 return ret;
358 }
359 }
360 bus->registered = true;
361 bus->socket_ops->attach(bus->sfp);
362 if (bus->started)
363 bus->socket_ops->start(bus->sfp);
364 bus->upstream_ops->attach(bus->upstream, bus);
365 return 0;
366 }
367
368 static void sfp_unregister_bus(struct sfp_bus *bus)
369 {
370 const struct sfp_upstream_ops *ops = bus->upstream_ops;
371
372 if (bus->registered) {
373 bus->upstream_ops->detach(bus->upstream, bus);
374 if (bus->started)
375 bus->socket_ops->stop(bus->sfp);
376 bus->socket_ops->detach(bus->sfp);
377 if (bus->phydev && ops && ops->disconnect_phy)
378 ops->disconnect_phy(bus->upstream);
379 }
380 bus->registered = false;
381 }
382
383 /**
384 * sfp_get_module_info() - Get the ethtool_modinfo for a SFP module
385 * @bus: a pointer to the &struct sfp_bus structure for the sfp module
386 * @modinfo: a &struct ethtool_modinfo
387 *
388 * Fill in the type and eeprom_len parameters in @modinfo for a module on
389 * the sfp bus specified by @bus.
390 *
391 * Returns 0 on success or a negative errno number.
392 */
393 int sfp_get_module_info(struct sfp_bus *bus, struct ethtool_modinfo *modinfo)
394 {
395 return bus->socket_ops->module_info(bus->sfp, modinfo);
396 }
397 EXPORT_SYMBOL_GPL(sfp_get_module_info);
398
399 /**
400 * sfp_get_module_eeprom() - Read the SFP module EEPROM
401 * @bus: a pointer to the &struct sfp_bus structure for the sfp module
402 * @ee: a &struct ethtool_eeprom
403 * @data: buffer to contain the EEPROM data (must be at least @ee->len bytes)
404 *
405 * Read the EEPROM as specified by the supplied @ee. See the documentation
406 * for &struct ethtool_eeprom for the region to be read.
407 *
408 * Returns 0 on success or a negative errno number.
409 */
410 int sfp_get_module_eeprom(struct sfp_bus *bus, struct ethtool_eeprom *ee,
411 u8 *data)
412 {
413 return bus->socket_ops->module_eeprom(bus->sfp, ee, data);
414 }
415 EXPORT_SYMBOL_GPL(sfp_get_module_eeprom);
416
417 /**
418 * sfp_upstream_start() - Inform the SFP that the network device is up
419 * @bus: a pointer to the &struct sfp_bus structure for the sfp module
420 *
421 * Inform the SFP socket that the network device is now up, so that the
422 * module can be enabled by allowing TX_DISABLE to be deasserted. This
423 * should be called from the network device driver's &struct net_device_ops
424 * ndo_open() method.
425 */
426 void sfp_upstream_start(struct sfp_bus *bus)
427 {
428 if (bus->registered)
429 bus->socket_ops->start(bus->sfp);
430 bus->started = true;
431 }
432 EXPORT_SYMBOL_GPL(sfp_upstream_start);
433
434 /**
435 * sfp_upstream_stop() - Inform the SFP that the network device is down
436 * @bus: a pointer to the &struct sfp_bus structure for the sfp module
437 *
438 * Inform the SFP socket that the network device is now up, so that the
439 * module can be disabled by asserting TX_DISABLE, disabling the laser
440 * in optical modules. This should be called from the network device
441 * driver's &struct net_device_ops ndo_stop() method.
442 */
443 void sfp_upstream_stop(struct sfp_bus *bus)
444 {
445 if (bus->registered)
446 bus->socket_ops->stop(bus->sfp);
447 bus->started = false;
448 }
449 EXPORT_SYMBOL_GPL(sfp_upstream_stop);
450
451 static void sfp_upstream_clear(struct sfp_bus *bus)
452 {
453 bus->upstream_ops = NULL;
454 bus->upstream = NULL;
455 }
456
457 /**
458 * sfp_bus_find_fwnode() - parse and locate the SFP bus from fwnode
459 * @fwnode: firmware node for the parent device (MAC or PHY)
460 *
461 * Parse the parent device's firmware node for a SFP bus, and locate
462 * the sfp_bus structure, incrementing its reference count. This must
463 * be put via sfp_bus_put() when done.
464 *
465 * Returns: on success, a pointer to the sfp_bus structure,
466 * %NULL if no SFP is specified,
467 * on failure, an error pointer value:
468 * corresponding to the errors detailed for
469 * fwnode_property_get_reference_args().
470 * %-ENOMEM if we failed to allocate the bus.
471 * an error from the upstream's connect_phy() method.
472 */
473 struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode)
474 {
475 struct fwnode_reference_args ref;
476 struct sfp_bus *bus;
477 int ret;
478
479 ret = fwnode_property_get_reference_args(fwnode, "sfp", NULL,
480 0, 0, &ref);
481 if (ret == -ENOENT)
482 return NULL;
483 else if (ret < 0)
484 return ERR_PTR(ret);
485
486 bus = sfp_bus_get(ref.fwnode);
487 fwnode_handle_put(ref.fwnode);
488 if (!bus)
489 return ERR_PTR(-ENOMEM);
490
491 return bus;
492 }
493 EXPORT_SYMBOL_GPL(sfp_bus_find_fwnode);
494
495 /**
496 * sfp_bus_add_upstream() - parse and register the neighbouring device
497 * @bus: the &struct sfp_bus found via sfp_bus_find_fwnode()
498 * @upstream: the upstream private data
499 * @ops: the upstream's &struct sfp_upstream_ops
500 *
501 * Add upstream driver for the SFP bus, and if the bus is complete, register
502 * the SFP bus using sfp_register_upstream(). This takes a reference on the
503 * bus, so it is safe to put the bus after this call.
504 *
505 * Returns: on success, a pointer to the sfp_bus structure,
506 * %NULL if no SFP is specified,
507 * on failure, an error pointer value:
508 * corresponding to the errors detailed for
509 * fwnode_property_get_reference_args().
510 * %-ENOMEM if we failed to allocate the bus.
511 * an error from the upstream's connect_phy() method.
512 */
513 int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream,
514 const struct sfp_upstream_ops *ops)
515 {
516 int ret;
517
518 /* If no bus, return success */
519 if (!bus)
520 return 0;
521
522 rtnl_lock();
523 kref_get(&bus->kref);
524 bus->upstream_ops = ops;
525 bus->upstream = upstream;
526
527 if (bus->sfp) {
528 ret = sfp_register_bus(bus);
529 if (ret)
530 sfp_upstream_clear(bus);
531 } else {
532 ret = 0;
533 }
534 rtnl_unlock();
535
536 if (ret)
537 sfp_bus_put(bus);
538
539 return ret;
540 }
541 EXPORT_SYMBOL_GPL(sfp_bus_add_upstream);
542
543 /**
544 * sfp_bus_del_upstream() - Delete a sfp bus
545 * @bus: a pointer to the &struct sfp_bus structure for the sfp module
546 *
547 * Delete a previously registered upstream connection for the SFP
548 * module. @bus should have been added by sfp_bus_add_upstream().
549 */
550 void sfp_bus_del_upstream(struct sfp_bus *bus)
551 {
552 if (bus) {
553 rtnl_lock();
554 if (bus->sfp)
555 sfp_unregister_bus(bus);
556 sfp_upstream_clear(bus);
557 rtnl_unlock();
558
559 sfp_bus_put(bus);
560 }
561 }
562 EXPORT_SYMBOL_GPL(sfp_bus_del_upstream);
563
564 /* Socket driver entry points */
565 int sfp_add_phy(struct sfp_bus *bus, struct phy_device *phydev)
566 {
567 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
568 int ret = 0;
569
570 if (ops && ops->connect_phy)
571 ret = ops->connect_phy(bus->upstream, phydev);
572
573 if (ret == 0)
574 bus->phydev = phydev;
575
576 return ret;
577 }
578 EXPORT_SYMBOL_GPL(sfp_add_phy);
579
580 void sfp_remove_phy(struct sfp_bus *bus)
581 {
582 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
583
584 if (ops && ops->disconnect_phy)
585 ops->disconnect_phy(bus->upstream);
586 bus->phydev = NULL;
587 }
588 EXPORT_SYMBOL_GPL(sfp_remove_phy);
589
590 void sfp_link_up(struct sfp_bus *bus)
591 {
592 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
593
594 if (ops && ops->link_up)
595 ops->link_up(bus->upstream);
596 }
597 EXPORT_SYMBOL_GPL(sfp_link_up);
598
599 void sfp_link_down(struct sfp_bus *bus)
600 {
601 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
602
603 if (ops && ops->link_down)
604 ops->link_down(bus->upstream);
605 }
606 EXPORT_SYMBOL_GPL(sfp_link_down);
607
608 int sfp_module_insert(struct sfp_bus *bus, const struct sfp_eeprom_id *id)
609 {
610 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
611 int ret = 0;
612
613 if (ops && ops->module_insert)
614 ret = ops->module_insert(bus->upstream, id);
615
616 return ret;
617 }
618 EXPORT_SYMBOL_GPL(sfp_module_insert);
619
620 void sfp_module_remove(struct sfp_bus *bus)
621 {
622 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
623
624 if (ops && ops->module_remove)
625 ops->module_remove(bus->upstream);
626 }
627 EXPORT_SYMBOL_GPL(sfp_module_remove);
628
629 static void sfp_socket_clear(struct sfp_bus *bus)
630 {
631 bus->sfp_dev = NULL;
632 bus->sfp = NULL;
633 bus->socket_ops = NULL;
634 }
635
636 struct sfp_bus *sfp_register_socket(struct device *dev, struct sfp *sfp,
637 const struct sfp_socket_ops *ops)
638 {
639 struct sfp_bus *bus = sfp_bus_get(dev->fwnode);
640 int ret = 0;
641
642 if (bus) {
643 rtnl_lock();
644 bus->sfp_dev = dev;
645 bus->sfp = sfp;
646 bus->socket_ops = ops;
647
648 if (bus->upstream_ops) {
649 ret = sfp_register_bus(bus);
650 if (ret)
651 sfp_socket_clear(bus);
652 }
653 rtnl_unlock();
654 }
655
656 if (ret) {
657 sfp_bus_put(bus);
658 bus = NULL;
659 }
660
661 return bus;
662 }
663 EXPORT_SYMBOL_GPL(sfp_register_socket);
664
665 void sfp_unregister_socket(struct sfp_bus *bus)
666 {
667 rtnl_lock();
668 if (bus->upstream_ops)
669 sfp_unregister_bus(bus);
670 sfp_socket_clear(bus);
671 rtnl_unlock();
672
673 sfp_bus_put(bus);
674 }
675 EXPORT_SYMBOL_GPL(sfp_unregister_socket);