summaryrefslogtreecommitdiff
path: root/drivers/net/phy/phy_device.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/phy/phy_device.c')
-rw-r--r--drivers/net/phy/phy_device.c57
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;
}