summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/phy/phy_device.c22
-rw-r--r--include/linux/phy.h14
2 files changed, 36 insertions, 0 deletions
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 0edff47478c2..cda4abf4e68c 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -1375,6 +1375,14 @@ int phy_init_hw(struct phy_device *phydev)
return ret;
}
+ /* Re-apply autonomous EEE disable after soft reset */
+ if (phydev->autonomous_eee_disabled &&
+ phydev->drv->disable_autonomous_eee) {
+ ret = phydev->drv->disable_autonomous_eee(phydev);
+ if (ret)
+ return ret;
+ }
+
return 0;
}
EXPORT_SYMBOL(phy_init_hw);
@@ -2898,6 +2906,20 @@ void phy_support_eee(struct phy_device *phydev)
linkmode_copy(phydev->advertising_eee, phydev->supported_eee);
phydev->eee_cfg.tx_lpi_enabled = true;
phydev->eee_cfg.eee_enabled = true;
+
+ /* If the PHY supports autonomous EEE, disable it so the MAC can
+ * manage LPI signaling instead. The flag is stored so it can be
+ * re-applied after a PHY soft reset (e.g. suspend/resume).
+ */
+ if (phydev->drv && phydev->drv->disable_autonomous_eee) {
+ int ret = phydev->drv->disable_autonomous_eee(phydev);
+
+ if (ret)
+ phydev_warn(phydev, "Failed to disable autonomous EEE: %pe\n",
+ ERR_PTR(ret));
+ else
+ phydev->autonomous_eee_disabled = true;
+ }
}
EXPORT_SYMBOL(phy_support_eee);
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 5de4b172cd0b..199a7aaa341b 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -612,6 +612,8 @@ struct phy_oatc14_sqi_capability {
* @advertising_eee: Currently advertised EEE linkmodes
* @enable_tx_lpi: When True, MAC should transmit LPI to PHY
* @eee_active: phylib private state, indicating that EEE has been negotiated
+ * @autonomous_eee_disabled: Set when autonomous EEE has been disabled,
+ * used to re-apply after PHY soft reset
* @eee_cfg: User configuration of EEE
* @lp_advertising: Current link partner advertised linkmodes
* @host_interfaces: PHY interface modes supported by host
@@ -739,6 +741,7 @@ struct phy_device {
__ETHTOOL_DECLARE_LINK_MODE_MASK(eee_disabled_modes);
bool enable_tx_lpi;
bool eee_active;
+ bool autonomous_eee_disabled;
struct eee_config eee_cfg;
/* Host supported PHY interface types. Should be ignored if empty. */
@@ -1359,6 +1362,17 @@ struct phy_driver {
void (*get_stats)(struct phy_device *dev,
struct ethtool_stats *stats, u64 *data);
+ /**
+ * @disable_autonomous_eee: Disable PHY-autonomous EEE
+ *
+ * Some PHYs manage EEE autonomously, preventing the MAC from
+ * controlling LPI signaling. This callback disables autonomous
+ * EEE at the PHY.
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+ int (*disable_autonomous_eee)(struct phy_device *dev);
+
/* Get and Set PHY tunables */
/** @get_tunable: Return the value of a tunable */
int (*get_tunable)(struct phy_device *dev,