Page MenuHomeFreeBSD

D28028.diff
No OneTemporary

D28028.diff

diff --git a/sys/dev/ixl/if_ixl.c b/sys/dev/ixl/if_ixl.c
--- a/sys/dev/ixl/if_ixl.c
+++ b/sys/dev/ixl/if_ixl.c
@@ -770,6 +770,12 @@
ixl_update_stats_counters(pf);
ixl_add_hw_stats(pf);
+ /*
+ * Driver may have been reloaded. Ensure that the link state
+ * is consistent with current settings.
+ */
+ ixl_set_link(pf, (pf->state & IXL_PF_STATE_LINK_ACTIVE_ON_DOWN) != 0);
+
hw->phy.get_link_info = true;
i40e_get_link_status(hw, &pf->link_up);
ixl_update_link_status(pf);
@@ -961,6 +967,8 @@
return;
}
+ ixl_set_link(pf, true);
+
/* Reconfigure multicast filters in HW */
ixl_if_multi_set(ctx);
@@ -1003,6 +1011,7 @@
ixl_if_stop(if_ctx_t ctx)
{
struct ixl_pf *pf = iflib_get_softc(ctx);
+ struct ifnet *ifp = iflib_get_ifp(ctx);
struct ixl_vsi *vsi = &pf->vsi;
INIT_DEBUGOUT("ixl_if_stop: begin\n");
@@ -1019,6 +1028,15 @@
ixl_disable_rings_intr(vsi);
ixl_disable_rings(pf, vsi, &pf->qtag);
+
+ /*
+ * Don't set link state if only reconfiguring
+ * e.g. on MTU change.
+ */
+ if ((if_getflags(ifp) & IFF_UP) == 0 &&
+ (atomic_load_acq_32(&pf->state) &
+ IXL_PF_STATE_LINK_ACTIVE_ON_DOWN) == 0)
+ ixl_set_link(pf, false);
}
static int
diff --git a/sys/dev/ixl/ixl_pf.h b/sys/dev/ixl/ixl_pf.h
--- a/sys/dev/ixl/ixl_pf.h
+++ b/sys/dev/ixl/ixl_pf.h
@@ -88,6 +88,7 @@
IXL_PF_STATE_EMP_RESET_REQ = (1 << 8),
IXL_PF_STATE_FW_LLDP_DISABLED = (1 << 9),
IXL_PF_STATE_EEE_ENABLED = (1 << 10),
+ IXL_PF_STATE_LINK_ACTIVE_ON_DOWN = (1 << 11),
};
#define IXL_PF_IN_RECOVERY_MODE(pf) \
@@ -229,6 +230,11 @@
"\t0 - disable\n" \
"\t1 - enable\n"
+#define IXL_SYSCTL_HELP_SET_LINK_ACTIVE \
+"\nKeep link active after setting interface down:\n" \
+"\t0 - disable\n" \
+"\t1 - enable\n"
+
#define IXL_SYSCTL_HELP_READ_I2C \
"\nRead a byte from I2C bus\n" \
"Input: 32-bit value\n" \
@@ -351,6 +357,7 @@
void ixl_get_bus_info(struct ixl_pf *pf);
int ixl_aq_get_link_status(struct ixl_pf *,
struct i40e_aqc_get_link_status *);
+void ixl_set_link(struct ixl_pf *, bool);
int ixl_handle_nvmupd_cmd(struct ixl_pf *, struct ifdrv *);
int ixl_handle_i2c_eeprom_read_cmd(struct ixl_pf *, struct ifreq *ifr);
diff --git a/sys/dev/ixl/ixl_pf_iflib.c b/sys/dev/ixl/ixl_pf_iflib.c
--- a/sys/dev/ixl/ixl_pf_iflib.c
+++ b/sys/dev/ixl/ixl_pf_iflib.c
@@ -413,6 +413,8 @@
/* Print out message if an unqualified module is found */
if ((status->link_info & I40E_AQ_MEDIA_AVAILABLE) &&
(pf->advertised_speed) &&
+ (atomic_load_32(&pf->state) &
+ IXL_PF_STATE_LINK_ACTIVE_ON_DOWN) != 0 &&
(!(status->an_info & I40E_AQ_QUALIFIED_MODULE)) &&
(!(status->link_info & I40E_AQ_LINK_UP)))
device_printf(dev, "Link failed because "
diff --git a/sys/dev/ixl/ixl_pf_main.c b/sys/dev/ixl/ixl_pf_main.c
--- a/sys/dev/ixl/ixl_pf_main.c
+++ b/sys/dev/ixl/ixl_pf_main.c
@@ -62,6 +62,7 @@
static int ixl_sysctl_pf_rx_itr(SYSCTL_HANDLER_ARGS);
static int ixl_sysctl_eee_enable(SYSCTL_HANDLER_ARGS);
+static int ixl_sysctl_set_link_active(SYSCTL_HANDLER_ARGS);
/* Debug Sysctls */
static int ixl_sysctl_link_status(SYSCTL_HANDLER_ARGS);
@@ -385,6 +386,9 @@
break;
}
+ /* Keep link active by default */
+ atomic_set_32(&pf->state, IXL_PF_STATE_LINK_ACTIVE_ON_DOWN);
+
/* Print a subset of the capability information. */
device_printf(dev,
"PF-ID[%d]: VFs %d, MSI-X %d, VF MSI-X %d, QPs %d, %s\n",
@@ -2499,6 +2503,12 @@
CTLFLAG_RD | CTLFLAG_MPSAFE, &pf->stats.rx_lpi_count,
"RX LPI count");
+ SYSCTL_ADD_PROC(ctx, ctx_list, OID_AUTO,
+ "link_active_on_if_down",
+ CTLTYPE_INT | CTLFLAG_RWTUN,
+ pf, 0, ixl_sysctl_set_link_active, "I",
+ IXL_SYSCTL_HELP_SET_LINK_ACTIVE);
+
/* Add sysctls meant to print debug information, but don't list them
* in "sysctl -a" output. */
debug_node = SYSCTL_ADD_NODE(ctx, ctx_list,
@@ -2519,6 +2529,11 @@
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT,
pf, 0, ixl_sysctl_link_status, "A", IXL_SYSCTL_HELP_LINK_STATUS);
+ SYSCTL_ADD_PROC(ctx, debug_list,
+ OID_AUTO, "phy_abilities_init",
+ CTLTYPE_STRING | CTLFLAG_RD,
+ pf, 1, ixl_sysctl_phy_abilities, "A", "Initial PHY Abilities");
+
SYSCTL_ADD_PROC(ctx, debug_list,
OID_AUTO, "phy_abilities",
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT,
@@ -3107,6 +3122,95 @@
return (-1);
}
+void
+ixl_set_link(struct ixl_pf *pf, bool enable)
+{
+ struct i40e_hw *hw = &pf->hw;
+ device_t dev = pf->dev;
+ struct i40e_aq_get_phy_abilities_resp abilities;
+ struct i40e_aq_set_phy_config config;
+ enum i40e_status_code aq_error = 0;
+ u32 phy_type, phy_type_ext;
+
+ /* Get initial capability information */
+ aq_error = i40e_aq_get_phy_capabilities(hw,
+ FALSE, TRUE, &abilities, NULL);
+ if (aq_error) {
+ device_printf(dev,
+ "%s: Error getting phy capabilities %d,"
+ " aq error: %d\n", __func__, aq_error,
+ hw->aq.asq_last_status);
+ return;
+ }
+
+ phy_type = abilities.phy_type;
+ phy_type_ext = abilities.phy_type_ext;
+
+ /* Get current capability information */
+ aq_error = i40e_aq_get_phy_capabilities(hw,
+ FALSE, FALSE, &abilities, NULL);
+ if (aq_error) {
+ device_printf(dev,
+ "%s: Error getting phy capabilities %d,"
+ " aq error: %d\n", __func__, aq_error,
+ hw->aq.asq_last_status);
+ return;
+ }
+
+ /* Prepare new config */
+ memset(&config, 0, sizeof(config));
+ config.link_speed = abilities.link_speed;
+ config.abilities = abilities.abilities;
+ 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;
+ config.phy_type = 0;
+ config.phy_type_ext = 0;
+
+ if (enable) {
+ config.phy_type = phy_type;
+ config.phy_type_ext = phy_type_ext;
+
+ config.abilities &= ~(I40E_AQ_PHY_FLAG_PAUSE_TX |
+ I40E_AQ_PHY_FLAG_PAUSE_RX);
+
+ switch (pf->fc) {
+ case I40E_FC_FULL:
+ config.abilities |= I40E_AQ_PHY_FLAG_PAUSE_TX |
+ I40E_AQ_PHY_FLAG_PAUSE_RX;
+ break;
+ case I40E_FC_RX_PAUSE:
+ config.abilities |= I40E_AQ_PHY_FLAG_PAUSE_RX;
+ break;
+ case I40E_FC_TX_PAUSE:
+ config.abilities |= I40E_AQ_PHY_FLAG_PAUSE_TX;
+ break;
+ default:
+ break;
+ }
+ }
+
+ aq_error = i40e_aq_set_phy_config(hw, &config, NULL);
+ if (aq_error) {
+ device_printf(dev,
+ "%s: Error setting new phy config %d,"
+ " aq error: %d\n", __func__, aq_error,
+ hw->aq.asq_last_status);
+ return;
+ }
+
+ aq_error = i40e_aq_set_link_restart_an(hw, enable, NULL);
+ if (aq_error) {
+ device_printf(dev,
+ "%s: Error set link config %d,"
+ " aq error: %d\n", __func__, aq_error,
+ hw->aq.asq_last_status);
+ return;
+ }
+}
+
static char *
ixl_phy_type_string(u32 bit_pos, bool ext)
{
@@ -3265,7 +3369,7 @@
}
status = i40e_aq_get_phy_capabilities(hw,
- FALSE, FALSE, &abilities, NULL);
+ FALSE, arg2 != 0, &abilities, NULL);
if (status) {
device_printf(dev,
"%s: i40e_aq_get_phy_capabilities() status %s, aq error %s\n",
@@ -4447,6 +4551,28 @@
return (0);
}
+static int
+ixl_sysctl_set_link_active(SYSCTL_HANDLER_ARGS)
+{
+ struct ixl_pf *pf = (struct ixl_pf *)arg1;
+ int error, state;
+
+ state = !!(atomic_load_acq_32(&pf->state) &
+ IXL_PF_STATE_LINK_ACTIVE_ON_DOWN);
+
+ error = sysctl_handle_int(oidp, &state, 0, req);
+ if ((error) || (req->newptr == NULL))
+ return (error);
+
+ if (state == 0)
+ atomic_clear_32(&pf->state, IXL_PF_STATE_LINK_ACTIVE_ON_DOWN);
+ else
+ atomic_set_32(&pf->state, IXL_PF_STATE_LINK_ACTIVE_ON_DOWN);
+
+ return (0);
+}
+
+
int
ixl_attach_get_link_status(struct ixl_pf *pf)
{

File Metadata

Mime Type
text/plain
Expires
Sat, Jan 11, 9:11 PM (20 h, 52 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15757847
Default Alt Text
D28028.diff (7 KB)

Event Timeline