diff options
author | Ioana Ciornei <ioana.ciornei@nxp.com> | 2019-05-28 13:38:16 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-05-30 00:48:53 -0400 |
commit | 0e27921816ad99f78140e0c61ddf2bc515cc7e22 (patch) | |
tree | 7b4f6d6e16753929f33852549b86a1c3b0f7d791 /net/dsa | |
parent | 77373d49de22e836cf58ddbe7689d6b4b5046539 (diff) |
net: dsa: Use PHYLINK for the CPU/DSA ports
For DSA switches that do not have an .adjust_link callback, aka those
who transitioned totally to the PHYLINK-compliant API, use PHYLINK to
drive the CPU/DSA ports.
The PHYLIB usage and .adjust_link are kept but deprecated, and users are
asked to transition from it. The reason why we can't do anything for
them is because PHYLINK does not wrap the fixed-link state behind a
phydev object, so we cannot wrap .phylink_mac_config into .adjust_link
unless we fabricate a phy_device structure.
For these ports, the newly introduced PHYLINK_DEV operation type is
used and the dsa_switch device structure is passed to PHYLINK for
printing purposes. The handling of the PHYLINK_NETDEV and PHYLINK_DEV
PHYLINK instances is common from the perspective of the driver.
Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dsa')
-rw-r--r-- | net/dsa/port.c | 69 |
1 files changed, 63 insertions, 6 deletions
diff --git a/net/dsa/port.c b/net/dsa/port.c index 0051f5006248..d74bc9df1359 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c | |||
@@ -481,12 +481,15 @@ void dsa_port_phylink_mac_link_down(struct phylink_config *config, | |||
481 | phy_interface_t interface) | 481 | phy_interface_t interface) |
482 | { | 482 | { |
483 | struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); | 483 | struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); |
484 | struct net_device *dev = dp->slave; | 484 | struct phy_device *phydev = NULL; |
485 | struct dsa_switch *ds = dp->ds; | 485 | struct dsa_switch *ds = dp->ds; |
486 | 486 | ||
487 | if (dsa_is_user_port(ds, dp->index)) | ||
488 | phydev = dp->slave->phydev; | ||
489 | |||
487 | if (!ds->ops->phylink_mac_link_down) { | 490 | if (!ds->ops->phylink_mac_link_down) { |
488 | if (ds->ops->adjust_link && dev->phydev) | 491 | if (ds->ops->adjust_link && phydev) |
489 | ds->ops->adjust_link(ds, dp->index, dev->phydev); | 492 | ds->ops->adjust_link(ds, dp->index, phydev); |
490 | return; | 493 | return; |
491 | } | 494 | } |
492 | 495 | ||
@@ -500,12 +503,11 @@ void dsa_port_phylink_mac_link_up(struct phylink_config *config, | |||
500 | struct phy_device *phydev) | 503 | struct phy_device *phydev) |
501 | { | 504 | { |
502 | struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); | 505 | struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); |
503 | struct net_device *dev = dp->slave; | ||
504 | struct dsa_switch *ds = dp->ds; | 506 | struct dsa_switch *ds = dp->ds; |
505 | 507 | ||
506 | if (!ds->ops->phylink_mac_link_up) { | 508 | if (!ds->ops->phylink_mac_link_up) { |
507 | if (ds->ops->adjust_link && dev->phydev) | 509 | if (ds->ops->adjust_link && phydev) |
508 | ds->ops->adjust_link(ds, dp->index, dev->phydev); | 510 | ds->ops->adjust_link(ds, dp->index, phydev); |
509 | return; | 511 | return; |
510 | } | 512 | } |
511 | 513 | ||
@@ -599,8 +601,53 @@ static int dsa_port_fixed_link_register_of(struct dsa_port *dp) | |||
599 | return 0; | 601 | return 0; |
600 | } | 602 | } |
601 | 603 | ||
604 | static int dsa_port_phylink_register(struct dsa_port *dp) | ||
605 | { | ||
606 | struct dsa_switch *ds = dp->ds; | ||
607 | struct device_node *port_dn = dp->dn; | ||
608 | int mode, err; | ||
609 | |||
610 | mode = of_get_phy_mode(port_dn); | ||
611 | if (mode < 0) | ||
612 | mode = PHY_INTERFACE_MODE_NA; | ||
613 | |||
614 | dp->pl_config.dev = ds->dev; | ||
615 | dp->pl_config.type = PHYLINK_DEV; | ||
616 | |||
617 | dp->pl = phylink_create(&dp->pl_config, of_fwnode_handle(port_dn), | ||
618 | mode, &dsa_port_phylink_mac_ops); | ||
619 | if (IS_ERR(dp->pl)) { | ||
620 | pr_err("error creating PHYLINK: %ld\n", PTR_ERR(dp->pl)); | ||
621 | return PTR_ERR(dp->pl); | ||
622 | } | ||
623 | |||
624 | err = phylink_of_phy_connect(dp->pl, port_dn, 0); | ||
625 | if (err) { | ||
626 | pr_err("could not attach to PHY: %d\n", err); | ||
627 | goto err_phy_connect; | ||
628 | } | ||
629 | |||
630 | rtnl_lock(); | ||
631 | phylink_start(dp->pl); | ||
632 | rtnl_unlock(); | ||
633 | |||
634 | return 0; | ||
635 | |||
636 | err_phy_connect: | ||
637 | phylink_destroy(dp->pl); | ||
638 | return err; | ||
639 | } | ||
640 | |||
602 | int dsa_port_link_register_of(struct dsa_port *dp) | 641 | int dsa_port_link_register_of(struct dsa_port *dp) |
603 | { | 642 | { |
643 | struct dsa_switch *ds = dp->ds; | ||
644 | |||
645 | if (!ds->ops->adjust_link) | ||
646 | return dsa_port_phylink_register(dp); | ||
647 | |||
648 | dev_warn(ds->dev, | ||
649 | "Using legacy PHYLIB callbacks. Please migrate to PHYLINK!\n"); | ||
650 | |||
604 | if (of_phy_is_fixed_link(dp->dn)) | 651 | if (of_phy_is_fixed_link(dp->dn)) |
605 | return dsa_port_fixed_link_register_of(dp); | 652 | return dsa_port_fixed_link_register_of(dp); |
606 | else | 653 | else |
@@ -609,6 +656,16 @@ int dsa_port_link_register_of(struct dsa_port *dp) | |||
609 | 656 | ||
610 | void dsa_port_link_unregister_of(struct dsa_port *dp) | 657 | void dsa_port_link_unregister_of(struct dsa_port *dp) |
611 | { | 658 | { |
659 | struct dsa_switch *ds = dp->ds; | ||
660 | |||
661 | if (!ds->ops->adjust_link) { | ||
662 | rtnl_lock(); | ||
663 | phylink_disconnect_phy(dp->pl); | ||
664 | rtnl_unlock(); | ||
665 | phylink_destroy(dp->pl); | ||
666 | return; | ||
667 | } | ||
668 | |||
612 | if (of_phy_is_fixed_link(dp->dn)) | 669 | if (of_phy_is_fixed_link(dp->dn)) |
613 | of_phy_deregister_fixed_link(dp->dn); | 670 | of_phy_deregister_fixed_link(dp->dn); |
614 | else | 671 | else |