Lines Matching +full:ethernet +full:- +full:ports
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * net/dsa/dsa2.c - Hardware switch handling, binding version 2
4 * Copyright (c) 2008-2009 Marvell Semiconductor
30 if (dst->index != tree_index) in dsa_switch_find()
33 list_for_each_entry(dp, &dst->ports, list) { in dsa_switch_find()
34 if (dp->ds->index != sw_index) in dsa_switch_find()
37 return dp->ds; in dsa_switch_find()
50 if (dst->index == index) in dsa_tree_find()
64 dst->index = index; in dsa_tree_alloc()
66 INIT_LIST_HEAD(&dst->rtable); in dsa_tree_alloc()
68 INIT_LIST_HEAD(&dst->ports); in dsa_tree_alloc()
70 INIT_LIST_HEAD(&dst->list); in dsa_tree_alloc()
71 list_add_tail(&dst->list, &dsa_tree_list); in dsa_tree_alloc()
73 kref_init(&dst->refcount); in dsa_tree_alloc()
80 list_del(&dst->list); in dsa_tree_free()
87 kref_get(&dst->refcount); in dsa_tree_get()
115 kref_put(&dst->refcount, dsa_tree_release); in dsa_tree_put()
120 return port->type == DSA_PORT_TYPE_DSA; in dsa_port_is_dsa()
125 return port->type == DSA_PORT_TYPE_CPU; in dsa_port_is_cpu()
130 return dp->type == DSA_PORT_TYPE_USER; in dsa_port_is_user()
138 list_for_each_entry(dp, &dst->ports, list) in dsa_tree_find_port_by_node()
139 if (dp->dn == dn) in dsa_tree_find_port_by_node()
148 struct dsa_switch *ds = dp->ds; in dsa_link_touch()
152 dst = ds->dst; in dsa_link_touch()
154 list_for_each_entry(dl, &dst->rtable, list) in dsa_link_touch()
155 if (dl->dp == dp && dl->link_dp == link_dp) in dsa_link_touch()
162 dl->dp = dp; in dsa_link_touch()
163 dl->link_dp = link_dp; in dsa_link_touch()
165 INIT_LIST_HEAD(&dl->list); in dsa_link_touch()
166 list_add_tail(&dl->list, &dst->rtable); in dsa_link_touch()
173 struct dsa_switch *ds = dp->ds; in dsa_port_setup_routing_table()
174 struct dsa_switch_tree *dst = ds->dst; in dsa_port_setup_routing_table()
175 struct device_node *dn = dp->dn; in dsa_port_setup_routing_table()
203 list_for_each_entry(dp, &dst->ports, list) { in dsa_tree_setup_routing_table()
218 list_for_each_entry(dp, &dst->ports, list) in dsa_tree_find_first_cpu()
231 pr_err("DSA: tree %d has no CPU port\n", dst->index); in dsa_tree_setup_default_cpu()
232 return -EINVAL; in dsa_tree_setup_default_cpu()
235 /* Assign the default CPU port to all ports of the fabric */ in dsa_tree_setup_default_cpu()
236 list_for_each_entry(dp, &dst->ports, list) in dsa_tree_setup_default_cpu()
238 dp->cpu_dp = cpu_dp; in dsa_tree_setup_default_cpu()
247 list_for_each_entry(dp, &dst->ports, list) in dsa_tree_teardown_default_cpu()
249 dp->cpu_dp = NULL; in dsa_tree_teardown_default_cpu()
254 struct devlink_port *dlp = &dp->devlink_port; in dsa_port_setup()
259 if (dp->setup) in dsa_port_setup()
262 switch (dp->type) { in dsa_port_setup()
291 dp->mac = of_get_mac_address(dp->dn); in dsa_port_setup()
296 devlink_port_type_eth_set(dlp, dp->slave); in dsa_port_setup()
307 dp->setup = true; in dsa_port_setup()
314 struct devlink_port *dlp = &dp->devlink_port; in dsa_port_devlink_setup()
315 struct dsa_switch_tree *dst = dp->ds->dst; in dsa_port_devlink_setup()
317 struct devlink *dl = dp->ds->devlink; in dsa_port_devlink_setup()
322 id = (const unsigned char *)&dst->index; in dsa_port_devlink_setup()
323 len = sizeof(dst->index); in dsa_port_devlink_setup()
325 attrs.phys.port_number = dp->index; in dsa_port_devlink_setup()
330 switch (dp->type) { in dsa_port_devlink_setup()
346 err = devlink_port_register(dl, dlp, dp->index); in dsa_port_devlink_setup()
349 dp->devlink_port_setup = true; in dsa_port_devlink_setup()
356 struct devlink_port *dlp = &dp->devlink_port; in dsa_port_teardown()
358 if (!dp->setup) in dsa_port_teardown()
363 switch (dp->type) { in dsa_port_teardown()
368 dsa_tag_driver_put(dp->tag_ops); in dsa_port_teardown()
376 if (dp->slave) { in dsa_port_teardown()
377 dsa_slave_destroy(dp->slave); in dsa_port_teardown()
378 dp->slave = NULL; in dsa_port_teardown()
383 dp->setup = false; in dsa_port_teardown()
388 struct devlink_port *dlp = &dp->devlink_port; in dsa_port_devlink_teardown()
390 if (dp->devlink_port_setup) in dsa_port_devlink_teardown()
392 dp->devlink_port_setup = false; in dsa_port_devlink_teardown()
401 if (ds->ops->devlink_info_get) in dsa_devlink_info_get()
402 return ds->ops->devlink_info_get(ds, req, extack); in dsa_devlink_info_get()
404 return -EOPNOTSUPP; in dsa_devlink_info_get()
417 if (ds->setup) in dsa_switch_setup()
420 /* Initialize ds->phys_mii_mask before registering the slave MDIO bus in dsa_switch_setup()
421 * driver and before ops->setup() has run, since the switch drivers and in dsa_switch_setup()
425 ds->phys_mii_mask |= dsa_user_ports(ds); in dsa_switch_setup()
430 ds->devlink = devlink_alloc(&dsa_devlink_ops, sizeof(*dl_priv)); in dsa_switch_setup()
431 if (!ds->devlink) in dsa_switch_setup()
432 return -ENOMEM; in dsa_switch_setup()
433 dl_priv = devlink_priv(ds->devlink); in dsa_switch_setup()
434 dl_priv->ds = ds; in dsa_switch_setup()
436 err = devlink_register(ds->devlink, ds->dev); in dsa_switch_setup()
441 * setup() can register regions etc, against the ports in dsa_switch_setup()
443 list_for_each_entry(dp, &ds->dst->ports, list) { in dsa_switch_setup()
444 if (dp->ds == ds) { in dsa_switch_setup()
455 err = ds->ops->setup(ds); in dsa_switch_setup()
459 devlink_params_publish(ds->devlink); in dsa_switch_setup()
461 if (!ds->slave_mii_bus && ds->ops->phy_read) { in dsa_switch_setup()
462 ds->slave_mii_bus = mdiobus_alloc(); in dsa_switch_setup()
463 if (!ds->slave_mii_bus) { in dsa_switch_setup()
464 err = -ENOMEM; in dsa_switch_setup()
470 err = mdiobus_register(ds->slave_mii_bus); in dsa_switch_setup()
475 ds->setup = true; in dsa_switch_setup()
480 if (ds->slave_mii_bus && ds->ops->phy_read) in dsa_switch_setup()
481 mdiobus_free(ds->slave_mii_bus); in dsa_switch_setup()
483 if (ds->ops->teardown) in dsa_switch_setup()
484 ds->ops->teardown(ds); in dsa_switch_setup()
488 list_for_each_entry(dp, &ds->dst->ports, list) in dsa_switch_setup()
489 if (dp->ds == ds) in dsa_switch_setup()
491 devlink_unregister(ds->devlink); in dsa_switch_setup()
493 devlink_free(ds->devlink); in dsa_switch_setup()
494 ds->devlink = NULL; in dsa_switch_setup()
503 if (!ds->setup) in dsa_switch_teardown()
506 if (ds->slave_mii_bus && ds->ops->phy_read) { in dsa_switch_teardown()
507 mdiobus_unregister(ds->slave_mii_bus); in dsa_switch_teardown()
508 mdiobus_free(ds->slave_mii_bus); in dsa_switch_teardown()
509 ds->slave_mii_bus = NULL; in dsa_switch_teardown()
514 if (ds->ops->teardown) in dsa_switch_teardown()
515 ds->ops->teardown(ds); in dsa_switch_teardown()
517 if (ds->devlink) { in dsa_switch_teardown()
518 list_for_each_entry(dp, &ds->dst->ports, list) in dsa_switch_teardown()
519 if (dp->ds == ds) in dsa_switch_teardown()
521 devlink_unregister(ds->devlink); in dsa_switch_teardown()
522 devlink_free(ds->devlink); in dsa_switch_teardown()
523 ds->devlink = NULL; in dsa_switch_teardown()
526 ds->setup = false; in dsa_switch_teardown()
534 list_for_each_entry(dp, &dst->ports, list) { in dsa_tree_setup_switches()
535 err = dsa_switch_setup(dp->ds); in dsa_tree_setup_switches()
540 list_for_each_entry(dp, &dst->ports, list) { in dsa_tree_setup_switches()
544 dp->type = DSA_PORT_TYPE_UNUSED; in dsa_tree_setup_switches()
555 list_for_each_entry(dp, &dst->ports, list) in dsa_tree_setup_switches()
558 list_for_each_entry(dp, &dst->ports, list) in dsa_tree_setup_switches()
559 dsa_switch_teardown(dp->ds); in dsa_tree_setup_switches()
568 list_for_each_entry(dp, &dst->ports, list) in dsa_tree_teardown_switches()
571 list_for_each_entry(dp, &dst->ports, list) in dsa_tree_teardown_switches()
572 dsa_switch_teardown(dp->ds); in dsa_tree_teardown_switches()
580 list_for_each_entry(dp, &dst->ports, list) { in dsa_tree_setup_master()
582 err = dsa_master_setup(dp->master, dp); in dsa_tree_setup_master()
595 list_for_each_entry(dp, &dst->ports, list) in dsa_tree_teardown_master()
597 dsa_master_teardown(dp->master); in dsa_tree_teardown_master()
605 if (dst->setup) { in dsa_tree_setup()
607 dst->index); in dsa_tree_setup()
608 return -EEXIST; in dsa_tree_setup()
627 dst->setup = true; in dsa_tree_setup()
629 pr_info("DSA: tree %d setup\n", dst->index); in dsa_tree_setup()
645 if (!dst->setup) in dsa_tree_teardown()
654 list_for_each_entry_safe(dl, next, &dst->rtable, list) { in dsa_tree_teardown()
655 list_del(&dl->list); in dsa_tree_teardown()
659 pr_info("DSA: tree %d torn down\n", dst->index); in dsa_tree_teardown()
661 dst->setup = false; in dsa_tree_teardown()
666 struct dsa_switch_tree *dst = ds->dst; in dsa_port_touch()
669 list_for_each_entry(dp, &dst->ports, list) in dsa_port_touch()
670 if (dp->ds == ds && dp->index == index) in dsa_port_touch()
677 dp->ds = ds; in dsa_port_touch()
678 dp->index = index; in dsa_port_touch()
680 INIT_LIST_HEAD(&dp->list); in dsa_port_touch()
681 list_add_tail(&dp->list, &dst->ports); in dsa_port_touch()
691 dp->type = DSA_PORT_TYPE_USER; in dsa_port_parse_user()
692 dp->name = name; in dsa_port_parse_user()
699 dp->type = DSA_PORT_TYPE_DSA; in dsa_port_parse_dsa()
708 struct dsa_switch *mds, *ds = dp->ds; in dsa_get_tag_protocol()
718 mds = mdp->ds; in dsa_get_tag_protocol()
719 mdp_upstream = dsa_upstream_port(mds, mdp->index); in dsa_get_tag_protocol()
720 tag_protocol = mds->ops->get_tag_protocol(mds, mdp_upstream, in dsa_get_tag_protocol()
727 return ds->ops->get_tag_protocol(ds, dp->index, tag_protocol); in dsa_get_tag_protocol()
732 struct dsa_switch *ds = dp->ds; in dsa_port_parse_cpu()
733 struct dsa_switch_tree *dst = ds->dst; in dsa_port_parse_cpu()
740 if (PTR_ERR(tag_ops) == -ENOPROTOOPT) in dsa_port_parse_cpu()
741 return -EPROBE_DEFER; in dsa_port_parse_cpu()
742 dev_warn(ds->dev, "No tagger for this switch\n"); in dsa_port_parse_cpu()
743 dp->master = NULL; in dsa_port_parse_cpu()
747 dp->master = master; in dsa_port_parse_cpu()
748 dp->type = DSA_PORT_TYPE_CPU; in dsa_port_parse_cpu()
749 dp->filter = tag_ops->filter; in dsa_port_parse_cpu()
750 dp->rcv = tag_ops->rcv; in dsa_port_parse_cpu()
751 dp->tag_ops = tag_ops; in dsa_port_parse_cpu()
752 dp->dst = dst; in dsa_port_parse_cpu()
759 struct device_node *ethernet = of_parse_phandle(dn, "ethernet", 0); in dsa_port_parse_of() local
763 dp->dn = dn; in dsa_port_parse_of()
765 if (ethernet) { in dsa_port_parse_of()
768 master = of_find_net_device_by_node(ethernet); in dsa_port_parse_of()
769 of_node_put(ethernet); in dsa_port_parse_of()
771 return -EPROBE_DEFER; in dsa_port_parse_of()
785 struct device_node *ports, *port; in dsa_switch_parse_ports_of() local
790 ports = of_get_child_by_name(dn, "ports"); in dsa_switch_parse_ports_of()
791 if (!ports) { in dsa_switch_parse_ports_of()
792 /* The second possibility is "ethernet-ports" */ in dsa_switch_parse_ports_of()
793 ports = of_get_child_by_name(dn, "ethernet-ports"); in dsa_switch_parse_ports_of()
794 if (!ports) { in dsa_switch_parse_ports_of()
795 dev_err(ds->dev, "no ports child node found\n"); in dsa_switch_parse_ports_of()
796 return -EINVAL; in dsa_switch_parse_ports_of()
800 for_each_available_child_of_node(ports, port) { in dsa_switch_parse_ports_of()
805 if (reg >= ds->num_ports) { in dsa_switch_parse_ports_of()
806 err = -EINVAL; in dsa_switch_parse_ports_of()
818 of_node_put(ports); in dsa_switch_parse_ports_of()
830 if (sz < 0 && sz != -EINVAL) in dsa_switch_parse_member_of()
833 ds->index = m[1]; in dsa_switch_parse_member_of()
835 ds->dst = dsa_tree_touch(m[0]); in dsa_switch_parse_member_of()
836 if (!ds->dst) in dsa_switch_parse_member_of()
837 return -ENOMEM; in dsa_switch_parse_member_of()
847 for (port = 0; port < ds->num_ports; port++) { in dsa_switch_touch_ports()
850 return -ENOMEM; in dsa_switch_touch_ports()
879 return -EPROBE_DEFER; in dsa_port_parse()
903 name = cd->port_names[i]; in dsa_switch_parse_ports()
904 dev = cd->netdev[i]; in dsa_switch_parse_ports()
918 return -EINVAL; in dsa_switch_parse_ports()
927 ds->cd = cd; in dsa_switch_parse()
932 ds->index = 0; in dsa_switch_parse()
933 ds->dst = dsa_tree_touch(0); in dsa_switch_parse()
934 if (!ds->dst) in dsa_switch_parse()
935 return -ENOMEM; in dsa_switch_parse()
946 struct dsa_switch_tree *dst = ds->dst; in dsa_switch_release_ports()
949 list_for_each_entry_safe(dp, next, &dst->ports, list) { in dsa_switch_release_ports()
950 if (dp->ds != ds) in dsa_switch_release_ports()
952 list_del(&dp->list); in dsa_switch_release_ports()
964 if (!ds->dev) in dsa_switch_probe()
965 return -ENODEV; in dsa_switch_probe()
967 pdata = ds->dev->platform_data; in dsa_switch_probe()
968 np = ds->dev->of_node; in dsa_switch_probe()
970 if (!ds->num_ports) in dsa_switch_probe()
971 return -EINVAL; in dsa_switch_probe()
982 err = -ENODEV; in dsa_switch_probe()
988 dst = ds->dst; in dsa_switch_probe()
1005 dsa_tree_put(ds->dst); in dsa_register_switch()
1014 struct dsa_switch_tree *dst = ds->dst; in dsa_switch_remove()