Message ID | 20211122235154.6392-3-kabel@kernel.org (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | [net,1/2] net: phylink: Force link down and retrigger resolve on interface change | expand |
On Tue, Nov 23, 2021 at 12:51:54AM +0100, Marek Behún wrote: > On mv88e6xxx 1G/2.5G PCS, the SerDes register 4.2001.2 has the following > description: > This register bit indicates when link was lost since the last > read. For the current link status, read this register > back-to-back. > > Thus to get current link state, we need to read the register twice. > > But doing that in the link change interrupt handler would lead to > potentially ignoring link down events, which we really want to avoid. > > Thus this needs to be solved in phylink's resolve, by retriggering > another resolve in the event when PCS reports link down and previous > link was up. > > The wrong value is read when phylink requests change from sgmii to > 2500base-x mode, and link won't come up. This fixes the bug. > > Fixes: 9525ae83959b ("phylink: add phylink infrastructure") > Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk> > Signed-off-by: Marek Behún <kabel@kernel.org> Same issue with this patch wrt authorship vs sign-off.
On Tue, Nov 23, 2021 at 12:51:54AM +0100, Marek Behún wrote: > On mv88e6xxx 1G/2.5G PCS, the SerDes register 4.2001.2 has the following > description: > This register bit indicates when link was lost since the last > read. For the current link status, read this register > back-to-back. > > Thus to get current link state, we need to read the register twice. > > But doing that in the link change interrupt handler would lead to > potentially ignoring link down events, which we really want to avoid. > > Thus this needs to be solved in phylink's resolve, by retriggering > another resolve in the event when PCS reports link down and previous > link was up. > > The wrong value is read when phylink requests change from sgmii to > 2500base-x mode, and link won't come up. This fixes the bug. I've also been re-thinking this patch - I don't think it's sufficient to completely solve the problem, and I think this is required to make it bullet-proof. I suspect the reason no problem is being seen is that normally, the BMSR is read prior to calling phylink_mac_change() which will "unlatch" the bit. diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 73cb97285caa..47fe16b4e387 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -1097,10 +1097,17 @@ static void phylink_resolve(struct work_struct *w) phylink_mac_pcs_get_state(pl, &link_state); /* The PCS may have a latching link-fail indicator. - * If the PCS link goes down, retrigger a resolve. + * 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 && cur_link_state) - retrigger = true; + 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 * both the PHY and the MAC
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 5b8b61daeb98..c6b5d5af8817 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -994,6 +994,12 @@ static void phylink_resolve(struct work_struct *w) case MLO_AN_INBAND: phylink_mac_pcs_get_state(pl, &link_state); + /* The PCS may have a latching link-fail indicator. + * If the PCS link goes down, retrigger a resolve. + */ + if (!link_state.link && cur_link_state) + retrigger = true; + /* If we have a phy, the "up" state is the union of * both the PHY and the MAC */