git: 0fdb7f3d30e0 - stable/15 - iflib: Use private lifecycle state for control work
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 29 Oct 2026 05:06:59 UTC
The branch stable/15 has been updated by kbowling:
URL: https://cgit.FreeBSD.org/src/commit/?id=0fdb7f3d30e065011fd346f70d067ba54845c55d
commit 0fdb7f3d30e065011fd346f70d067ba54845c55d
Author: Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-09-11 18:57:42 +0000
Commit: Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-10-29 05:06:50 +0000
iflib: Use private lifecycle state for control work
Use the context-locked datapath state for netmap initialization results,
resume completion and administrative work eligibility. Keep stopped
and failed interfaces eligible for link and mailbox recovery without
using IFF_DRV_OACTIVE as an implicit indication that initialization has
been attempted. Evaluate media and deferred admin eligibility under
the context lock rather than from an earlier IFF_DRV_ flag snapshot.
Always pass through iflib_stop() before an IOV-init callback which
changes the PF queue layout, as the IOV-uninit counterpart already does.
Neither administrative down nor a cleared IFF_DRV_RUNNING proves that
queue DMA is stopped. The private lifecycle state decides whether the
hardware stop is necessary; IFF_UP only decides whether to initialize
again afterward.
Reviewed by: iflib (gallatin)
Sponsored by: BBOX.io
Differential Revision: https://reviews.freebsd.org/D59597
(cherry picked from commit 7fb00406ebf53e07273d0914a5f36ff6fb78c185)
---
sys/net/iflib.c | 51 +++++++++++++++++++++++++++------------------------
1 file changed, 27 insertions(+), 24 deletions(-)
diff --git a/sys/net/iflib.c b/sys/net/iflib.c
index 2fff221023d2..c008d915fd6d 100644
--- a/sys/net/iflib.c
+++ b/sys/net/iflib.c
@@ -539,6 +539,20 @@ typedef struct if_rxsd {
#define CALLOUT_LOCK(txq) mtx_lock(&txq->ift_mtx)
#define CALLOUT_UNLOCK(txq) mtx_unlock(&txq->ift_mtx)
+static bool
+iflib_admin_enabled(if_ctx_t ctx)
+{
+
+ sx_assert(&ctx->ifc_ctx_sx, SA_XLOCKED);
+ /*
+ * Before the first stop/init, only drivers with an always-running
+ * admin path need deferred updates. Stopped and failed datapaths
+ * still need link, mailbox and recovery work after that point.
+ */
+ return (ctx->ifc_datapath_state != IFLIB_DP_UNKNOWN ||
+ (ctx->ifc_sctx->isc_flags & IFLIB_ADMIN_ALWAYS_RUN) != 0);
+}
+
/* Our boot-time initialization hook */
static int iflib_module_event_handler(module_t, int, void *);
@@ -833,7 +847,7 @@ iflib_netmap_register(struct netmap_adapter *na, int onoff)
iflib_init_locked(ctx);
IFDI_CRCSTRIP_SET(ctx, onoff, iflib_crcstrip); // XXX why twice ?
- status = if_getdrvflags(ifp) & IFF_DRV_RUNNING ? 0 : 1;
+ status = ctx->ifc_datapath_state == IFLIB_DP_RUNNING ? 0 : 1;
if (status)
nm_clear_native_flags(na);
CTX_UNLOCK(ctx);
@@ -2621,12 +2635,6 @@ static void
iflib_media_status(if_t ifp, struct ifmediareq *ifmr)
{
if_ctx_t ctx = if_getsoftc(ifp);
- bool oactive, running;
-
- STATE_LOCK(ctx);
- running = (if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_RUNNING);
- oactive = (if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_OACTIVE);
- STATE_UNLOCK(ctx);
CTX_LOCK(ctx);
if (ctx->ifc_pm_state != IFLIB_PM_ACTIVE) {
@@ -2640,8 +2648,7 @@ iflib_media_status(if_t ifp, struct ifmediareq *ifmr)
* _task_fn_admin(), so only do it if that's not running. That can be quite
* expensive on some drivers.
*/
- if ((!running && !oactive) &&
- !(ctx->ifc_sctx->isc_flags & IFLIB_ADMIN_ALWAYS_RUN)) {
+ if (!iflib_admin_enabled(ctx)) {
IFDI_UPDATE_ADMIN_STATUS(ctx);
}
IFDI_MEDIA_STATUS(ctx, ifmr);
@@ -4190,12 +4197,10 @@ _task_fn_admin(void *context, int pending)
if_softc_ctx_t sctx = &ctx->ifc_softc_ctx;
iflib_txq_t txq;
int i;
- bool oactive, running, do_reset, do_reset_if_up, do_watchdog;
+ bool do_reset, do_reset_if_up, do_watchdog;
bool in_detach;
STATE_LOCK(ctx);
- running = (if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_RUNNING);
- oactive = (if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_OACTIVE);
do_reset = (ctx->ifc_flags & IFC_DO_RESET);
do_reset_if_up = (ctx->ifc_flags & IFC_DO_RESET_IF_UP);
do_watchdog = (ctx->ifc_flags & IFC_DO_WATCHDOG);
@@ -4204,8 +4209,6 @@ _task_fn_admin(void *context, int pending)
IFC_DO_WATCHDOG);
STATE_UNLOCK(ctx);
- if ((!running && !oactive) && !(ctx->ifc_sctx->isc_flags & IFLIB_ADMIN_ALWAYS_RUN))
- return;
if (in_detach)
return;
KFAIL_POINT_CODE_COND(_debug_fail_point_iflib,
@@ -4215,7 +4218,8 @@ _task_fn_admin(void *context, int pending)
iflib_admin_task_fail_device) == 0, FAIL_POINT_NONSLEEPABLE, {});
CTX_LOCK(ctx);
- if (ctx->ifc_pm_state != IFLIB_PM_ACTIVE) {
+ if (ctx->ifc_pm_state != IFLIB_PM_ACTIVE ||
+ !iflib_admin_enabled(ctx)) {
CTX_UNLOCK(ctx);
return;
}
@@ -5853,7 +5857,7 @@ iflib_device_resume(device_t dev)
CTX_LOCK(ctx);
error = iflib_device_resume_locked(ctx);
- running = (if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_RUNNING) != 0;
+ running = ctx->ifc_datapath_state == IFLIB_DP_RUNNING;
CTX_UNLOCK(ctx);
if (running) {
for (int i = 0; i < NTXQSETS(ctx); i++, txq++)
@@ -5883,7 +5887,7 @@ iflib_device_iov_init_restart(device_t dev, uint16_t num_vfs,
{
if_ctx_t ctx;
if_t ifp;
- bool restart, running;
+ bool restart;
int error;
ctx = device_get_softc(dev);
@@ -5892,15 +5896,14 @@ iflib_device_iov_init_restart(device_t dev, uint16_t num_vfs,
CTX_LOCK(ctx);
/*
* Drivers which change the PF queue layout need the complete iflib
- * stop/init sequence around their IOV callback when the interface is
- * active. An administratively-down interface has no live queues to
- * quiesce, and must remain down after the new layout is installed.
- * Keep the transition within one context-lock critical section.
+ * stop/init sequence around their IOV callback. Administrative state
+ * and IFF_DRV_RUNNING do not establish that the queues are stopped:
+ * failed initialization or a pending watchdog reset can leave DMA
+ * active. Let iflib_stop() decide whether hardware needs quiescing,
+ * and preserve administrative state across the layout change.
*/
restart = (if_getflags(ifp) & IFF_UP) != 0;
- running = (if_getdrvflags(ifp) & IFF_DRV_RUNNING) != 0;
- if (restart || running)
- iflib_stop(ctx);
+ iflib_stop(ctx);
error = IFDI_IOV_INIT(ctx, num_vfs, params);
if (restart)
iflib_init_locked(ctx);