diff options
Diffstat (limited to 'drivers/net/phy/phy_device.c')
-rw-r--r-- | drivers/net/phy/phy_device.c | 57 |
1 files changed, 38 insertions, 19 deletions
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 2f5587306022..348a5fefd68e 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -89,13 +89,23 @@ static bool mdio_bus_phy_may_suspend(struct phy_device *phydev) if (!drv || !phydrv->suspend) return false; - /* PHY not attached? May suspend if the PHY has not already been - * suspended as part of a prior call to phy_disconnect() -> - * phy_detach() -> phy_suspend() because the parent netdev might be the - * MDIO bus driver and clock gated at this point. + /* + * netdev is NULL has three cases: + * - phy is not found + * - phy is found, match to general phy driver + * - phy is found, match to specifical phy driver + * + * Case 1: phy is not found, cannot communicate by MDIO bus. + * Case 2: phy is found: + * if phy dev driver probe/bind err, netdev is not __open__ status, + * mdio bus is unregistered. + * if phy is detached, phy had entered suspended status. + * Case 3: phy is found, phy is detached, phy had entered suspended status. + * + * So, in here, it shouldn't set phy to suspend by calling mdio bus. */ if (!netdev) - goto out; + return false; /* Don't suspend PHY if the attached netdev parent may wakeup. * The parent may point to a PCI device, as in tg3 driver. @@ -110,8 +120,7 @@ static bool mdio_bus_phy_may_suspend(struct phy_device *phydev) if (device_may_wakeup(&netdev->dev)) return false; -out: - return !phydev->suspended; + return true; } static int mdio_bus_phy_suspend(struct device *dev) @@ -254,7 +263,7 @@ static int phy_needs_fixup(struct phy_device *phydev, struct phy_fixup *fixup) } /* Runs any matching fixups for this phydev */ -static int phy_scan_fixups(struct phy_device *phydev) +int phy_scan_fixups(struct phy_device *phydev) { struct phy_fixup *fixup; @@ -274,6 +283,7 @@ static int phy_scan_fixups(struct phy_device *phydev) return 0; } +EXPORT_SYMBOL(phy_scan_fixups); static int phy_bus_match(struct device *dev, struct device_driver *drv) { @@ -1238,15 +1248,7 @@ int genphy_restart_aneg(struct phy_device *phydev) } EXPORT_SYMBOL(genphy_restart_aneg); -/** - * genphy_config_aneg - restart auto-negotiation or write BMCR - * @phydev: target phy_device struct - * - * Description: If auto-negotiation is enabled, we configure the - * advertising, and then restart auto-negotiation. If it is not - * enabled, then we write the BMCR. - */ -int genphy_config_aneg(struct phy_device *phydev) +int genphy_config_aneg_check(struct phy_device *phydev) { int err, changed; @@ -1274,11 +1276,28 @@ int genphy_config_aneg(struct phy_device *phydev) changed = 1; /* do restart aneg */ } + return changed; +} +EXPORT_SYMBOL(genphy_config_aneg_check); + +/** + * genphy_config_aneg - restart auto-negotiation or write BMCR + * @phydev: target phy_device struct + * + * Description: If auto-negotiation is enabled, we configure the + * advertising, and then restart auto-negotiation. If it is not + * enabled, then we write the BMCR. + */ +int genphy_config_aneg(struct phy_device *phydev) +{ + int result; + /* Only restart aneg if we are advertising something different * than we were before. */ - if (changed > 0) - return genphy_restart_aneg(phydev); + result = genphy_config_aneg_check(phydev); + if (result > 0) + result = genphy_restart_aneg(phydev); return 0; } |