summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2016-12-19 12:17:57 +0000
committerRussell King <rmk+kernel@armlinux.org.uk>2017-05-05 18:42:38 +0100
commit16d2efd8904d068a17f3edc2c5ba78f54e1ef132 (patch)
treee408b6bd21e063e0e7dce634b8ba5dfa673524b7
parent9f4bfb85c85851e88ccba1f2de928b316061fa73 (diff)
phylink: ensure link drops are reported
When the MAC reports a link failure, it can be momentary. Ensure that the event is reported by latching the loss of link, so that the worker reports link down. Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
-rw-r--r--drivers/net/phy/phylink.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index fc0c6eca9101..bc1f2e63d541 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -60,6 +60,8 @@ struct phylink {
struct phylink_link_state phy_state;
struct work_struct resolve;
+ bool mac_link_dropped;
+
const struct phylink_module_ops *module_ops;
void *module_data;
};
@@ -369,6 +371,9 @@ static void phylink_resolve(struct work_struct *w)
mutex_lock(&pl->state_mutex);
if (pl->phylink_disable_state) {
+ pl->mac_link_dropped = false;
+ link_state.link = false;
+ } else if (pl->mac_link_dropped) {
link_state.link = false;
} else {
switch (pl->link_an_mode) {
@@ -434,6 +439,10 @@ static void phylink_resolve(struct work_struct *w)
phylink_pause_to_str(link_state.pause));
}
}
+ if (!link_state.link && pl->mac_link_dropped) {
+ pl->mac_link_dropped = false;
+ queue_work(system_power_efficient_wq, &pl->resolve);
+ }
mutex_unlock(&pl->state_mutex);
}
@@ -648,6 +657,8 @@ EXPORT_SYMBOL_GPL(phylink_disconnect_phy);
void phylink_mac_change(struct phylink *pl, bool up)
{
+ if (!up)
+ pl->mac_link_dropped = true;
phylink_run_resolve(pl);
netdev_dbg(pl->netdev, "mac link %s\n", up ? "up" : "down");
}