Commit 06e5ba71 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'phylink-resolve-fixes'

Marek Behún says:

====================
phylink resolve fixes

With information from me and my nagging, Russell has produced two fixes
for phylink, which add code that triggers another phylink_resolve() from
phylink_resolve(), if certain conditions are met:
  interface is being changed
or
  link is down and previous link was up
These are needed because sometimes the PCS callbacks may provide stale
values if link / speed / ...
====================

Link: https://lore.kernel.org/r/20211123154403.32051-1-kabel@kernel.orgSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents ddb826c2 dbae3388
...@@ -710,6 +710,7 @@ static void phylink_resolve(struct work_struct *w) ...@@ -710,6 +710,7 @@ static void phylink_resolve(struct work_struct *w)
struct phylink_link_state link_state; struct phylink_link_state link_state;
struct net_device *ndev = pl->netdev; struct net_device *ndev = pl->netdev;
bool mac_config = false; bool mac_config = false;
bool retrigger = false;
bool cur_link_state; bool cur_link_state;
mutex_lock(&pl->state_mutex); mutex_lock(&pl->state_mutex);
...@@ -723,6 +724,7 @@ static void phylink_resolve(struct work_struct *w) ...@@ -723,6 +724,7 @@ static void phylink_resolve(struct work_struct *w)
link_state.link = false; link_state.link = false;
} else if (pl->mac_link_dropped) { } else if (pl->mac_link_dropped) {
link_state.link = false; link_state.link = false;
retrigger = true;
} else { } else {
switch (pl->cur_link_an_mode) { switch (pl->cur_link_an_mode) {
case MLO_AN_PHY: case MLO_AN_PHY:
...@@ -739,6 +741,19 @@ static void phylink_resolve(struct work_struct *w) ...@@ -739,6 +741,19 @@ static void phylink_resolve(struct work_struct *w)
case MLO_AN_INBAND: case MLO_AN_INBAND:
phylink_mac_pcs_get_state(pl, &link_state); phylink_mac_pcs_get_state(pl, &link_state);
/* The PCS may have a latching link-fail indicator.
* If the link was up, bring the link down and
* re-trigger the resolve. Otherwise, re-read the
* PCS state to get the current status of the link.
*/
if (!link_state.link) {
if (cur_link_state)
retrigger = true;
else
phylink_mac_pcs_get_state(pl,
&link_state);
}
/* If we have a phy, the "up" state is the union of /* If we have a phy, the "up" state is the union of
* both the PHY and the MAC * both the PHY and the MAC
*/ */
...@@ -747,6 +762,15 @@ static void phylink_resolve(struct work_struct *w) ...@@ -747,6 +762,15 @@ static void phylink_resolve(struct work_struct *w)
/* Only update if the PHY link is up */ /* Only update if the PHY link is up */
if (pl->phydev && pl->phy_state.link) { if (pl->phydev && pl->phy_state.link) {
/* If the interface has changed, force a
* link down event if the link isn't already
* down, and re-resolve.
*/
if (link_state.interface !=
pl->phy_state.interface) {
retrigger = true;
link_state.link = false;
}
link_state.interface = pl->phy_state.interface; link_state.interface = pl->phy_state.interface;
/* If we have a PHY, we need to update with /* If we have a PHY, we need to update with
...@@ -789,7 +813,7 @@ static void phylink_resolve(struct work_struct *w) ...@@ -789,7 +813,7 @@ static void phylink_resolve(struct work_struct *w)
else else
phylink_link_up(pl, link_state); phylink_link_up(pl, link_state);
} }
if (!link_state.link && pl->mac_link_dropped) { if (!link_state.link && retrigger) {
pl->mac_link_dropped = false; pl->mac_link_dropped = false;
queue_work(system_power_efficient_wq, &pl->resolve); queue_work(system_power_efficient_wq, &pl->resolve);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment