The issue is that when the user disables auto-negotiation by removing
the capability bit from the 'advertised mask' (set method) and then
reads the resulting capabilities, which involves querying MCDI, the
bit reappears in the mask irrespective of the user's intent.

Fix this by remembering the user's intent before any link-state queries.

Fixes: 2a5cf77e6de8 ("common/sfc_efx/base: provide PHY link get method on 
Medford4")
Fixes: 06f569de6c06 ("common/sfc_efx/base: decode netport link state on probe 
path")
Cc: [email protected]

Suggested-by: Andy Moreton <[email protected]>
Signed-off-by: Ivan Malov <[email protected]>
Reviewed-by: Viacheslav Galaktionov <[email protected]>
Reviewed-by: Andy Moreton <[email protected]>
---
 drivers/common/sfc_efx/base/efx_np.c       | 11 +++++------
 drivers/common/sfc_efx/base/medford4_phy.c |  6 +++++-
 2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/common/sfc_efx/base/efx_np.c 
b/drivers/common/sfc_efx/base/efx_np.c
index 293f587892..f35d6aaee1 100644
--- a/drivers/common/sfc_efx/base/efx_np.c
+++ b/drivers/common/sfc_efx/base/efx_np.c
@@ -436,9 +436,6 @@ efx_np_link_state(
            MCDI_OUT2(req, const uint8_t, LINK_STATE_OUT_ADVERTISED_ABILITIES),
            &lsp->enls_adv_cap_mask);
 
-       if (lsp->enls_an_supported != B_FALSE)
-               lsp->enls_adv_cap_mask |= 1U << EFX_PHY_CAP_AN;
-
        efx_np_cap_hw_data_to_sw_mask(
            MCDI_OUT2(req, const uint8_t,
                    LINK_STATE_OUT_LINK_PARTNER_ABILITIES),
@@ -1022,11 +1019,13 @@ efx_np_attach(
        if (rc != 0)
                goto fail3;
 
-       if (ls.enls_an_supported != B_FALSE)
-               epp->ep_phy_cap_mask |= 1U << EFX_PHY_CAP_AN;
-
        epp->ep_adv_cap_mask = ls.enls_adv_cap_mask;
 
+       if (ls.enls_an_supported != B_FALSE) {
+               epp->ep_adv_cap_mask |= 1U << EFX_PHY_CAP_AN;
+               epp->ep_phy_cap_mask |= 1U << EFX_PHY_CAP_AN;
+       }
+
 #if EFSYS_OPT_LOOPBACK
        efx_np_assign_loopback_props(enp);
 #endif /* EFSYS_OPT_LOOPBACK */
diff --git a/drivers/common/sfc_efx/base/medford4_phy.c 
b/drivers/common/sfc_efx/base/medford4_phy.c
index 7b456c9b8a..4d2a954d4f 100644
--- a/drivers/common/sfc_efx/base/medford4_phy.c
+++ b/drivers/common/sfc_efx/base/medford4_phy.c
@@ -32,15 +32,19 @@ medford4_phy_get_link(
        __out           ef10_link_state_t *elsp)
 {
        efx_np_handle_t nph = enp->en_port.ep_np_handle;
+       const efx_port_t *port = &enp->en_port;
        efx_np_link_state_t ls;
        efx_np_mac_state_t ms;
+       uint32_t preserve_an;
        efx_rc_t rc;
 
+       preserve_an = port->ep_adv_cap_mask & (1U << EFX_PHY_CAP_AN);
+
        rc = efx_np_link_state(enp, nph, &ls);
        if (rc != 0)
                goto fail1;
 
-       elsp->epls.epls_adv_cap_mask = ls.enls_adv_cap_mask;
+       elsp->epls.epls_adv_cap_mask = ls.enls_adv_cap_mask | preserve_an;
        elsp->epls.epls_lp_cap_mask = ls.enls_lp_cap_mask;
        elsp->epls.epls_lane_count = ls.enls_lane_count;
        elsp->els_loopback = ls.enls_loopback;
-- 
2.47.3

Reply via email to