diff options
Diffstat (limited to 'drivers/net/phy/phylink.c')
-rw-r--r-- | drivers/net/phy/phylink.c | 60 |
1 files changed, 42 insertions, 18 deletions
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 96d8e88b4e46..eb29ef53d971 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -5,6 +5,7 @@ * * Copyright (C) 2015 Russell King */ +#include <linux/acpi.h> #include <linux/ethtool.h> #include <linux/export.h> #include <linux/gpio/consumer.h> @@ -181,7 +182,8 @@ static int phylink_parse_fixedlink(struct phylink *pl, pl->link_config.duplex = DUPLEX_FULL; /* We treat the "pause" and "asym-pause" terminology as - * defining the link partner's ability. */ + * defining the link partner's ability. + */ if (fwnode_property_read_bool(fixed_node, "pause")) __set_bit(ETHTOOL_LINK_MODE_Pause_BIT, pl->link_config.lp_advertising); @@ -311,6 +313,11 @@ static int phylink_parse_mode(struct phylink *pl, struct fwnode_handle *fwnode) phylink_set(pl->supported, 5000baseT_Full); break; + case PHY_INTERFACE_MODE_25GBASER: + phylink_set(pl->supported, 25000baseCR_Full); + phylink_set(pl->supported, 25000baseKR_Full); + phylink_set(pl->supported, 25000baseSR_Full); + fallthrough; case PHY_INTERFACE_MODE_USXGMII: case PHY_INTERFACE_MODE_10GKR: case PHY_INTERFACE_MODE_10GBASER: @@ -679,7 +686,8 @@ static void phylink_resolve(struct work_struct *w) phylink_mac_pcs_get_state(pl, &link_state); /* If we have a phy, the "up" state is the union of - * both the PHY and the MAC */ + * both the PHY and the MAC + */ if (pl->phydev) link_state.link &= pl->phy_state.link; @@ -688,7 +696,8 @@ static void phylink_resolve(struct work_struct *w) link_state.interface = pl->phy_state.interface; /* If we have a PHY, we need to update with - * the PHY flow control bits. */ + * the PHY flow control bits. + */ link_state.pause = pl->phy_state.pause; mac_config = true; } @@ -1084,7 +1093,26 @@ EXPORT_SYMBOL_GPL(phylink_connect_phy); int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn, u32 flags) { - struct device_node *phy_node; + return phylink_fwnode_phy_connect(pl, of_fwnode_handle(dn), flags); +} +EXPORT_SYMBOL_GPL(phylink_of_phy_connect); + +/** + * phylink_fwnode_phy_connect() - connect the PHY specified in the fwnode. + * @pl: a pointer to a &struct phylink returned from phylink_create() + * @fwnode: a pointer to a &struct fwnode_handle. + * @flags: PHY-specific flags to communicate to the PHY device driver + * + * Connect the phy specified @fwnode to the phylink instance specified + * by @pl. + * + * Returns 0 on success or a negative errno. + */ +int phylink_fwnode_phy_connect(struct phylink *pl, + struct fwnode_handle *fwnode, + u32 flags) +{ + struct fwnode_handle *phy_fwnode; struct phy_device *phy_dev; int ret; @@ -1094,28 +1122,25 @@ int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn, phy_interface_mode_is_8023z(pl->link_interface))) return 0; - phy_node = of_parse_phandle(dn, "phy-handle", 0); - if (!phy_node) - phy_node = of_parse_phandle(dn, "phy", 0); - if (!phy_node) - phy_node = of_parse_phandle(dn, "phy-device", 0); - - if (!phy_node) { + phy_fwnode = fwnode_get_phy_node(fwnode); + if (IS_ERR(phy_fwnode)) { if (pl->cfg_link_an_mode == MLO_AN_PHY) return -ENODEV; return 0; } - phy_dev = of_phy_find_device(phy_node); + phy_dev = fwnode_phy_find_device(phy_fwnode); /* We're done with the phy_node handle */ - of_node_put(phy_node); + fwnode_handle_put(phy_fwnode); if (!phy_dev) return -ENODEV; ret = phy_attach_direct(pl->netdev, phy_dev, flags, pl->link_interface); - if (ret) + if (ret) { + phy_device_free(phy_dev); return ret; + } ret = phylink_bringup_phy(pl, phy_dev, pl->link_config.interface); if (ret) @@ -1123,7 +1148,7 @@ int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn, return ret; } -EXPORT_SYMBOL_GPL(phylink_of_phy_connect); +EXPORT_SYMBOL_GPL(phylink_fwnode_phy_connect); /** * phylink_disconnect_phy() - disconnect any PHY attached to the phylink @@ -1358,11 +1383,10 @@ int phylink_ethtool_ksettings_get(struct phylink *pl, ASSERT_RTNL(); - if (pl->phydev) { + if (pl->phydev) phy_ethtool_ksettings_get(pl->phydev, kset); - } else { + else kset->base.port = pl->link_port; - } linkmode_copy(kset->link_modes.supported, pl->supported); |