git: 7fb00406ebf5 - main - iflib: Use private lifecycle state for control work
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 15 Sep 2026 18:30:30 UTC
The branch main has been updated by kbowling:
URL: https://cgit.FreeBSD.org/src/commit/?id=7fb00406ebf53e07273d0914a5f36ff6fb78c185
commit 7fb00406ebf53e07273d0914a5f36ff6fb78c185
Author: Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-09-11 18:57:42 +0000
Commit: Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-09-15 18:29:18 +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)
MFC after: 2 weeks
Sponsored by: BBOX.io
Differential Revision: https://reviews.freebsd.org/D59597
---
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 9979d17777ef..012c4ab5f54a 100644
--- a/sys/net/iflib.c
+++ b/sys/net/iflib.c
@@ -600,6 +600,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 *);
@@ -952,7 +966,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);
@@ -2843,12 +2857,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) {
@@ -2862,8 +2870,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);
@@ -4441,12 +4448,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);
@@ -4455,8 +4460,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,
@@ -4466,7 +4469,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;
}
@@ -6147,7 +6151,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++)
@@ -6177,7 +6181,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);
@@ -6186,15 +6190,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);