Lines Matching +full:bus +full:- +full:id
1 // SPDX-License-Identifier: GPL-2.0-only
16 void (*modes)(const struct sfp_eeprom_id *id, unsigned long *modes);
20 * struct sfp_bus - internal representation of a sfp bus
41 static void sfp_quirk_2500basex(const struct sfp_eeprom_id *id, in sfp_quirk_2500basex() argument
47 static void sfp_quirk_ubnt_uf_instant(const struct sfp_eeprom_id *id, in sfp_quirk_ubnt_uf_instant() argument
50 /* Ubiquiti U-Fiber Instant module claims that support all transceiver in sfp_quirk_ubnt_uf_instant()
60 // Alcatel Lucent G-010S-P can operate at 2500base-X, but
66 // Alcatel Lucent G-010S-A can operate at 2500base-X, but
72 // Huawei MA5671A can operate at 2500base-X, but report 1.2GBd
78 // Lantech 8330-262D-E can operate at 2500base-X, but
81 .part = "8330-262D-E",
85 .part = "UF-INSTANT",
111 static const struct sfp_quirk *sfp_lookup_quirk(const struct sfp_eeprom_id *id) in sfp_lookup_quirk() argument
117 vs = sfp_strlen(id->base.vendor_name, ARRAY_SIZE(id->base.vendor_name)); in sfp_lookup_quirk()
118 ps = sfp_strlen(id->base.vendor_pn, ARRAY_SIZE(id->base.vendor_pn)); in sfp_lookup_quirk()
121 if (sfp_match(q->vendor, id->base.vendor_name, vs) && in sfp_lookup_quirk()
122 sfp_match(q->part, id->base.vendor_pn, ps)) in sfp_lookup_quirk()
129 * sfp_parse_port() - Parse the EEPROM base ID, setting the port type
130 * @bus: a pointer to the &struct sfp_bus structure for the sfp module
131 * @id: a pointer to the module's &struct sfp_eeprom_id
135 * Parse the EEPROM identification given in @id, and return one of
136 * %PORT_TP, %PORT_FIBRE or %PORT_OTHER. If @support is non-%NULL,
142 int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id, in sfp_parse_port() argument
148 switch (id->base.connector) { in sfp_parse_port()
169 if (id->base.e1000_base_t) { in sfp_parse_port()
181 dev_warn(bus->sfp_dev, "SFP: unknown connector id 0x%02x\n", in sfp_parse_port()
182 id->base.connector); in sfp_parse_port()
204 * sfp_may_have_phy() - indicate whether the module may have a PHY
205 * @bus: a pointer to the &struct sfp_bus structure for the sfp module
206 * @id: a pointer to the module's &struct sfp_eeprom_id
208 * Parse the EEPROM identification given in @id, and return whether
211 bool sfp_may_have_phy(struct sfp_bus *bus, const struct sfp_eeprom_id *id) in sfp_may_have_phy() argument
213 if (id->base.e1000_base_t) in sfp_may_have_phy()
216 if (id->base.phys_id != SFF8024_ID_DWDM_SFP) { in sfp_may_have_phy()
217 switch (id->base.extended_cc) { in sfp_may_have_phy()
231 * sfp_parse_support() - Parse the eeprom id for supported link modes
232 * @bus: a pointer to the &struct sfp_bus structure for the sfp module
233 * @id: a pointer to the module's &struct sfp_eeprom_id
239 void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id, in sfp_parse_support() argument
247 if (id->base.br_nominal) { in sfp_parse_support()
248 if (id->base.br_nominal != 255) { in sfp_parse_support()
249 br_nom = id->base.br_nominal * 100; in sfp_parse_support()
250 br_min = br_nom - id->base.br_nominal * id->ext.br_min; in sfp_parse_support()
251 br_max = br_nom + id->base.br_nominal * id->ext.br_max; in sfp_parse_support()
252 } else if (id->ext.br_max) { in sfp_parse_support()
253 br_nom = 250 * id->ext.br_max; in sfp_parse_support()
254 br_max = br_nom + br_nom * id->ext.br_min / 100; in sfp_parse_support()
255 br_min = br_nom - br_nom * id->ext.br_min / 100; in sfp_parse_support()
262 if (br_min == br_max && id->base.sfp_ct_passive) in sfp_parse_support()
267 if (id->base.e10g_base_sr) in sfp_parse_support()
269 if (id->base.e10g_base_lr) in sfp_parse_support()
271 if (id->base.e10g_base_lrm) in sfp_parse_support()
273 if (id->base.e10g_base_er) in sfp_parse_support()
275 if (id->base.e1000_base_sx || in sfp_parse_support()
276 id->base.e1000_base_lx || in sfp_parse_support()
277 id->base.e1000_base_cx) in sfp_parse_support()
279 if (id->base.e1000_base_t) { in sfp_parse_support()
284 /* 1000Base-PX or 1000Base-BX10 */ in sfp_parse_support()
285 if ((id->base.e_base_px || id->base.e_base_bx10) && in sfp_parse_support()
292 if ((id->base.sfp_ct_passive || id->base.sfp_ct_active) && br_nom) { in sfp_parse_support()
301 if (id->base.sfp_ct_passive) { in sfp_parse_support()
302 if (id->base.passive.sff8431_app_e) in sfp_parse_support()
305 if (id->base.sfp_ct_active) { in sfp_parse_support()
306 if (id->base.active.sff8431_app_e || in sfp_parse_support()
307 id->base.active.sff8431_lim) { in sfp_parse_support()
312 switch (id->base.extended_cc) { in sfp_parse_support()
341 dev_warn(bus->sfp_dev, in sfp_parse_support()
343 id->base.extended_cc); in sfp_parse_support()
348 if (id->base.fc_speed_100 || in sfp_parse_support()
349 id->base.fc_speed_200 || in sfp_parse_support()
350 id->base.fc_speed_400) { in sfp_parse_support()
351 if (id->base.br_nominal >= 31) in sfp_parse_support()
353 if (id->base.br_nominal >= 12) in sfp_parse_support()
359 * 1310nm/1550nm) are not 1000BASE-BX compliant due to the differing in sfp_parse_support()
368 if (bus->sfp_quirk) in sfp_parse_support()
369 bus->sfp_quirk->modes(id, modes); in sfp_parse_support()
380 * sfp_select_interface() - Select appropriate phy_interface_t mode
381 * @bus: a pointer to the &struct sfp_bus structure for the sfp module
387 phy_interface_t sfp_select_interface(struct sfp_bus *bus, in sfp_select_interface() argument
408 dev_warn(bus->sfp_dev, "Unable to ascertain link mode\n"); in sfp_select_interface()
417 static const struct sfp_upstream_ops *sfp_get_upstream_ops(struct sfp_bus *bus) in sfp_get_upstream_ops() argument
419 return bus->registered ? bus->upstream_ops : NULL; in sfp_get_upstream_ops()
431 if (sfp->fwnode == fwnode) { in sfp_bus_get()
432 kref_get(&sfp->kref); in sfp_bus_get()
439 kref_init(&new->kref); in sfp_bus_get()
440 new->fwnode = fwnode; in sfp_bus_get()
441 list_add(&new->node, &sfp_buses); in sfp_bus_get()
455 struct sfp_bus *bus = container_of(kref, struct sfp_bus, kref); in sfp_bus_release() local
457 list_del(&bus->node); in sfp_bus_release()
459 kfree(bus); in sfp_bus_release()
463 * sfp_bus_put() - put a reference on the &struct sfp_bus
464 * @bus: the &struct sfp_bus found via sfp_bus_find_fwnode()
469 void sfp_bus_put(struct sfp_bus *bus) in sfp_bus_put() argument
471 if (bus) in sfp_bus_put()
472 kref_put_mutex(&bus->kref, sfp_bus_release, &sfp_mutex); in sfp_bus_put()
476 static int sfp_register_bus(struct sfp_bus *bus) in sfp_register_bus() argument
478 const struct sfp_upstream_ops *ops = bus->upstream_ops; in sfp_register_bus()
482 if (ops->link_down) in sfp_register_bus()
483 ops->link_down(bus->upstream); in sfp_register_bus()
484 if (ops->connect_phy && bus->phydev) { in sfp_register_bus()
485 ret = ops->connect_phy(bus->upstream, bus->phydev); in sfp_register_bus()
490 bus->registered = true; in sfp_register_bus()
491 bus->socket_ops->attach(bus->sfp); in sfp_register_bus()
492 if (bus->started) in sfp_register_bus()
493 bus->socket_ops->start(bus->sfp); in sfp_register_bus()
494 bus->upstream_ops->attach(bus->upstream, bus); in sfp_register_bus()
498 static void sfp_unregister_bus(struct sfp_bus *bus) in sfp_unregister_bus() argument
500 const struct sfp_upstream_ops *ops = bus->upstream_ops; in sfp_unregister_bus()
502 if (bus->registered) { in sfp_unregister_bus()
503 bus->upstream_ops->detach(bus->upstream, bus); in sfp_unregister_bus()
504 if (bus->started) in sfp_unregister_bus()
505 bus->socket_ops->stop(bus->sfp); in sfp_unregister_bus()
506 bus->socket_ops->detach(bus->sfp); in sfp_unregister_bus()
507 if (bus->phydev && ops && ops->disconnect_phy) in sfp_unregister_bus()
508 ops->disconnect_phy(bus->upstream); in sfp_unregister_bus()
510 bus->registered = false; in sfp_unregister_bus()
514 * sfp_get_module_info() - Get the ethtool_modinfo for a SFP module
515 * @bus: a pointer to the &struct sfp_bus structure for the sfp module
519 * the sfp bus specified by @bus.
523 int sfp_get_module_info(struct sfp_bus *bus, struct ethtool_modinfo *modinfo) in sfp_get_module_info() argument
525 return bus->socket_ops->module_info(bus->sfp, modinfo); in sfp_get_module_info()
530 * sfp_get_module_eeprom() - Read the SFP module EEPROM
531 * @bus: a pointer to the &struct sfp_bus structure for the sfp module
533 * @data: buffer to contain the EEPROM data (must be at least @ee->len bytes)
540 int sfp_get_module_eeprom(struct sfp_bus *bus, struct ethtool_eeprom *ee, in sfp_get_module_eeprom() argument
543 return bus->socket_ops->module_eeprom(bus->sfp, ee, data); in sfp_get_module_eeprom()
548 * sfp_upstream_start() - Inform the SFP that the network device is up
549 * @bus: a pointer to the &struct sfp_bus structure for the sfp module
556 void sfp_upstream_start(struct sfp_bus *bus) in sfp_upstream_start() argument
558 if (bus->registered) in sfp_upstream_start()
559 bus->socket_ops->start(bus->sfp); in sfp_upstream_start()
560 bus->started = true; in sfp_upstream_start()
565 * sfp_upstream_stop() - Inform the SFP that the network device is down
566 * @bus: a pointer to the &struct sfp_bus structure for the sfp module
573 void sfp_upstream_stop(struct sfp_bus *bus) in sfp_upstream_stop() argument
575 if (bus->registered) in sfp_upstream_stop()
576 bus->socket_ops->stop(bus->sfp); in sfp_upstream_stop()
577 bus->started = false; in sfp_upstream_stop()
581 static void sfp_upstream_clear(struct sfp_bus *bus) in sfp_upstream_clear() argument
583 bus->upstream_ops = NULL; in sfp_upstream_clear()
584 bus->upstream = NULL; in sfp_upstream_clear()
588 * sfp_bus_find_fwnode() - parse and locate the SFP bus from fwnode
591 * Parse the parent device's firmware node for a SFP bus, and locate
596 * - on success, a pointer to the sfp_bus structure,
597 * - %NULL if no SFP is specified,
598 * - on failure, an error pointer value:
600 * - corresponding to the errors detailed for
602 * - %-ENOMEM if we failed to allocate the bus.
603 * - an error from the upstream's connect_phy() method.
608 struct sfp_bus *bus; in sfp_bus_find_fwnode() local
613 if (ret == -ENOENT) in sfp_bus_find_fwnode()
623 bus = sfp_bus_get(ref.fwnode); in sfp_bus_find_fwnode()
625 if (!bus) in sfp_bus_find_fwnode()
626 return ERR_PTR(-ENOMEM); in sfp_bus_find_fwnode()
628 return bus; in sfp_bus_find_fwnode()
633 * sfp_bus_add_upstream() - parse and register the neighbouring device
634 * @bus: the &struct sfp_bus found via sfp_bus_find_fwnode()
638 * Add upstream driver for the SFP bus, and if the bus is complete, register
639 * the SFP bus using sfp_register_upstream(). This takes a reference on the
640 * bus, so it is safe to put the bus after this call.
643 * - on success, a pointer to the sfp_bus structure,
644 * - %NULL if no SFP is specified,
645 * - on failure, an error pointer value:
647 * - corresponding to the errors detailed for
649 * - %-ENOMEM if we failed to allocate the bus.
650 * - an error from the upstream's connect_phy() method.
652 int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream, in sfp_bus_add_upstream() argument
657 /* If no bus, return success */ in sfp_bus_add_upstream()
658 if (!bus) in sfp_bus_add_upstream()
662 kref_get(&bus->kref); in sfp_bus_add_upstream()
663 bus->upstream_ops = ops; in sfp_bus_add_upstream()
664 bus->upstream = upstream; in sfp_bus_add_upstream()
666 if (bus->sfp) { in sfp_bus_add_upstream()
667 ret = sfp_register_bus(bus); in sfp_bus_add_upstream()
669 sfp_upstream_clear(bus); in sfp_bus_add_upstream()
676 sfp_bus_put(bus); in sfp_bus_add_upstream()
683 * sfp_bus_del_upstream() - Delete a sfp bus
684 * @bus: a pointer to the &struct sfp_bus structure for the sfp module
687 * module. @bus should have been added by sfp_bus_add_upstream().
689 void sfp_bus_del_upstream(struct sfp_bus *bus) in sfp_bus_del_upstream() argument
691 if (bus) { in sfp_bus_del_upstream()
693 if (bus->sfp) in sfp_bus_del_upstream()
694 sfp_unregister_bus(bus); in sfp_bus_del_upstream()
695 sfp_upstream_clear(bus); in sfp_bus_del_upstream()
698 sfp_bus_put(bus); in sfp_bus_del_upstream()
704 int sfp_add_phy(struct sfp_bus *bus, struct phy_device *phydev) in sfp_add_phy() argument
706 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus); in sfp_add_phy()
709 if (ops && ops->connect_phy) in sfp_add_phy()
710 ret = ops->connect_phy(bus->upstream, phydev); in sfp_add_phy()
713 bus->phydev = phydev; in sfp_add_phy()
719 void sfp_remove_phy(struct sfp_bus *bus) in sfp_remove_phy() argument
721 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus); in sfp_remove_phy()
723 if (ops && ops->disconnect_phy) in sfp_remove_phy()
724 ops->disconnect_phy(bus->upstream); in sfp_remove_phy()
725 bus->phydev = NULL; in sfp_remove_phy()
729 void sfp_link_up(struct sfp_bus *bus) in sfp_link_up() argument
731 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus); in sfp_link_up()
733 if (ops && ops->link_up) in sfp_link_up()
734 ops->link_up(bus->upstream); in sfp_link_up()
738 void sfp_link_down(struct sfp_bus *bus) in sfp_link_down() argument
740 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus); in sfp_link_down()
742 if (ops && ops->link_down) in sfp_link_down()
743 ops->link_down(bus->upstream); in sfp_link_down()
747 int sfp_module_insert(struct sfp_bus *bus, const struct sfp_eeprom_id *id) in sfp_module_insert() argument
749 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus); in sfp_module_insert()
752 bus->sfp_quirk = sfp_lookup_quirk(id); in sfp_module_insert()
754 if (ops && ops->module_insert) in sfp_module_insert()
755 ret = ops->module_insert(bus->upstream, id); in sfp_module_insert()
761 void sfp_module_remove(struct sfp_bus *bus) in sfp_module_remove() argument
763 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus); in sfp_module_remove()
765 if (ops && ops->module_remove) in sfp_module_remove()
766 ops->module_remove(bus->upstream); in sfp_module_remove()
768 bus->sfp_quirk = NULL; in sfp_module_remove()
772 int sfp_module_start(struct sfp_bus *bus) in sfp_module_start() argument
774 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus); in sfp_module_start()
777 if (ops && ops->module_start) in sfp_module_start()
778 ret = ops->module_start(bus->upstream); in sfp_module_start()
784 void sfp_module_stop(struct sfp_bus *bus) in sfp_module_stop() argument
786 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus); in sfp_module_stop()
788 if (ops && ops->module_stop) in sfp_module_stop()
789 ops->module_stop(bus->upstream); in sfp_module_stop()
793 static void sfp_socket_clear(struct sfp_bus *bus) in sfp_socket_clear() argument
795 bus->sfp_dev = NULL; in sfp_socket_clear()
796 bus->sfp = NULL; in sfp_socket_clear()
797 bus->socket_ops = NULL; in sfp_socket_clear()
803 struct sfp_bus *bus = sfp_bus_get(dev->fwnode); in sfp_register_socket() local
806 if (bus) { in sfp_register_socket()
808 bus->sfp_dev = dev; in sfp_register_socket()
809 bus->sfp = sfp; in sfp_register_socket()
810 bus->socket_ops = ops; in sfp_register_socket()
812 if (bus->upstream_ops) { in sfp_register_socket()
813 ret = sfp_register_bus(bus); in sfp_register_socket()
815 sfp_socket_clear(bus); in sfp_register_socket()
821 sfp_bus_put(bus); in sfp_register_socket()
822 bus = NULL; in sfp_register_socket()
825 return bus; in sfp_register_socket()
829 void sfp_unregister_socket(struct sfp_bus *bus) in sfp_unregister_socket() argument
832 if (bus->upstream_ops) in sfp_unregister_socket()
833 sfp_unregister_bus(bus); in sfp_unregister_socket()
834 sfp_socket_clear(bus); in sfp_unregister_socket()
837 sfp_bus_put(bus); in sfp_unregister_socket()