git: ba2f531f816a - main - ixl(4): Add link state polling
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 20 Jul 2023 22:37:38 UTC
The branch main has been updated by erj: URL: https://cgit.FreeBSD.org/src/commit/?id=ba2f531f816a6bc1ef5f2cba4a329ff7bdbec0f3 commit ba2f531f816a6bc1ef5f2cba4a329ff7bdbec0f3 Author: Krzysztof Galazka <krzysztof.galazka@intel.com> AuthorDate: 2023-07-20 22:33:52 +0000 Commit: Eric Joyner <erj@FreeBSD.org> CommitDate: 2023-07-20 22:33:52 +0000 ixl(4): Add link state polling In some cases driver may ask FW about link state before FW finishes configuration of a (Q)SFP+ transceiver. If first attempt of using Get Link Status AQC after loading driver or handling a reset fails, then re-try periodically for 5 seconds. Signed-off-by: Krzysztof Galazka <krzysztof.galazka@intel.com> Signed-off-by: Eric Joyner <erj@FreeBSD.org> Tested by: jeffrey.e.pieper@intel.com Approved by: erj@ MFC after: 2 days Sponsored by: Intel Corporation Differential Revision: https://reviews.freebsd.org/D40899 --- sys/dev/ixl/i40e_adminq_cmd.h | 2 +- sys/dev/ixl/if_ixl.c | 50 ++++++++++++++++++++++++++++++++++++------- sys/dev/ixl/ixl.h | 2 ++ sys/dev/ixl/ixl_debug.h | 2 ++ sys/dev/ixl/ixl_pf.h | 4 ++++ sys/dev/ixl/ixl_pf_iflib.c | 4 +--- sys/dev/ixl/ixl_pf_main.c | 30 ++++++++++++++++++++------ 7 files changed, 75 insertions(+), 19 deletions(-) diff --git a/sys/dev/ixl/i40e_adminq_cmd.h b/sys/dev/ixl/i40e_adminq_cmd.h index 564a076761d0..679e191412cd 100644 --- a/sys/dev/ixl/i40e_adminq_cmd.h +++ b/sys/dev/ixl/i40e_adminq_cmd.h @@ -44,7 +44,7 @@ #define I40E_FW_API_VERSION_MAJOR 0x0001 #define I40E_FW_API_VERSION_MINOR_X722 0x000C -#define I40E_FW_API_VERSION_MINOR_X710 0x000E +#define I40E_FW_API_VERSION_MINOR_X710 0x000F #define I40E_FW_MINOR_VERSION(_h) ((_h)->mac.type == I40E_MAC_XL710 ? \ I40E_FW_API_VERSION_MINOR_X710 : \ diff --git a/sys/dev/ixl/if_ixl.c b/sys/dev/ixl/if_ixl.c index 7ebbed1f81c8..6e1a3e3e2229 100644 --- a/sys/dev/ixl/if_ixl.c +++ b/sys/dev/ixl/if_ixl.c @@ -444,6 +444,29 @@ ixl_admin_timer(void *arg) { struct ixl_pf *pf = (struct ixl_pf *)arg; + if (ixl_test_state(&pf->state, IXL_STATE_LINK_POLLING)) { + struct i40e_hw *hw = &pf->hw; + sbintime_t stime; + enum i40e_status_code status; + + hw->phy.get_link_info = TRUE; + status = i40e_get_link_status(hw, &pf->link_up); + if (status == I40E_SUCCESS) { + ixl_clear_state(&pf->state, IXL_STATE_LINK_POLLING); + /* OS link info is updated in the admin task */ + } else { + device_printf(pf->dev, + "%s: i40e_get_link_status status %s, aq error %s\n", + __func__, i40e_stat_str(hw, status), + i40e_aq_str(hw, hw->aq.asq_last_status)); + stime = getsbinuptime(); + if (stime - pf->link_poll_start > IXL_PF_MAX_LINK_POLL) { + device_printf(pf->dev, "Polling link status failed\n"); + ixl_clear_state(&pf->state, IXL_STATE_LINK_POLLING); + } + } + } + /* Fire off the admin task */ iflib_admin_intr_deferred(pf->vsi.ctx); @@ -706,12 +729,6 @@ ixl_if_attach_post(if_ctx_t ctx) return (0); } - /* Determine link state */ - if (ixl_attach_get_link_status(pf)) { - error = EINVAL; - goto err; - } - error = ixl_switch_config(pf); if (error) { device_printf(dev, "Initial ixl_switch_config() failed: %d\n", @@ -740,6 +757,11 @@ ixl_if_attach_post(if_ctx_t ctx) device_printf(dev, "Allocating %d queues for PF LAN VSI; %d queues active\n", pf->qtag.num_allocated, pf->qtag.num_active); + /* Determine link state */ + error = ixl_attach_get_link_status(pf); + if (error == EINVAL) + goto err; + /* Limit PHY interrupts to link, autoneg, and modules failure */ status = i40e_aq_set_phy_int_mask(hw, IXL_DEFAULT_PHY_INT_MASK, NULL); @@ -775,8 +797,20 @@ ixl_if_attach_post(if_ctx_t ctx) ixl_set_link(pf, ixl_test_state(&pf->state, IXL_STATE_LINK_ACTIVE_ON_DOWN)); hw->phy.get_link_info = true; - i40e_get_link_status(hw, &pf->link_up); - ixl_update_link_status(pf); + status = i40e_get_link_status(hw, &pf->link_up); + if (status != I40E_SUCCESS) { + device_printf(dev, + "%s get link status, status: %s aq_err=%s\n", + __func__, i40e_stat_str(hw, status), + i40e_aq_str(hw, hw->aq.asq_last_status)); + /* + * Most probably FW has not finished configuring PHY. + * Retry periodically in a timer callback. + */ + ixl_set_state(&pf->state, IXL_STATE_LINK_POLLING); + pf->link_poll_start = getsbinuptime(); + } else + ixl_update_link_status(pf); #ifdef PCI_IOV ixl_initialize_sriov(pf); diff --git a/sys/dev/ixl/ixl.h b/sys/dev/ixl/ixl.h index 30e8ce40126b..03a1fa46fa65 100644 --- a/sys/dev/ixl/ixl.h +++ b/sys/dev/ixl/ixl.h @@ -286,6 +286,8 @@ /* For stats sysctl naming */ #define IXL_QUEUE_NAME_LEN 32 +#define IXL_PF_MAX_LINK_POLL SBT_1S * 5 + MALLOC_DECLARE(M_IXL); #define IXL_DEV_ERR(_dev, _format, ...) \ diff --git a/sys/dev/ixl/ixl_debug.h b/sys/dev/ixl/ixl_debug.h index 0d8c624d2df9..818ba8a1df83 100644 --- a/sys/dev/ixl/ixl_debug.h +++ b/sys/dev/ixl/ixl_debug.h @@ -101,6 +101,8 @@ enum ixl_dbg_mask { IXL_DBG_SWITCH_INFO = 0x00010000, IXL_DBG_I2C = 0x00020000, + IXL_DBG_LINK = 0x00100000, + IXL_DBG_ALL = 0xFFFFFFFF }; diff --git a/sys/dev/ixl/ixl_pf.h b/sys/dev/ixl/ixl_pf.h index 80b35fcb6696..9a786845be13 100644 --- a/sys/dev/ixl/ixl_pf.h +++ b/sys/dev/ixl/ixl_pf.h @@ -89,6 +89,7 @@ enum ixl_state { IXL_STATE_FW_LLDP_DISABLED = 9, IXL_STATE_EEE_ENABLED = 10, IXL_STATE_LINK_ACTIVE_ON_DOWN = 11, + IXL_STATE_LINK_POLLING = 12, }; #define IXL_PF_IN_RECOVERY_MODE(pf) \ @@ -172,6 +173,8 @@ struct ixl_pf { int num_vfs; uint16_t veb_seid; int vc_debug_lvl; + + sbintime_t link_poll_start; }; /* @@ -282,6 +285,7 @@ struct ixl_pf { #define ixl_dbg_info(pf, s, ...) ixl_debug_core((pf)->dev, (pf)->dbg_mask, IXL_DBG_INFO, s, ##__VA_ARGS__) #define ixl_dbg_filter(pf, s, ...) ixl_debug_core((pf)->dev, (pf)->dbg_mask, IXL_DBG_FILTER, s, ##__VA_ARGS__) #define ixl_dbg_iov(pf, s, ...) ixl_debug_core((pf)->dev, (pf)->dbg_mask, IXL_DBG_IOV, s, ##__VA_ARGS__) +#define ixl_dbg_link(pf, s, ...) ixl_debug_core((pf)->dev, (pf)->dbg_mask, IXL_DBG_LINK, s, ##__VA_ARGS__) /* PF-only function declarations */ void ixl_set_state(volatile u32 *s, enum ixl_state bit); diff --git a/sys/dev/ixl/ixl_pf_iflib.c b/sys/dev/ixl/ixl_pf_iflib.c index e0452c7dc01e..a0b450dc038b 100644 --- a/sys/dev/ixl/ixl_pf_iflib.c +++ b/sys/dev/ixl/ixl_pf_iflib.c @@ -1028,9 +1028,7 @@ ixl_rebuild_hw_structs_after_reset(struct ixl_pf *pf, bool is_up) i40e_aq_set_vsi_broadcast(&pf->hw, vsi->seid, TRUE, NULL); /* Determine link state */ - if (ixl_attach_get_link_status(pf)) { - error = EINVAL; - } + ixl_attach_get_link_status(pf); i40e_aq_set_dcb_parameters(hw, TRUE, NULL); diff --git a/sys/dev/ixl/ixl_pf_main.c b/sys/dev/ixl/ixl_pf_main.c index 1ba59c0592a7..13ba4c5f5d17 100644 --- a/sys/dev/ixl/ixl_pf_main.c +++ b/sys/dev/ixl/ixl_pf_main.c @@ -4705,22 +4705,38 @@ ixl_attach_get_link_status(struct ixl_pf *pf) { struct i40e_hw *hw = &pf->hw; device_t dev = pf->dev; - int error = 0; + enum i40e_status_code status; if (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) || (hw->aq.fw_maj_ver < 4)) { i40e_msec_delay(75); - error = i40e_aq_set_link_restart_an(hw, TRUE, NULL); - if (error) { - device_printf(dev, "link restart failed, aq_err=%d\n", - pf->hw.aq.asq_last_status); - return error; + status = i40e_aq_set_link_restart_an(hw, TRUE, NULL); + if (status != I40E_SUCCESS) { + device_printf(dev, + "%s link restart failed status: %s, aq_err=%s\n", + __func__, i40e_stat_str(hw, status), + i40e_aq_str(hw, hw->aq.asq_last_status)); + return (EINVAL); } } /* Determine link state */ hw->phy.get_link_info = TRUE; - i40e_get_link_status(hw, &pf->link_up); + status = i40e_get_link_status(hw, &pf->link_up); + if (status != I40E_SUCCESS) { + device_printf(dev, + "%s get link status, status: %s aq_err=%s\n", + __func__, i40e_stat_str(hw, status), + i40e_aq_str(hw, hw->aq.asq_last_status)); + /* + * Most probably FW has not finished configuring PHY. + * Retry periodically in a timer callback. + */ + ixl_set_state(&pf->state, IXL_STATE_LINK_POLLING); + pf->link_poll_start = getsbinuptime(); + return (EAGAIN); + } + ixl_dbg_link(pf, "%s link_up: %d\n", __func__, pf->link_up); /* Flow Control mode not set by user, read current FW settings */ if (pf->fc == -1)