static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy) { struct phylink_link_state config; __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); u32 advertising; int ret; memset(&config, 0, sizeof(config)); ethtool_convert_legacy_u32_to_link_mode(supported, phy->supported); ethtool_convert_legacy_u32_to_link_mode(config.advertising, phy->advertising); config.interface = pl->link_config.interface; /* * This is the new way of dealing with flow control for PHYs, * as described by Timur Tabi in commit 529ed1275263 ("net: phy: * phy drivers should not set SUPPORTED_[Asym_]Pause") except * using our validate call to the MAC, we rely upon the MAC * clearing the bits from both supported and advertising fields. */ if (phylink_test(supported, Pause)) phylink_set(config.advertising, Pause); if (phylink_test(supported, Asym_Pause)) phylink_set(config.advertising, Asym_Pause); ret = phylink_validate(pl, supported, &config); if (ret) return ret; phy->phylink = pl; phy->phy_link_change = phylink_phy_change; netdev_info(pl->netdev, "PHY [%s] driver [%s]\n", dev_name(&phy->mdio.dev), phy->drv->name); mutex_lock(&phy->lock); mutex_lock(&pl->state_mutex); pl->netdev->phydev = phy; pl->phydev = phy; linkmode_copy(pl->supported, supported); linkmode_copy(pl->link_config.advertising, config.advertising); /* Restrict the phy advertisment according to the MAC support. */ ethtool_convert_link_mode_to_legacy_u32(&advertising, config.advertising); phy->advertising = advertising; mutex_unlock(&pl->state_mutex); mutex_unlock(&phy->lock); netdev_dbg(pl->netdev, "phy: setting supported %*pb advertising 0x%08x\n", __ETHTOOL_LINK_MODE_MASK_NBITS, pl->supported, phy->advertising); phy_start_machine(phy); if (phy->irq > 0) phy_start_interrupts(phy); return 0; }
/* phy_connect: * * description: Convenience function for connecting ethernet * devices to PHY devices. The default behavior is for * the PHY infrastructure to handle everything, and only notify * the connected driver when the link status changes. If you * don't want, or can't use the provided functionality, you may * choose to call only the subset of functions which provide * the desired functionality. */ struct phy_device * phy_connect(struct net_device *dev, const char *phy_id, void (*handler)(struct net_device *), u32 flags) { struct phy_device *phydev; phydev = phy_attach(dev, phy_id, flags); if (IS_ERR(phydev)) return phydev; phy_prepare_link(phydev, handler); phy_start_machine(phydev, NULL); if (phydev->irq > 0) phy_start_interrupts(phydev); return phydev; }