Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F177552138
D61453.1794698209.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
10 KB
Referenced Files
None
Subscribers
None
D61453.1794698209.diff
View Options
diff --git a/share/man/man4/ix.4 b/share/man/man4/ix.4
--- a/share/man/man4/ix.4
+++ b/share/man/man4/ix.4
@@ -29,7 +29,7 @@
.\"
.\" * Other names and brands may be claimed as the property of others.
.\"
-.Dd September 2, 2026
+.Dd November 12, 2026
.Dt IX 4
.Os
.Sh NAME
@@ -281,7 +281,32 @@
.Pp
This feature is only supported on E610 devices.
.It Va dev.ix.?.eee_state
-Enable or disable Energy Efficient Ethernet on supported devices.
+Request Energy Efficient Ethernet (EEE) on supported devices.
+Set to 0 to disable EEE or 1 to enable it.
+Reading this variable returns the requested setting, not the negotiated
+EEE status.
+Reads and writes fail with
+.Er EPERM
+while the device is in firmware recovery mode.
+.Pp
+Changes are applied asynchronously by reinitializing the interface if it
+is administratively up.
+When the interface is down, the driver updates the PHY without bringing
+up the host interface, so a link shared with a management controller can
+still be configured.
+An EEE update can renegotiate that physical link.
+Changes made while suspended are saved and applied after resume, even if
+the interface remains down.
+A successful write does not confirm that the hardware accepted the setting.
+Failures in the EEE setup step are logged without aborting initialization.
+The requested setting is retained for subsequent initialization attempts.
+Writing the same value has no effect, including after a failed attempt.
+To retry, bring the interface down and back up.
+.Pp
+EEE operates only when negotiated with a supporting link partner at a
+supported link speed.
+The requested policy can be enabled even if the current link speed does
+not support EEE.
.It Va dev.ix.?.eee.tx_lpi_count
Count transmit Low Power Idle events.
.It Va dev.ix.?.eee.rx_lpi_count
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
@@ -253,6 +253,8 @@
static void ixgbe_add_media_types(if_ctx_t);
static void ixgbe_update_stats_counters(struct ixgbe_softc *);
static void ixgbe_config_link(if_ctx_t);
+static void ixgbe_apply_eee(struct ixgbe_softc *);
+static void ixgbe_apply_eee_if_down(struct ixgbe_softc *);
static void ixgbe_get_slot_info(struct ixgbe_softc *);
static void ixgbe_fw_mode_timer(void *);
static void ixgbe_fw_mode_timer_pause(struct ixgbe_softc *);
@@ -3948,7 +3950,8 @@
SYSCTL_ADD_PROC(ctx_list, child, OID_AUTO, "eee_state",
CTLTYPE_INT | CTLFLAG_RW, sc, 0,
- ixgbe_sysctl_eee_state, "I", "EEE Power Save State");
+ ixgbe_sysctl_eee_state, "I",
+ "Requested EEE Power Save State");
eee_node = SYSCTL_ADD_NODE(ctx_list, child, OID_AUTO, "eee",
CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
@@ -4100,6 +4103,8 @@
{
struct ixgbe_softc *sc = iflib_get_softc(ctx);
+ /* Keep EEE updates away from a device that is powering down. */
+ sc->eee_power_blocked = true;
ixgbe_fw_mode_timer_pause(sc);
ixgbe_prepare_wakeup(ctx, event != IFLIB_POWER_DETACH);
return (0);
@@ -4251,6 +4256,9 @@
hw->wol_enabled = false;
sc->wol_filters = 0;
ixgbe_fw_mode_timer_resume(sc);
+ sc->eee_power_blocked = false;
+ /* An administratively down interface will not be initialized. */
+ ixgbe_apply_eee_if_down(sc);
return (0);
} /* ixgbe_if_resume */
@@ -4383,6 +4391,11 @@
iflib_init_failed(ctx);
return;
}
+ /* Enable PHY power before applying the cached link policy. */
+ ixgbe_set_phy_power(hw, true);
+
+ /* Replay EEE policy after reset, before enabling any queues. */
+ ixgbe_apply_eee(sc);
sc->iov_mta_valid = false;
sc->iov_vfta_valid = false;
@@ -4501,9 +4514,6 @@
/* Set moderation on the Link interrupt */
IXGBE_WRITE_REG(hw, IXGBE_EITR(sc->vector), IXGBE_LINK_ITR);
- /* Enable power to the phy. */
- ixgbe_set_phy_power(hw, true);
-
/* Config/Enable Link */
ixgbe_config_link(ctx);
@@ -5221,6 +5231,8 @@
}
ixgbe_if_update_admin_status(ctx);
ixgbe_apply_ldo_link_state(sc, false);
+ /* The interface may have gone down after the sysctl queued a reset. */
+ ixgbe_apply_eee_if_down(sc);
/* reprogram the RAR[0] in case user changed it. */
ixgbe_set_rar(&sc->hw, 0, sc->hw.mac.addr, 0, IXGBE_RAH_AV);
@@ -5305,6 +5317,42 @@
}
} /* ixgbe_link_speed_to_str */
+/* Called with the context lock held and the device accessible. */
+static void
+ixgbe_apply_eee(struct ixgbe_softc *sc)
+{
+ s32 status;
+
+ sx_assert(iflib_ctx_lock_get(sc->ctx), SA_XLOCKED);
+ if ((sc->feat_cap & IXGBE_FEATURE_EEE) == 0)
+ return;
+ status = ixgbe_setup_eee(&sc->hw,
+ (sc->feat_en & IXGBE_FEATURE_EEE) != 0);
+ if (status != IXGBE_SUCCESS)
+ device_printf(sc->dev,
+ "EEE setup failed: %d; retaining requested policy\n",
+ status);
+}
+
+/*
+ * A down host interface may still share an active PHY with a BMC, and no
+ * initialization follows to replay the policy.
+ */
+static void
+ixgbe_apply_eee_if_down(struct ixgbe_softc *sc)
+{
+ if_ctx_t ctx = sc->ctx;
+
+ sx_assert(iflib_ctx_lock_get(ctx), SA_XLOCKED);
+ if (sc->eee_power_blocked ||
+ (if_getflags(iflib_get_ifp(ctx)) & IFF_UP) != 0 ||
+ iflib_is_running(ctx) ||
+ atomic_load_acq_int(&sc->recovery_mode) != 0 ||
+ sc->overtemp_shutdown_pending)
+ return;
+ ixgbe_apply_eee(sc);
+}
+
/************************************************************************
* ixgbe_update_link_status - Update OS on link state
*
@@ -5867,6 +5915,7 @@
ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS)
{
struct ixgbe_softc *sc;
+ struct sx *ctx_lock;
int error, advertise;
sc = (struct ixgbe_softc *)arg1;
@@ -5879,7 +5928,15 @@
if ((error) || (req->newptr == NULL))
return (error);
- return ixgbe_set_advertise(sc, advertise);
+ /* Serialize the PHY update with init and other PHY configuration. */
+ ctx_lock = iflib_ctx_lock_get(sc->ctx);
+ sx_xlock(ctx_lock);
+ if (iflib_in_detach(sc->ctx))
+ error = ENXIO;
+ else
+ error = ixgbe_set_advertise(sc, advertise);
+ sx_xunlock(ctx_lock);
+ return (error);
} /* ixgbe_sysctl_advertise */
/************************************************************************
@@ -6296,30 +6353,27 @@
* Values:
* 0 - disable EEE
* 1 - enable EEE
- * (none) - get current device EEE state
+ * (none) - get requested device EEE state
************************************************************************/
static int
ixgbe_sysctl_eee_state(SYSCTL_HANDLER_ARGS)
{
struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1;
device_t dev = sc->dev;
- if_t ifp = iflib_get_ifp(sc->ctx);
- int curr_eee, new_eee, error = 0;
- s32 retval;
+ struct sx *ctx_lock = iflib_ctx_lock_get(sc->ctx);
+ int new_eee, error;
if (atomic_load_acq_int(&sc->recovery_mode))
return (EPERM);
- curr_eee = new_eee = !!(sc->feat_en & IXGBE_FEATURE_EEE);
+ sx_xlock(ctx_lock);
+ new_eee = !!(sc->feat_en & IXGBE_FEATURE_EEE);
+ sx_xunlock(ctx_lock);
error = sysctl_handle_int(oidp, &new_eee, 0, req);
if ((error) || (req->newptr == NULL))
return (error);
- /* Nothing to do */
- if (new_eee == curr_eee)
- return (0);
-
/* Not supported */
if (!(sc->feat_cap & IXGBE_FEATURE_EEE))
return (EINVAL);
@@ -6328,33 +6382,30 @@
if ((new_eee < 0) || (new_eee > 1))
return (EINVAL);
- /* If link speed is <= 1Gbps and EEE is being enabled, log info */
- if (sc->hw.mac.type == ixgbe_mac_E610 &&
- new_eee &&
- sc->link_speed <= IXGBE_LINK_SPEED_1GB_FULL) {
- device_printf(dev,
- "Energy Efficient Ethernet (EEE) feature is not "
- "supported on link speeds equal to or below 1Gbps. "
- "EEE is supported on speeds above 1Gbps.\n");
- return (EINVAL);
- }
-
- retval = ixgbe_setup_eee(&sc->hw, new_eee);
- if (retval) {
- device_printf(dev, "Error in EEE setup: 0x%08X\n", retval);
- return (EINVAL);
+ sx_xlock(ctx_lock);
+ if (iflib_in_detach(sc->ctx)) {
+ error = ENXIO;
+ goto out;
}
+ /* The state may have changed while copying the sysctl value. */
+ if (new_eee == !!(sc->feat_en & IXGBE_FEATURE_EEE))
+ goto out;
- /* Restart auto-neg */
- if_init(ifp, ifp);
-
- device_printf(dev, "New EEE state: %d\n", new_eee);
-
- /* Cache new value */
+ /* Keep the request until it can be applied, including after suspend. */
if (new_eee)
sc->feat_en |= IXGBE_FEATURE_EEE;
else
sc->feat_en &= ~IXGBE_FEATURE_EEE;
+ device_printf(dev, "Requested EEE state: %d\n", new_eee);
+
+ if ((if_getflags(iflib_get_ifp(sc->ctx)) & IFF_UP) != 0) {
+ iflib_request_reset_if_up(sc->ctx);
+ iflib_admin_intr_deferred(sc->ctx);
+ } else {
+ ixgbe_apply_eee_if_down(sc);
+ }
+out:
+ sx_xunlock(ctx_lock);
return (error);
} /* ixgbe_sysctl_eee_state */
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
@@ -450,6 +450,8 @@
bool link_up;
bool link_enabled;
bool led_active;
+ /* No EEE updates while powering down; iflib context lock. */
+ bool eee_power_blocked;
u32 vector;
u16 dmac;
u32 phy_layer;
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
@@ -78,6 +78,7 @@
case ixgbe_aci_opc_get_phy_caps:
case ixgbe_aci_opc_get_link_status:
case ixgbe_aci_opc_get_link_topo:
+ case ixgbe_aci_opc_set_phy_cfg:
return true;
}
@@ -255,7 +256,8 @@
}
if (desc->retval != IXGBE_ACI_RC_OK) {
- hw->aci.last_status = (enum ixgbe_aci_err)desc->retval;
+ hw->aci.last_status = (enum ixgbe_aci_err)
+ IXGBE_LE16_TO_CPU(desc->retval);
status = IXGBE_ERR_ACI_ERROR;
break;
}
@@ -325,6 +327,10 @@
if (!is_cmd_for_retry || status == IXGBE_SUCCESS ||
(last_status != IXGBE_ACI_RC_EBUSY && status != IXGBE_ERR_ACI_ERROR))
break;
+ /* Only retry PHY updates on an explicit busy response. */
+ if (opcode == ixgbe_aci_opc_set_phy_cfg &&
+ last_status != IXGBE_ACI_RC_EBUSY)
+ break;
if (buf)
memcpy(buf, buf_cpy, buf_size);
@@ -5050,11 +5056,6 @@
if (status != IXGBE_SUCCESS)
return status;
- ixgbe_copy_phy_caps_to_cfg(&phy_caps, &phy_cfg);
-
- phy_cfg.caps |= IXGBE_ACI_PHY_ENA_LINK;
- phy_cfg.caps |= IXGBE_ACI_PHY_ENA_AUTO_LINK_UPDT;
-
/* setup only speeds which are defined for [0x0601/0x0600].eee_cap */
if (enable_eee) {
if (hw->phy.eee_speeds_advertised & IXGBE_LINK_SPEED_100_FULL)
@@ -5069,6 +5070,14 @@
eee_cap |= IXGBE_ACI_PHY_EEE_EN_10GBASE_T;
}
+ /* Avoid restarting the link when the EEE policy already matches. */
+ if (phy_caps.eee_cap == IXGBE_CPU_TO_LE16(eee_cap))
+ return IXGBE_SUCCESS;
+
+ ixgbe_copy_phy_caps_to_cfg(&phy_caps, &phy_cfg);
+ /* An EEE update must not enable a disabled physical link. */
+ phy_cfg.caps |= IXGBE_ACI_PHY_ENA_AUTO_LINK_UPDT;
+
/* Set EEE capability for particular PHY types */
phy_cfg.eee_cap = IXGBE_CPU_TO_LE16(eee_cap);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Nov 14, 11:16 PM (12 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41733687
Default Alt Text
D61453.1794698209.diff (10 KB)
Attached To
Mode
D61453: ixgbe: Apply EEE policy through serialized initialization
Attached
Detach File
Event Timeline