Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F175762407
D60643.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D60643.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D60643: ix(4): Support Total Port Shutdown on E610
Attached
Detach File
Event Timeline
Log In to Comment