[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID:
<174481734008.986682.1350602067856870465.stgit@ahduyck-xeon-server.home.arpa>
Date: Wed, 16 Apr 2025 08:29:00 -0700
From: Alexander Duyck <alexander.duyck@...il.com>
To: netdev@...r.kernel.org
Cc: linux@...linux.org.uk, andrew@...n.ch, hkallweit1@...il.com,
davem@...emloft.net, kuba@...nel.org, pabeni@...hat.com
Subject: [net-next PATCH 2/2] net: phylink: Fix issues with link balancing w/
BMC present
From: Alexander Duyck <alexanderduyck@...com>
This change is meant to address the fact that there are link imbalances
introduced when using phylink on a system with a BMC. Specifically there
are two issues.
The first issue is that if we lose link after the first call to
phylink_start but before it gets to the phylink_resolve we will end up with
the phylink interface assuming the link was always down and not calling
phylink_link_down resulting in a stuck interface.
The second issue is that when a BMC is present we are currently forcing the
link down. This results in us bouncing the link for a fraction of a second
and that will result in dropped packets for the BMC.
The third issue is just an extra "Link Down" message that is seen when
calling phylink_resume. This is addressed by identifying that the link
isn't balanced and just not displaying the down message in such a case.
To resolve these issues this change introduces a new boolean variable
link_balanced. This value will be set to 0 initially when we create the
phylink interface, and again when we bring down the link and unbalance it
in phylink_suspend. When it is set to 0 it will force us to trigger the
phylink_link_up/down call which will have us write to the hardware. As a
result we can avoid the two issues and it should not rearm without another
call to phylink_suspend.
Signed-off-by: Alexander Duyck <alexanderduyck@...com>
---
drivers/net/phy/phylink.c | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 942ce114dabd..2b9ab343942e 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -45,6 +45,7 @@ struct phylink {
struct phylink_pcs *pcs;
struct device *dev;
unsigned int old_link_state:1;
+ unsigned int link_balanced:1;
unsigned long phylink_disable_state; /* bitmask of disables */
struct phy_device *phydev;
@@ -1553,7 +1554,8 @@ static void phylink_link_down(struct phylink *pl)
pl->mac_ops->mac_link_down(pl->config, pl->act_link_an_mode,
pl->cur_interface);
- phylink_info(pl, "Link is Down\n");
+ if (pl->link_balanced)
+ phylink_info(pl, "Link is Down\n");
}
static bool phylink_link_is_up(struct phylink *pl)
@@ -1658,12 +1660,13 @@ static void phylink_resolve(struct work_struct *w)
if (pl->major_config_failed)
link_state.link = false;
- if (link_state.link != cur_link_state) {
+ if (link_state.link != cur_link_state || !pl->link_balanced) {
pl->old_link_state = link_state.link;
if (!link_state.link)
phylink_link_down(pl);
else
phylink_link_up(pl, link_state);
+ pl->link_balanced = true;
}
if (!link_state.link && retrigger) {
pl->link_failed = false;
@@ -2546,6 +2549,7 @@ void phylink_suspend(struct phylink *pl, bool mac_wol)
netif_carrier_off(pl->netdev);
else
pl->old_link_state = false;
+ pl->link_balanced = false;
/* We do not call mac_link_down() here as we want the
* link to remain up to receive the WoL packets.
@@ -2596,16 +2600,6 @@ void phylink_resume(struct phylink *pl)
if (test_bit(PHYLINK_DISABLE_MAC_WOL, &pl->phylink_disable_state)) {
/* Wake-on-Lan enabled, MAC handling */
- /* Call mac_link_down() so we keep the overall state balanced.
- * Do this under the state_mutex lock for consistency. This
- * will cause a "Link Down" message to be printed during
- * resume, which is harmless - the true link state will be
- * printed when we run a resolve.
- */
- mutex_lock(&pl->state_mutex);
- phylink_link_down(pl);
- mutex_unlock(&pl->state_mutex);
-
/* Re-apply the link parameters so that all the settings get
* restored to the MAC.
*/
Powered by blists - more mailing lists