diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/common/io/i40e/core/i40e_common.c | 4 | ||||
-rw-r--r-- | usr/src/uts/common/io/i40e/i40e_gld.c | 118 | ||||
-rw-r--r-- | usr/src/uts/common/io/i40e/i40e_sw.h | 1 | ||||
-rw-r--r-- | usr/src/uts/common/mapfiles/mac.mapfile | 2 |
4 files changed, 125 insertions, 0 deletions
diff --git a/usr/src/uts/common/io/i40e/core/i40e_common.c b/usr/src/uts/common/io/i40e/core/i40e_common.c index f750bf69ce..9a9f5a4651 100644 --- a/usr/src/uts/common/io/i40e/core/i40e_common.c +++ b/usr/src/uts/common/io/i40e/core/i40e_common.c @@ -1761,6 +1761,8 @@ enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures, config.eee_capability = abilities.eee_capability; config.eeer = abilities.eeer_val; config.low_power_ctrl = abilities.d3_lpan; + config.fec_config = abilities.fec_cfg_curr_mod_ext_info & + I40E_AQ_PHY_FEC_CONFIG_MASK; status = i40e_aq_set_phy_config(hw, &config, NULL); if (status) @@ -1920,6 +1922,8 @@ enum i40e_status_code i40e_aq_get_link_info(struct i40e_hw *hw, hw_link_info->link_speed = (enum i40e_aq_link_speed)resp->link_speed; hw_link_info->link_info = resp->link_info; hw_link_info->an_info = resp->an_info; + hw_link_info->fec_info = resp->config & (I40E_AQ_CONFIG_FEC_KR_ENA | + I40E_AQ_CONFIG_FEC_RS_ENA); hw_link_info->ext_info = resp->ext_info; hw_link_info->loopback = resp->loopback & I40E_AQ_LOOPBACK_MASK; hw_link_info->max_frame_size = LE16_TO_CPU(resp->max_frame_size); diff --git a/usr/src/uts/common/io/i40e/i40e_gld.c b/usr/src/uts/common/io/i40e/i40e_gld.c index ca5b15cd4a..09bc1b4743 100644 --- a/usr/src/uts/common/io/i40e/i40e_gld.c +++ b/usr/src/uts/common/io/i40e/i40e_gld.c @@ -965,10 +965,80 @@ i40e_m_propinfo_private(i40e_t *i40e, const char *pr_name, } static int +i40e_update_fec(i40e_t *i40e, link_fec_t fec) +{ + struct i40e_hw *hw = &i40e->i40e_hw_space; + struct i40e_aq_get_phy_abilities_resp abilities; + struct i40e_aq_set_phy_config config; + link_fec_t fec_requested; + int req_fec; + + ASSERT(MUTEX_HELD(&i40e->i40e_general_lock)); + + if (fec == i40e->i40e_fec_requested) + return (0); + + fec_requested = fec; + if ((fec & LINK_FEC_AUTO) != 0) { + req_fec = I40E_AQ_SET_FEC_AUTO; + fec &= ~LINK_FEC_AUTO; + } else if ((fec & LINK_FEC_NONE) != 0) { + req_fec = 0; + fec &= ~LINK_FEC_NONE; + } else { + req_fec = 0; + if ((fec & LINK_FEC_BASE_R) != 0) { + req_fec |= I40E_AQ_SET_FEC_ABILITY_KR | + I40E_AQ_SET_FEC_REQUEST_KR; + fec &= ~LINK_FEC_BASE_R; + } + if ((fec & LINK_FEC_RS) != 0) { + req_fec |= I40E_AQ_SET_FEC_ABILITY_RS | + I40E_AQ_SET_FEC_REQUEST_RS; + fec &= ~LINK_FEC_RS; + } + if (req_fec == 0) + return (EINVAL); + } + + /* + * if fec is not zero now, then there is an invalid fec or + * combination of settings. + */ + if (fec != 0) + return (EINVAL); + + if (i40e_aq_get_phy_capabilities(hw, B_FALSE, B_FALSE, &abilities, + NULL) != I40E_SUCCESS) + return (EIO); + + bzero(&config, sizeof (config)); + config.abilities = abilities.abilities; + /* Restart the link */ + config.abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK; + config.phy_type = abilities.phy_type; + config.phy_type_ext = abilities.phy_type_ext; + config.link_speed = abilities.link_speed; + config.eee_capability = abilities.eee_capability; + config.eeer = abilities.eeer_val; + config.low_power_ctrl = abilities.d3_lpan; + config.fec_config = req_fec & I40E_AQ_PHY_FEC_CONFIG_MASK; + if (i40e_aq_set_phy_config(hw, &config, NULL) != I40E_SUCCESS) + return (EIO); + + if (i40e_update_link_info(hw) != I40E_SUCCESS) + return (EIO); + + i40e->i40e_fec_requested = fec_requested; + + return (0); +} +static int i40e_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, uint_t pr_valsize, const void *pr_val) { uint32_t new_mtu; + link_fec_t fec; i40e_t *i40e = arg; int ret = 0; @@ -1029,6 +1099,12 @@ i40e_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, } break; + case MAC_PROP_EN_FEC_CAP: + bcopy(pr_val, &fec, sizeof (fec)); + + ret = i40e_update_fec(i40e, fec); + break; + case MAC_PROP_PRIVATE: ret = i40e_m_setprop_private(i40e, pr_name, pr_valsize, pr_val); break; @@ -1041,6 +1117,20 @@ i40e_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, return (ret); } +static link_fec_t +i40e_fec_to_linkfec(struct i40e_hw *hw) +{ + struct i40e_link_status *ls = &hw->phy.link_info; + + if ((ls->fec_info & I40E_AQ_CONFIG_FEC_KR_ENA) != 0) + return (LINK_FEC_BASE_R); + + if ((ls->fec_info & I40E_AQ_CONFIG_FEC_RS_ENA) != 0) + return (LINK_FEC_RS); + + return (LINK_FEC_NONE); +} + static int i40e_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, uint_t pr_valsize, void *pr_val) @@ -1103,6 +1193,21 @@ i40e_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, } bcopy(&i40e->i40e_sdu, pr_val, sizeof (uint32_t)); break; + case MAC_PROP_ADV_FEC_CAP: + if (pr_valsize < sizeof (link_fec_t)) { + ret = EOVERFLOW; + break; + } + *(link_fec_t *)pr_val = + i40e_fec_to_linkfec(&i40e->i40e_hw_space); + break; + case MAC_PROP_EN_FEC_CAP: + if (pr_valsize < sizeof (link_fec_t)) { + ret = EOVERFLOW; + break; + } + *(link_fec_t *)pr_val = i40e->i40e_fec_requested; + break; /* * Because we don't let users control the speeds we may auto-negotiate @@ -1191,6 +1296,19 @@ i40e_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num, case MAC_PROP_MTU: mac_prop_info_set_range_uint32(prh, I40E_MIN_MTU, I40E_MAX_MTU); break; + case MAC_PROP_ADV_FEC_CAP: + mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); + if (i40e_is_25G_device(i40e->i40e_hw_space.device_id)) + mac_prop_info_set_default_fec(prh, LINK_FEC_AUTO); + break; + case MAC_PROP_EN_FEC_CAP: + if (i40e_is_25G_device(i40e->i40e_hw_space.device_id)) { + mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW); + mac_prop_info_set_default_fec(prh, LINK_FEC_AUTO); + } else { + mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); + } + break; /* * We set the defaults for these based upon the phy's ability to diff --git a/usr/src/uts/common/io/i40e/i40e_sw.h b/usr/src/uts/common/io/i40e/i40e_sw.h index f4da8e75d7..59de0d069e 100644 --- a/usr/src/uts/common/io/i40e/i40e_sw.h +++ b/usr/src/uts/common/io/i40e/i40e_sw.h @@ -867,6 +867,7 @@ typedef struct i40e { link_state_t i40e_link_state; uint32_t i40e_link_speed; /* In Mbps */ link_duplex_t i40e_link_duplex; + link_fec_t i40e_fec_requested; uint_t i40e_sdu; uint_t i40e_frame_max; diff --git a/usr/src/uts/common/mapfiles/mac.mapfile b/usr/src/uts/common/mapfiles/mac.mapfile index d5ba3ae2e5..7613dbc644 100644 --- a/usr/src/uts/common/mapfiles/mac.mapfile +++ b/usr/src/uts/common/mapfiles/mac.mapfile @@ -11,6 +11,7 @@ # # Copyright (c) 2017, Joyent, Inc. +# Copyright 2020 RackTop Systems, Inc. # # @@ -42,6 +43,7 @@ SYMBOL_SCOPE { mac_lso_get { FLAGS = EXTERN }; mac_maxsdu_update { FLAGS = EXTERN }; mac_prop_info_set_default_link_flowctrl { FLAGS = EXTERN }; + mac_prop_info_set_default_fec { FLAGS = EXTERN }; mac_prop_info_set_default_str { FLAGS = EXTERN }; mac_prop_info_set_default_uint8 { FLAGS = EXTERN }; mac_prop_info_set_perm { FLAGS = EXTERN }; |