Page MenuHomeFreeBSD

D58266.diff
No OneTemporary

D58266.diff

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,11 @@
/* The minimum descriptors per second before we start coalescing */
#define IFLIB_MIN_DESC_SEC 16384
#define IFLIB_DEFAULT_TX_UPDATE_FREQ 16
+/*
+ * 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
@@ -364,7 +369,8 @@
uint8_t ift_gen;
uint8_t ift_br_offset:1,
ift_defer_mfree:1,
- ift_spare_bits0:6;
+ ift_wdog_pending_prev:1,
+ ift_spare_bits0:5;
uint16_t ift_npending;
uint16_t ift_db_pending;
uint16_t ift_rs_pending;
@@ -373,6 +379,7 @@
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 +2410,58 @@
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 pending;
+
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);
+ pending = outstanding > txq->ift_rs_pending;
+
+ /*
+ * The queue is suspect if writeback-owed work was
+ * outstanding across the entire timer period and no
+ * completions were harvested, with the link up, no
+ * pause frames seen, and no doorbell pending (the
+ * laggard check below rings it). Then ask the
+ * hardware: if it consumed nothing, the queue is
+ * hung; if completions are ready but nobody
+ * harvested them for a whole period, the completion
+ * interrupt went missing - kick the queue's task
+ * instead of resetting.
+ */
+ if (pending && txq->ift_wdog_pending_prev &&
+ txq->ift_processed == txq->ift_processed_prev &&
+ txq->ift_db_pending == 0 &&
+ sctx->isc_pause_frames == 0 &&
+ ctx->ifc_link_state == LINK_STATE_UP) {
+ 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_cleaned_prev = txq->ift_cleaned;
+ txq->ift_wdog_pending_prev = pending;
+ txq->ift_processed_prev = txq->ift_processed;
}
/* handle any laggards */
if (txq->ift_db_pending)
@@ -2625,6 +2665,8 @@
iflib_txsd_free(ctx, txq, j);
}
txq->ift_processed = txq->ift_cleaned = txq->ift_cidx_processed = 0;
+ txq->ift_processed_prev = 0;
+ txq->ift_wdog_pending_prev = 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

Mime Type
text/plain
Expires
Sat, Jul 18, 7:48 PM (6 h, 3 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35163605
Default Alt Text
D58266.diff (3 KB)

Event Timeline