diff options
author | Baruch Siach <baruch@tkos.co.il> | 2018-10-03 12:04:49 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-10-05 04:04:12 -0400 |
commit | 7e4183752735deb7543e179a44f4f4b44917cd6f (patch) | |
tree | 8e824d068ccec95206d0ff741d9224a2da60ab29 | |
parent | 2d52527e80c2dc0c5f43f50adf183781262ec565 (diff) |
net: phy: phylink: fix SFP interface autodetection
When connecting SFP PHY to phylink use the detected interface.
Otherwise, the link fails to come up when the configured 'phy-mode'
differs from the SFP detected mode.
Move most of phylink_connect_phy() into __phylink_connect_phy(), and
leave phylink_connect_phy() as a wrapper. phylink_sfp_connect_phy() can
now pass the SFP detected PHY interface to __phylink_connect_phy().
This fixes 1GB SFP module link up on eth3 of the Macchiatobin board that
is configured in the DT to "2500base-x" phy-mode.
Fixes: 9525ae83959b6 ("phylink: add phylink infrastructure")
Suggested-by: Russell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/phy/phylink.c | 48 |
1 files changed, 28 insertions, 20 deletions
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 3ba5cf2a8a5f..7abca86c3aa9 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c | |||
@@ -717,6 +717,30 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy) | |||
717 | return 0; | 717 | return 0; |
718 | } | 718 | } |
719 | 719 | ||
720 | static int __phylink_connect_phy(struct phylink *pl, struct phy_device *phy, | ||
721 | phy_interface_t interface) | ||
722 | { | ||
723 | int ret; | ||
724 | |||
725 | if (WARN_ON(pl->link_an_mode == MLO_AN_FIXED || | ||
726 | (pl->link_an_mode == MLO_AN_INBAND && | ||
727 | phy_interface_mode_is_8023z(interface)))) | ||
728 | return -EINVAL; | ||
729 | |||
730 | if (pl->phydev) | ||
731 | return -EBUSY; | ||
732 | |||
733 | ret = phy_attach_direct(pl->netdev, phy, 0, interface); | ||
734 | if (ret) | ||
735 | return ret; | ||
736 | |||
737 | ret = phylink_bringup_phy(pl, phy); | ||
738 | if (ret) | ||
739 | phy_detach(phy); | ||
740 | |||
741 | return ret; | ||
742 | } | ||
743 | |||
720 | /** | 744 | /** |
721 | * phylink_connect_phy() - connect a PHY to the phylink instance | 745 | * phylink_connect_phy() - connect a PHY to the phylink instance |
722 | * @pl: a pointer to a &struct phylink returned from phylink_create() | 746 | * @pl: a pointer to a &struct phylink returned from phylink_create() |
@@ -734,31 +758,13 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy) | |||
734 | */ | 758 | */ |
735 | int phylink_connect_phy(struct phylink *pl, struct phy_device *phy) | 759 | int phylink_connect_phy(struct phylink *pl, struct phy_device *phy) |
736 | { | 760 | { |
737 | int ret; | ||
738 | |||
739 | if (WARN_ON(pl->link_an_mode == MLO_AN_FIXED || | ||
740 | (pl->link_an_mode == MLO_AN_INBAND && | ||
741 | phy_interface_mode_is_8023z(pl->link_interface)))) | ||
742 | return -EINVAL; | ||
743 | |||
744 | if (pl->phydev) | ||
745 | return -EBUSY; | ||
746 | |||
747 | /* Use PHY device/driver interface */ | 761 | /* Use PHY device/driver interface */ |
748 | if (pl->link_interface == PHY_INTERFACE_MODE_NA) { | 762 | if (pl->link_interface == PHY_INTERFACE_MODE_NA) { |
749 | pl->link_interface = phy->interface; | 763 | pl->link_interface = phy->interface; |
750 | pl->link_config.interface = pl->link_interface; | 764 | pl->link_config.interface = pl->link_interface; |
751 | } | 765 | } |
752 | 766 | ||
753 | ret = phy_attach_direct(pl->netdev, phy, 0, pl->link_interface); | 767 | return __phylink_connect_phy(pl, phy, pl->link_interface); |
754 | if (ret) | ||
755 | return ret; | ||
756 | |||
757 | ret = phylink_bringup_phy(pl, phy); | ||
758 | if (ret) | ||
759 | phy_detach(phy); | ||
760 | |||
761 | return ret; | ||
762 | } | 768 | } |
763 | EXPORT_SYMBOL_GPL(phylink_connect_phy); | 769 | EXPORT_SYMBOL_GPL(phylink_connect_phy); |
764 | 770 | ||
@@ -1672,7 +1678,9 @@ static void phylink_sfp_link_up(void *upstream) | |||
1672 | 1678 | ||
1673 | static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy) | 1679 | static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy) |
1674 | { | 1680 | { |
1675 | return phylink_connect_phy(upstream, phy); | 1681 | struct phylink *pl = upstream; |
1682 | |||
1683 | return __phylink_connect_phy(upstream, phy, pl->link_config.interface); | ||
1676 | } | 1684 | } |
1677 | 1685 | ||
1678 | static void phylink_sfp_disconnect_phy(void *upstream) | 1686 | static void phylink_sfp_disconnect_phy(void *upstream) |