Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F166431461
D58266.id182220.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D58266.id182220.diff
View Options
diff --git a/sys/net/iflib.c b/sys/net/iflib.c
--- a/sys/net/iflib.c
+++ b/sys/net/iflib.c
@@ -312,6 +312,19 @@
/* The minimum descriptors per second before we start coalescing */
#define IFLIB_MIN_DESC_SEC 16384
#define IFLIB_DEFAULT_TX_UPDATE_FREQ 16
+/*
+ * Consecutive armed timer periods before a suspect TX queue is
+ * declared hung. A healthy queue on writeback-coalescing hardware
+ * (e.g. 8254x, TXDCTL.WTHRESH) shows armed runs of at most two
+ * periods (measured on 82541PI); a wedged queue stays armed until
+ * reset.
+ */
+#define IFLIB_WDOG_ARMED_PERIODS 4
+/*
+ * The queue states below, ift_qstatus, and ift_cleaned_prev no longer
+ * participate in the TX watchdog decision and are scheduled for
+ * removal.
+ */
#define IFLIB_QUEUE_IDLE 0
#define IFLIB_QUEUE_HUNG 1
#define IFLIB_QUEUE_WORKING 2
@@ -368,11 +381,14 @@
uint16_t ift_npending;
uint16_t ift_db_pending;
uint16_t ift_rs_pending;
+ qidx_t ift_outstanding_prev;
+ uint8_t ift_wdog_armed;
uint32_t ift_last_reclaim;
uint16_t ift_reclaim_thresh;
uint16_t ift_reclaim_ticks;
uint8_t ift_txd_size[8];
uint64_t ift_processed;
+ uint64_t ift_processed_prev;
uint64_t ift_cleaned;
uint64_t ift_cleaned_prev;
#if MEMORY_LOGGING
@@ -2403,25 +2419,80 @@
return;
/*
- ** Check on the state of the TX queue(s), this
- ** can be done without the lock because its RO
- ** and the HUNG state will be static if set.
- */
+ * Check on the state of the TX queue(s); this can be done
+ * without the lock: the counters the check reads are only
+ * advanced by the queue's tx task and a stale read just
+ * delays the verdict by one timer period.
+ */
if (this_tick - txq->ift_last_timer_tick >= iflib_timer_default) {
+ qidx_t outstanding;
+ bool frozen;
+
txq->ift_last_timer_tick = this_tick;
IFDI_TIMER(ctx, txq->ift_id);
- if ((txq->ift_qstatus == IFLIB_QUEUE_HUNG) &&
- ((txq->ift_cleaned_prev == txq->ift_cleaned) ||
- (sctx->isc_pause_frames == 0)))
- goto hung;
- if (txq->ift_qstatus != IFLIB_QUEUE_IDLE &&
- ifmp_ring_is_stalled(txq->ift_br)) {
- KASSERT(ctx->ifc_link_state == LINK_STATE_UP,
- ("queue can't be marked as hung if interface is down"));
- txq->ift_qstatus = IFLIB_QUEUE_HUNG;
+ /*
+ * Descriptors handed to the hardware for which a
+ * completion writeback is still owed: those neither
+ * harvested as credits (ift_processed) nor reclaimed
+ * (ift_cleaned accounts the difference to ift_in_use).
+ * The tail whose report-status request is still
+ * deferred (ift_rs_pending over-counts it by one per
+ * packet) never writes back and must not count as
+ * owed.
+ */
+ outstanding = txq->ift_in_use -
+ (qidx_t)(txq->ift_processed - txq->ift_cleaned);
+
+ /*
+ * A period is frozen if writeback-owed work exists
+ * and no completions were harvested since the last
+ * period, with the link up, no pause frames seen,
+ * and no doorbell pending (the laggard check below
+ * rings it).
+ *
+ * Frozen alone is a normal state: hardware with
+ * descriptor-writeback coalescing (e.g. 8254x,
+ * TXDCTL.WTHRESH) legitimately withholds the final
+ * report-status writeback of a quiet queue
+ * indefinitely, so a constant owed tail must never
+ * trigger the watchdog. Only a queue that received
+ * new work across a frozen period (the owed count
+ * grew) arms, and the verdict waits until it has
+ * stayed frozen for IFLIB_WDOG_ARMED_PERIODS
+ * consecutive periods.
+ */
+ frozen = outstanding > txq->ift_rs_pending &&
+ txq->ift_processed == txq->ift_processed_prev &&
+ txq->ift_db_pending == 0 &&
+ sctx->isc_pause_frames == 0 &&
+ ctx->ifc_link_state == LINK_STATE_UP;
+ if (!frozen)
+ txq->ift_wdog_armed = 0;
+ else if (txq->ift_wdog_armed > 0 ||
+ outstanding > txq->ift_outstanding_prev) {
+ if (txq->ift_wdog_armed < UINT8_MAX)
+ txq->ift_wdog_armed++;
}
- txq->ift_cleaned_prev = txq->ift_cleaned;
+
+ /*
+ * Armed long enough - ask the hardware: if
+ * completions are ready but nobody harvested them
+ * for this long, the completion interrupt went
+ * missing - kick the queue's task instead of
+ * resetting; if it reported nothing although the
+ * owed count grew, the queue is hung.
+ */
+ if (txq->ift_wdog_armed >= IFLIB_WDOG_ARMED_PERIODS) {
+ bus_dmamap_sync(txq->ift_ifdi->idi_tag,
+ txq->ift_ifdi->idi_map, BUS_DMASYNC_POSTREAD);
+ if (ctx->isc_txd_credits_update(ctx->ifc_softc,
+ txq->ift_id, false) == 0)
+ goto hung;
+ GROUPTASK_ENQUEUE(&txq->ift_task);
+ }
+ txq->ift_outstanding_prev = outstanding;
+ txq->ift_processed_prev = txq->ift_processed;
}
/* handle any laggards */
if (txq->ift_db_pending)
@@ -2625,6 +2696,9 @@
iflib_txsd_free(ctx, txq, j);
}
txq->ift_processed = txq->ift_cleaned = txq->ift_cidx_processed = 0;
+ txq->ift_processed_prev = 0;
+ txq->ift_outstanding_prev = 0;
+ txq->ift_wdog_armed = 0;
txq->ift_in_use = txq->ift_gen = txq->ift_no_desc_avail = 0;
if (sctx->isc_flags & IFLIB_PRESERVE_TX_INDICES)
txq->ift_cidx = txq->ift_pidx;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Aug 14, 1:20 PM (10 h, 22 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35275397
Default Alt Text
D58266.id182220.diff (5 KB)
Attached To
Mode
D58266: iflib: restore TX watchdog functionality
Attached
Detach File
Event Timeline
Log In to Comment