Page MenuHomeFreeBSD

D60643.diff
No OneTemporary

D60643.diff

diff --git a/sys/dev/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c
--- a/sys/dev/ixgbe/if_ix.c
+++ b/sys/dev/ixgbe/if_ix.c
@@ -307,6 +307,9 @@
static int ixgbe_enable_lse(struct ixgbe_softc *sc);
static int ixgbe_disable_lse(struct ixgbe_softc *sc);
+static void ixgbe_cache_ldo_policy(struct ixgbe_softc *sc);
+static void ixgbe_apply_ldo_link_state(struct ixgbe_softc *sc, bool link_up);
+
/************************************************************************
* FreeBSD Device Interface Entry Points
************************************************************************/
@@ -361,6 +364,62 @@
}
#endif
+/************************************************************************
+ * ixgbe_cache_ldo_policy
+ ************************************************************************/
+static void
+ixgbe_cache_ldo_policy(struct ixgbe_softc *sc)
+{
+ struct ixgbe_link_default_override_tlv ldo = {0};
+ struct ixgbe_hw *hw = &sc->hw;
+ s32 error;
+
+ sc->ldo_valid = false;
+ sc->ldo_port_disabled = false;
+
+ error = ixgbe_get_link_default_override(hw, &ldo);
+ if (error) {
+ device_printf(sc->dev,
+ "Failed to read E610 Link Default Override TLV, error: %d\n",
+ error);
+ return;
+ }
+
+ sc->ldo_valid = true;
+ sc->ldo_port_disabled =
+ !!(ldo.link_options & IXGBE_LINK_OVERRIDE_PORT_DIS);
+} /* ixgbe_cache_ldo_policy */
+
+/************************************************************************
+ * ixgbe_apply_ldo_link_state
+ ************************************************************************/
+static void
+ixgbe_apply_ldo_link_state(struct ixgbe_softc *sc, bool link_up)
+{
+ struct ixgbe_hw *hw = &sc->hw;
+ s32 error;
+
+ if (!sc->ldo_valid || !sc->ldo_port_disabled)
+ return;
+
+ error = ixgbe_force_link_state(hw, link_up);
+ if (!error)
+ return;
+
+ if (!link_up && error == IXGBE_ERR_ACI_ERROR &&
+ hw->aci.last_status == IXGBE_ACI_RC_EMODE) {
+ device_printf(sc->dev,
+ "Firmware vetoed link shutdown, "
+ "last ACI status: %d\n", hw->aci.last_status);
+ return;
+ }
+
+ device_printf(sc->dev,
+ "Failed to force link %s, error: %d, "
+ "last aci status: %d\n", link_up ? "up" : "down", error,
+ hw->aci.last_status);
+} /* ixgbe_apply_ldo_link_state */
+
static device_method_t ixgbe_if_methods[] = {
DEVMETHOD(ifdi_attach_pre, ixgbe_if_attach_pre),
DEVMETHOD(ifdi_attach_post, ixgbe_if_attach_post),
@@ -1175,6 +1234,7 @@
hw->phy.smart_speed = ixgbe_smart_speed;
ixgbe_init_device_features(sc);
+ ixgbe_cache_ldo_policy(sc);
/* Verify adapter fan is still functional (if applicable) */
if (sc->feat_en & IXGBE_FEATURE_FAN_FAIL) {
@@ -2061,9 +2121,14 @@
"error: %d", err);
}
- if (hw->mac.ops.setup_link)
+ if (hw->mac.ops.setup_link) {
err = hw->mac.ops.setup_link(hw, autoneg,
sc->link_up);
+ if (err)
+ return;
+ }
+
+ ixgbe_apply_ldo_link_state(sc, true);
}
} /* ixgbe_config_link */
@@ -3730,6 +3795,20 @@
if (sc->feat_en & IXGBE_FEATURE_FW_LOGGING)
ixgbe_add_fw_logging_tunables(sc, sc->debug_sysctls);
+
+ if (sc->hw.mac.type == ixgbe_mac_E610) {
+ struct sysctl_oid_list *debug_list;
+ debug_list = SYSCTL_CHILDREN(sc->debug_sysctls);
+
+ SYSCTL_ADD_BOOL(ctx, debug_list, OID_AUTO, "ldo_valid",
+ CTLFLAG_RD, &sc->ldo_valid, 0,
+ "E610 Link Default Override policy valid");
+
+ SYSCTL_ADD_BOOL(ctx, debug_list, OID_AUTO,
+ "ldo_port_disabled", CTLFLAG_RD, &sc->ldo_port_disabled,
+ 0, "E610 Link Default Override PORT_DIS set");
+ }
+
} /* ixgbe_add_debug_sysctls */
/************************************************************************
@@ -5120,6 +5199,8 @@
iflib_link_state_change(ctx, LINK_STATE_DOWN, 0);
sc->link_active = false;
}
+ ixgbe_if_update_admin_status(ctx);
+ ixgbe_apply_ldo_link_state(sc, false);
/* reprogram the RAR[0] in case user changed it. */
ixgbe_set_rar(&sc->hw, 0, sc->hw.mac.addr, 0, IXGBE_RAH_AV);
diff --git a/sys/dev/ixgbe/ixgbe.h b/sys/dev/ixgbe/ixgbe.h
--- a/sys/dev/ixgbe/ixgbe.h
+++ b/sys/dev/ixgbe/ixgbe.h
@@ -443,6 +443,8 @@
int advertise; /* link speeds */
int enable_aim; /* adaptive interrupt moderation */
bool link_active;
+ bool ldo_valid;
+ bool ldo_port_disabled;
u16 num_segs;
u32 link_speed;
bool link_up;
diff --git a/sys/dev/ixgbe/ixgbe_e610.h b/sys/dev/ixgbe/ixgbe_e610.h
--- a/sys/dev/ixgbe/ixgbe_e610.h
+++ b/sys/dev/ixgbe/ixgbe_e610.h
@@ -75,6 +75,7 @@
s32 ixgbe_get_link_status(struct ixgbe_hw *hw, bool *link_up);
s32 ixgbe_aci_get_link_info(struct ixgbe_hw *hw, bool ena_lse,
struct ixgbe_link_status *link);
+s32 ixgbe_force_link_state(struct ixgbe_hw *hw, bool link_up);
s32 ixgbe_aci_set_event_mask(struct ixgbe_hw *hw, u8 port_num, u16 mask);
s32 ixgbe_configure_lse(struct ixgbe_hw *hw, bool activate, u16 mask);
@@ -232,6 +233,9 @@
s32 ixgbe_calc_eeprom_checksum_E610(struct ixgbe_hw *hw);
s32 ixgbe_update_eeprom_checksum_E610(struct ixgbe_hw *hw);
s32 ixgbe_validate_eeprom_checksum_E610(struct ixgbe_hw *hw, u16 *checksum_val);
+/* Reads LDO TLV 0x134; callers consume only IXGBE_LINK_OVERRIDE_PORT_DIS. */
+s32 ixgbe_get_link_default_override(struct ixgbe_hw *hw,
+ struct ixgbe_link_default_override_tlv *ldo);
s32 ixgbe_read_pba_string_E610(struct ixgbe_hw *hw, u8 *pba_num, u32 pba_num_size);
#endif /* _IXGBE_E610_H_ */
diff --git a/sys/dev/ixgbe/ixgbe_e610.c b/sys/dev/ixgbe/ixgbe_e610.c
--- a/sys/dev/ixgbe/ixgbe_e610.c
+++ b/sys/dev/ixgbe/ixgbe_e610.c
@@ -1643,6 +1643,38 @@
return IXGBE_SUCCESS;
}
+/**
+ * ixgbe_force_link_state - force phy link to get up/down
+ * @hw: pointer to hardware structure
+ * @link_up: if true: force link up, if false: force link down
+ *
+ * Send 0x0601 with the IXGBE_ACI_PHY_ENA_LINK bit set/cleared.
+ *
+ * Return: the exit code of the operation.
+ */
+s32 ixgbe_force_link_state(struct ixgbe_hw *hw, bool link_up)
+{
+ struct ixgbe_aci_cmd_set_phy_cfg_data pcfg = {0};
+ struct ixgbe_aci_cmd_get_phy_caps_data pcaps;
+ s32 err;
+
+ err = ixgbe_aci_get_phy_caps(hw, false, IXGBE_ACI_REPORT_ACTIVE_CFG,
+ &pcaps);
+ if (err) {
+ return err;
+ }
+
+ ixgbe_copy_phy_caps_to_cfg(&pcaps, &pcfg);
+
+ if (link_up)
+ pcfg.caps |= IXGBE_ACI_PHY_ENA_LINK;
+ else
+ pcfg.caps &= ~IXGBE_ACI_PHY_ENA_LINK;
+ pcfg.caps |= IXGBE_ACI_PHY_ENA_AUTO_LINK_UPDT;
+
+ return ixgbe_aci_set_phy_cfg(hw, &pcfg);
+}
+
/**
* ixgbe_aci_set_event_mask - set event mask
* @hw: pointer to the HW struct
@@ -5973,6 +6005,53 @@
return IXGBE_ERR_DOES_NOT_EXIST;
}
+/**
+ * ixgbe_get_link_default_override - Get link default override from NVM
+ * @hw: pointer to hardware structure
+ * @ldo: pointer to link default override struct to populate
+ *
+ * Read the Link Default Override TLV (0x134) from the NVM PFA and return
+ * the full per-port override configuration. The caller must consume only
+ * IXGBE_LINK_OVERRIDE_PORT_DIS from link_options for force-link policy.
+ * All port data is read in a single bulk NVM access.
+ *
+ * Return: the exit code of the operation.
+ */
+s32 ixgbe_get_link_default_override(struct ixgbe_hw *hw,
+ struct ixgbe_link_default_override_tlv *ldo)
+{
+ u16 min_tlv_len;
+ u16 tlv, tlv_len, tlv_start;
+ s32 status;
+
+ DEBUGFUNC("ixgbe_get_link_default_override");
+
+ if (!ldo)
+ return IXGBE_ERR_PARAM;
+
+ status = ixgbe_get_pfa_module_tlv(hw, &tlv, &tlv_len,
+ E610_SR_LINK_DEFAULT_OVERRIDE_PTR);
+ if (status)
+ return status;
+
+ /* tlv_len covers value words only, don't add header offset. */
+ min_tlv_len = (hw->bus.func + 1) * E610_SR_PFA_LINK_OVERRIDE_WORDS;
+ if (tlv_len < min_tlv_len)
+ return IXGBE_ERR_INVAL_SIZE;
+
+ tlv_start = tlv + E610_SR_PFA_LINK_OVERRIDE_OFFSET +
+ hw->bus.func * E610_SR_PFA_LINK_OVERRIDE_WORDS;
+
+ /* Read all port-specific words in a single NVM access */
+ status = ixgbe_read_ee_aci_buffer_E610(hw, tlv_start,
+ E610_SR_PFA_LINK_OVERRIDE_WORDS,
+ (u16 *)ldo);
+ if (status)
+ return status;
+
+ return IXGBE_SUCCESS;
+}
+
/**
* ixgbe_read_pba_string_E610 - Reads part number string from NVM
* @hw: pointer to hardware structure
diff --git a/sys/dev/ixgbe/ixgbe_type_e610.h b/sys/dev/ixgbe/ixgbe_type_e610.h
--- a/sys/dev/ixgbe/ixgbe_type_e610.h
+++ b/sys/dev/ixgbe/ixgbe_type_e610.h
@@ -140,6 +140,23 @@
#define E610_SR_NVM_CTRL_WORD 0x00
#define E610_SR_PBA_BLOCK_PTR 0x16
+/* Link Default Override TLV in PFA */
+#define E610_SR_LINK_DEFAULT_OVERRIDE_PTR 0x134
+#define E610_SR_PFA_LINK_OVERRIDE_WORDS 10
+#define E610_SR_PFA_LINK_OVERRIDE_PHY_WORDS 8
+#define E610_SR_PFA_LINK_OVERRIDE_OFFSET 2
+
+/* Link Options bits */
+#define IXGBE_LINK_OVERRIDE_PORT_DIS BIT(2)
+
+#pragma pack(1)
+struct ixgbe_link_default_override_tlv {
+ u16 link_options; /* Port Options 0: only PORT_DIS is consumed */
+ u16 phy_options; /* Port Options 1 */
+ u16 phy_types[E610_SR_PFA_LINK_OVERRIDE_PHY_WORDS]; /* words 2-9 */
+};
+#pragma pack()
+
/* The Orom version topology */
#define IXGBE_OROM_VER_PATCH_SHIFT 0
#define IXGBE_OROM_VER_PATCH_MASK (0xff << IXGBE_OROM_VER_PATCH_SHIFT)

File Metadata

Mime Type
text/plain
Expires
Wed, Oct 14, 3:42 AM (19 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40783191
Default Alt Text
D60643.diff (8 KB)

Event Timeline