summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/io/i40e/core/i40e_common.c4
-rw-r--r--usr/src/uts/common/io/i40e/i40e_gld.c118
-rw-r--r--usr/src/uts/common/io/i40e/i40e_sw.h1
-rw-r--r--usr/src/uts/common/mapfiles/mac.mapfile2
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 };