mirror of
https://github.com/opnsense/src.git
synced 2026-06-08 16:22:46 -04:00
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
This commit is contained in:
parent
1d9722de6f
commit
ba2f531f81
7 changed files with 75 additions and 19 deletions
|
|
@ -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 : \
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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, ...) \
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in a new issue