Changeset View
Changeset View
Standalone View
Standalone View
sys/net/iflib.c
Show First 20 Lines • Show All 579 Lines • ▼ Show 20 Lines | |||||
* XXX need to ensure that this can't accidentally cause the head to be moved backwards | * XXX need to ensure that this can't accidentally cause the head to be moved backwards | ||||
*/ | */ | ||||
static int iflib_min_tx_latency = 0; | static int iflib_min_tx_latency = 0; | ||||
SYSCTL_INT(_net_iflib, OID_AUTO, min_tx_latency, CTLFLAG_RW, | SYSCTL_INT(_net_iflib, OID_AUTO, min_tx_latency, CTLFLAG_RW, | ||||
&iflib_min_tx_latency, 0, "minimize transmit latency at the possible expense of throughput"); | &iflib_min_tx_latency, 0, "minimize transmit latency at the possible expense of throughput"); | ||||
static int iflib_no_tx_batch = 0; | static int iflib_no_tx_batch = 0; | ||||
SYSCTL_INT(_net_iflib, OID_AUTO, no_tx_batch, CTLFLAG_RW, | SYSCTL_INT(_net_iflib, OID_AUTO, no_tx_batch, CTLFLAG_RW, | ||||
&iflib_no_tx_batch, 0, "minimize transmit latency at the possible expense of throughput"); | &iflib_no_tx_batch, 0, "minimize transmit latency at the possible expense of throughput"); | ||||
static int iflib_timer_default = 1000; | |||||
SYSCTL_INT(_net_iflib, OID_AUTO, timer_default, CTLFLAG_RW, | |||||
&iflib_timer_default, 0, "number of ticks between iflib_timer calls"); | |||||
#if IFLIB_DEBUG_COUNTERS | #if IFLIB_DEBUG_COUNTERS | ||||
static int iflib_tx_seen; | static int iflib_tx_seen; | ||||
static int iflib_tx_sent; | static int iflib_tx_sent; | ||||
static int iflib_tx_encap; | static int iflib_tx_encap; | ||||
static int iflib_rx_allocs; | static int iflib_rx_allocs; | ||||
static int iflib_fl_refills; | static int iflib_fl_refills; | ||||
static int iflib_fl_refills_large; | static int iflib_fl_refills_large; | ||||
▲ Show 20 Lines • Show All 1,691 Lines • ▼ Show 20 Lines | iflib_timer(void *arg) | ||||
if (!(if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_RUNNING)) | if (!(if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_RUNNING)) | ||||
return; | return; | ||||
/* | /* | ||||
** Check on the state of the TX queue(s), this | ** Check on the state of the TX queue(s), this | ||||
** can be done without the lock because its RO | ** can be done without the lock because its RO | ||||
** and the HUNG state will be static if set. | ** and the HUNG state will be static if set. | ||||
*/ | */ | ||||
if (this_tick - txq->ift_last_timer_tick >= hz / 2) { | if (this_tick - txq->ift_last_timer_tick >= iflib_timer_default) { | ||||
txq->ift_last_timer_tick = this_tick; | txq->ift_last_timer_tick = this_tick; | ||||
IFDI_TIMER(ctx, txq->ift_id); | IFDI_TIMER(ctx, txq->ift_id); | ||||
if ((txq->ift_qstatus == IFLIB_QUEUE_HUNG) && | if ((txq->ift_qstatus == IFLIB_QUEUE_HUNG) && | ||||
((txq->ift_cleaned_prev == txq->ift_cleaned) || | ((txq->ift_cleaned_prev == txq->ift_cleaned) || | ||||
(sctx->isc_pause_frames == 0))) | (sctx->isc_pause_frames == 0))) | ||||
goto hung; | goto hung; | ||||
if (txq->ift_qstatus != IFLIB_QUEUE_IDLE && | if (txq->ift_qstatus != IFLIB_QUEUE_IDLE && | ||||
ifmp_ring_is_stalled(txq->ift_br)) { | 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")); | 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; | txq->ift_qstatus = IFLIB_QUEUE_HUNG; | ||||
} | } | ||||
txq->ift_cleaned_prev = txq->ift_cleaned; | txq->ift_cleaned_prev = txq->ift_cleaned; | ||||
} | } | ||||
/* handle any laggards */ | /* handle any laggards */ | ||||
if (txq->ift_db_pending) | if (txq->ift_db_pending) | ||||
GROUPTASK_ENQUEUE(&txq->ift_task); | GROUPTASK_ENQUEUE(&txq->ift_task); | ||||
sctx->isc_pause_frames = 0; | sctx->isc_pause_frames = 0; | ||||
if (if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_RUNNING) | if (if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_RUNNING) | ||||
callout_reset_on(&txq->ift_timer, hz / 2, iflib_timer, txq, txq->ift_timer.c_cpu); | callout_reset_on(&txq->ift_timer, iflib_timer_default, iflib_timer, | ||||
txq, txq->ift_timer.c_cpu); | |||||
return; | return; | ||||
hung: | hung: | ||||
device_printf(ctx->ifc_dev, | device_printf(ctx->ifc_dev, | ||||
"Watchdog timeout (TX: %d desc avail: %d pidx: %d) -- resetting\n", | "Watchdog timeout (TX: %d desc avail: %d pidx: %d) -- resetting\n", | ||||
txq->ift_id, TXQ_AVAIL(txq), txq->ift_pidx); | txq->ift_id, TXQ_AVAIL(txq), txq->ift_pidx); | ||||
STATE_LOCK(ctx); | STATE_LOCK(ctx); | ||||
if_setdrvflagbits(ctx->ifc_ifp, IFF_DRV_OACTIVE, IFF_DRV_RUNNING); | if_setdrvflagbits(ctx->ifc_ifp, IFF_DRV_OACTIVE, IFF_DRV_RUNNING); | ||||
▲ Show 20 Lines • Show All 95 Lines • ▼ Show 20 Lines | for (j = 0, fl = rxq->ifr_fl; j < rxq->ifr_nfl; j++, fl++) { | ||||
} | } | ||||
} | } | ||||
} | } | ||||
done: | done: | ||||
if_setdrvflagbits(ctx->ifc_ifp, IFF_DRV_RUNNING, IFF_DRV_OACTIVE); | if_setdrvflagbits(ctx->ifc_ifp, IFF_DRV_RUNNING, IFF_DRV_OACTIVE); | ||||
IFDI_INTR_ENABLE(ctx); | IFDI_INTR_ENABLE(ctx); | ||||
txq = ctx->ifc_txqs; | txq = ctx->ifc_txqs; | ||||
for (i = 0; i < sctx->isc_ntxqsets; i++, txq++) | for (i = 0; i < sctx->isc_ntxqsets; i++, txq++) | ||||
callout_reset_on(&txq->ift_timer, hz/2, iflib_timer, txq, | callout_reset_on(&txq->ift_timer, iflib_timer_default, iflib_timer, txq, | ||||
txq->ift_timer.c_cpu); | txq->ift_timer.c_cpu); | ||||
} | } | ||||
static int | static int | ||||
iflib_media_change(if_t ifp) | iflib_media_change(if_t ifp) | ||||
{ | { | ||||
if_ctx_t ctx = if_getsoftc(ifp); | if_ctx_t ctx = if_getsoftc(ifp); | ||||
int err; | int err; | ||||
▲ Show 20 Lines • Show All 558 Lines • ▼ Show 20 Lines | |||||
#define FIRST_QSET(ctx) 0 | #define FIRST_QSET(ctx) 0 | ||||
#define NTXQSETS(ctx) ((ctx)->ifc_softc_ctx.isc_ntxqsets) | #define NTXQSETS(ctx) ((ctx)->ifc_softc_ctx.isc_ntxqsets) | ||||
#define NRXQSETS(ctx) ((ctx)->ifc_softc_ctx.isc_nrxqsets) | #define NRXQSETS(ctx) ((ctx)->ifc_softc_ctx.isc_nrxqsets) | ||||
#define QIDX(ctx, m) ((((m)->m_pkthdr.flowid & ctx->ifc_softc_ctx.isc_rss_table_mask) % NTXQSETS(ctx)) + FIRST_QSET(ctx)) | #define QIDX(ctx, m) ((((m)->m_pkthdr.flowid & ctx->ifc_softc_ctx.isc_rss_table_mask) % NTXQSETS(ctx)) + FIRST_QSET(ctx)) | ||||
#define DESC_RECLAIMABLE(q) ((int)((q)->ift_processed - (q)->ift_cleaned - (q)->ift_ctx->ifc_softc_ctx.isc_tx_nsegments)) | #define DESC_RECLAIMABLE(q) ((int)((q)->ift_processed - (q)->ift_cleaned - (q)->ift_ctx->ifc_softc_ctx.isc_tx_nsegments)) | ||||
/* XXX we should be setting this to something other than zero */ | /* XXX we should be setting this to something other than zero */ | ||||
#define RECLAIM_THRESH(ctx) ((ctx)->ifc_sctx->isc_tx_reclaim_thresh) | #define RECLAIM_THRESH(ctx) ((ctx)->ifc_sctx->isc_tx_reclaim_thresh) | ||||
#define MAX_TX_DESC(ctx) max((ctx)->ifc_softc_ctx.isc_tx_tso_segments_max, \ | #define MAX_TX_DESC(ctx) MAX((ctx)->ifc_softc_ctx.isc_tx_tso_segments_max, \ | ||||
(ctx)->ifc_softc_ctx.isc_tx_nsegments) | (ctx)->ifc_softc_ctx.isc_tx_nsegments) | ||||
static inline bool | static inline bool | ||||
iflib_txd_db_check(if_ctx_t ctx, iflib_txq_t txq, int ring, qidx_t in_use) | iflib_txd_db_check(iflib_txq_t txq, int ring) | ||||
{ | { | ||||
if_ctx_t ctx = txq->ift_ctx; | |||||
qidx_t dbval, max; | qidx_t dbval, max; | ||||
bool rang; | |||||
rang = false; | max = TXQ_MAX_DB_DEFERRED(txq, txq->ift_in_use); | ||||
max = TXQ_MAX_DB_DEFERRED(txq, in_use); | |||||
if (ring || txq->ift_db_pending >= max) { | /* force || threshold exceeded || at the edge of the ring */ | ||||
if (ring || (txq->ift_db_pending >= max) || (TXQ_AVAIL(txq) <= MAX_TX_DESC(ctx) + 2)) { | |||||
/* | |||||
* 'npending' is used if the card's doorbell is in terms of the number of descriptors | |||||
* pending flush (BRCM). 'pidx' is used in cases where the card's doorbeel uses the | |||||
* producer index explicitly (INTC). | |||||
*/ | |||||
dbval = txq->ift_npending ? txq->ift_npending : txq->ift_pidx; | dbval = txq->ift_npending ? txq->ift_npending : txq->ift_pidx; | ||||
bus_dmamap_sync(txq->ift_ifdi->idi_tag, txq->ift_ifdi->idi_map, | bus_dmamap_sync(txq->ift_ifdi->idi_tag, txq->ift_ifdi->idi_map, | ||||
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | ||||
ctx->isc_txd_flush(ctx->ifc_softc, txq->ift_id, dbval); | ctx->isc_txd_flush(ctx->ifc_softc, txq->ift_id, dbval); | ||||
/* | |||||
* Absent bugs there are zero packets pending so reset pending counts to zero. | |||||
*/ | |||||
txq->ift_db_pending = txq->ift_npending = 0; | txq->ift_db_pending = txq->ift_npending = 0; | ||||
rang = true; | return (true); | ||||
} | } | ||||
return (rang); | return (false); | ||||
} | } | ||||
#ifdef PKT_DEBUG | #ifdef PKT_DEBUG | ||||
static void | static void | ||||
print_pkt(if_pkt_info_t pi) | print_pkt(if_pkt_info_t pi) | ||||
{ | { | ||||
printf("pi len: %d qsidx: %d nsegs: %d ndescs: %d flags: %x pidx: %d\n", | printf("pi len: %d qsidx: %d nsegs: %d ndescs: %d flags: %x pidx: %d\n", | ||||
pi->ipi_len, pi->ipi_qsidx, pi->ipi_nsegs, pi->ipi_ndescs, pi->ipi_flags, pi->ipi_pidx); | pi->ipi_len, pi->ipi_qsidx, pi->ipi_nsegs, pi->ipi_ndescs, pi->ipi_flags, pi->ipi_pidx); | ||||
▲ Show 20 Lines • Show All 444 Lines • ▼ Show 20 Lines | if ((err = ctx->isc_txd_encap(ctx->ifc_softc, &pi)) == 0) { | ||||
/* | /* | ||||
* drivers can need as many as | * drivers can need as many as | ||||
* two sentinels | * two sentinels | ||||
*/ | */ | ||||
MPASS(ndesc <= pi.ipi_nsegs + 2); | MPASS(ndesc <= pi.ipi_nsegs + 2); | ||||
MPASS(pi.ipi_new_pidx != pidx); | MPASS(pi.ipi_new_pidx != pidx); | ||||
MPASS(ndesc > 0); | MPASS(ndesc > 0); | ||||
txq->ift_in_use += ndesc; | txq->ift_in_use += ndesc; | ||||
txq->ift_db_pending += ndesc; | |||||
/* | /* | ||||
* We update the last software descriptor again here because there may | * We update the last software descriptor again here because there may | ||||
* be a sentinel and/or there may be more mbufs than segments | * be a sentinel and/or there may be more mbufs than segments | ||||
*/ | */ | ||||
txq->ift_pidx = pi.ipi_new_pidx; | txq->ift_pidx = pi.ipi_new_pidx; | ||||
txq->ift_npending += pi.ipi_ndescs; | txq->ift_npending += pi.ipi_ndescs; | ||||
} else { | } else { | ||||
▲ Show 20 Lines • Show All 150 Lines • ▼ Show 20 Lines | |||||
static uint32_t | static uint32_t | ||||
iflib_txq_drain(struct ifmp_ring *r, uint32_t cidx, uint32_t pidx) | iflib_txq_drain(struct ifmp_ring *r, uint32_t cidx, uint32_t pidx) | ||||
{ | { | ||||
iflib_txq_t txq = r->cookie; | iflib_txq_t txq = r->cookie; | ||||
if_ctx_t ctx = txq->ift_ctx; | if_ctx_t ctx = txq->ift_ctx; | ||||
if_t ifp = ctx->ifc_ifp; | if_t ifp = ctx->ifc_ifp; | ||||
struct mbuf *m, **mp; | struct mbuf *m, **mp; | ||||
int avail, bytes_sent, consumed, count, err, i, in_use_prev; | int avail, bytes_sent, skipped, count, err, i; | ||||
int mcast_sent, pkt_sent, reclaimed, txq_avail; | int mcast_sent, pkt_sent, reclaimed; | ||||
bool do_prefetch, rang, ring; | bool do_prefetch, rang, ring; | ||||
if (__predict_false(!(if_getdrvflags(ifp) & IFF_DRV_RUNNING) || | if (__predict_false(!(if_getdrvflags(ifp) & IFF_DRV_RUNNING) || | ||||
!LINK_ACTIVE(ctx))) { | !LINK_ACTIVE(ctx))) { | ||||
DBG_COUNTER_INC(txq_drain_notready); | DBG_COUNTER_INC(txq_drain_notready); | ||||
return (0); | return (0); | ||||
} | } | ||||
reclaimed = iflib_completed_tx_reclaim(txq, RECLAIM_THRESH(ctx)); | reclaimed = iflib_completed_tx_reclaim(txq, RECLAIM_THRESH(ctx)); | ||||
rang = iflib_txd_db_check(ctx, txq, reclaimed, txq->ift_in_use); | rang = iflib_txd_db_check(txq, reclaimed && txq->ift_db_pending); | ||||
avail = IDXDIFF(pidx, cidx, r->size); | avail = IDXDIFF(pidx, cidx, r->size); | ||||
if (__predict_false(ctx->ifc_flags & IFC_QFLUSH)) { | if (__predict_false(ctx->ifc_flags & IFC_QFLUSH)) { | ||||
/* | |||||
* The driver is unloading so we need to free all pending packets. | |||||
*/ | |||||
DBG_COUNTER_INC(txq_drain_flushing); | DBG_COUNTER_INC(txq_drain_flushing); | ||||
for (i = 0; i < avail; i++) { | for (i = 0; i < avail; i++) { | ||||
if (__predict_true(r->items[(cidx + i) & (r->size-1)] != (void *)txq)) | if (__predict_true(r->items[(cidx + i) & (r->size-1)] != (void *)txq)) | ||||
m_freem(r->items[(cidx + i) & (r->size-1)]); | m_freem(r->items[(cidx + i) & (r->size-1)]); | ||||
r->items[(cidx + i) & (r->size-1)] = NULL; | r->items[(cidx + i) & (r->size-1)] = NULL; | ||||
} | } | ||||
return (avail); | return (avail); | ||||
} | } | ||||
if (__predict_false(if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_OACTIVE)) { | if (__predict_false(if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_OACTIVE)) { | ||||
txq->ift_qstatus = IFLIB_QUEUE_IDLE; | txq->ift_qstatus = IFLIB_QUEUE_IDLE; | ||||
CALLOUT_LOCK(txq); | CALLOUT_LOCK(txq); | ||||
callout_stop(&txq->ift_timer); | callout_stop(&txq->ift_timer); | ||||
CALLOUT_UNLOCK(txq); | CALLOUT_UNLOCK(txq); | ||||
DBG_COUNTER_INC(txq_drain_oactive); | DBG_COUNTER_INC(txq_drain_oactive); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | |||||
* If we've reclaimed any packets this queue cannot be hung. | |||||
*/ | |||||
if (reclaimed) | if (reclaimed) | ||||
txq->ift_qstatus = IFLIB_QUEUE_IDLE; | txq->ift_qstatus = IFLIB_QUEUE_IDLE; | ||||
consumed = mcast_sent = bytes_sent = pkt_sent = 0; | skipped = mcast_sent = bytes_sent = pkt_sent = 0; | ||||
count = MIN(avail, TX_BATCH_SIZE); | count = MIN(avail, TX_BATCH_SIZE); | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
if (iflib_verbose_debug) | if (iflib_verbose_debug) | ||||
printf("%s avail=%d ifc_flags=%x txq_avail=%d ", __FUNCTION__, | printf("%s avail=%d ifc_flags=%x txq_avail=%d ", __FUNCTION__, | ||||
avail, ctx->ifc_flags, TXQ_AVAIL(txq)); | avail, ctx->ifc_flags, TXQ_AVAIL(txq)); | ||||
#endif | #endif | ||||
do_prefetch = (ctx->ifc_flags & IFC_PREFETCH); | do_prefetch = (ctx->ifc_flags & IFC_PREFETCH); | ||||
txq_avail = TXQ_AVAIL(txq); | |||||
err = 0; | err = 0; | ||||
for (i = 0; i < count && txq_avail > MAX_TX_DESC(ctx) + 2; i++) { | for (i = 0; i < count && TXQ_AVAIL(txq) >= MAX_TX_DESC(ctx) + 2; i++) { | ||||
int rem = do_prefetch ? count - i : 0; | int rem = do_prefetch ? count - i : 0; | ||||
mp = _ring_peek_one(r, cidx, i, rem); | mp = _ring_peek_one(r, cidx, i, rem); | ||||
MPASS(mp != NULL && *mp != NULL); | MPASS(mp != NULL && *mp != NULL); | ||||
/* | |||||
* Completion interrupts will use the address of the txq | |||||
* as a sentinel to enqueue _something_ in order to acquire | |||||
* the lock on the mp_ring (there's no direct lock call). | |||||
* We obviously whave to check for these sentinel cases | |||||
* and skip them. | |||||
*/ | |||||
if (__predict_false(*mp == (struct mbuf *)txq)) { | if (__predict_false(*mp == (struct mbuf *)txq)) { | ||||
consumed++; | skipped++; | ||||
continue; | continue; | ||||
} | } | ||||
in_use_prev = txq->ift_in_use; | |||||
err = iflib_encap(txq, mp); | err = iflib_encap(txq, mp); | ||||
if (__predict_false(err)) { | if (__predict_false(err)) { | ||||
/* no room - bail out */ | /* no room - bail out */ | ||||
if (err == ENOBUFS) | if (err == ENOBUFS) | ||||
break; | break; | ||||
consumed++; | skipped++; | ||||
/* we can't send this packet - skip it */ | /* we can't send this packet - skip it */ | ||||
continue; | continue; | ||||
} | } | ||||
consumed++; | |||||
pkt_sent++; | pkt_sent++; | ||||
m = *mp; | m = *mp; | ||||
DBG_COUNTER_INC(tx_sent); | DBG_COUNTER_INC(tx_sent); | ||||
bytes_sent += m->m_pkthdr.len; | bytes_sent += m->m_pkthdr.len; | ||||
mcast_sent += !!(m->m_flags & M_MCAST); | mcast_sent += !!(m->m_flags & M_MCAST); | ||||
txq_avail = TXQ_AVAIL(txq); | |||||
txq->ift_db_pending += (txq->ift_in_use - in_use_prev); | |||||
ETHER_BPF_MTAP(ifp, m); | |||||
if (__predict_false(!(ifp->if_drv_flags & IFF_DRV_RUNNING))) | if (__predict_false(!(ifp->if_drv_flags & IFF_DRV_RUNNING))) | ||||
break; | break; | ||||
rang = iflib_txd_db_check(ctx, txq, false, in_use_prev); | ETHER_BPF_MTAP(ifp, m); | ||||
rang = iflib_txd_db_check(txq, false); | |||||
} | } | ||||
/* deliberate use of bitwise or to avoid gratuitous short-circuit */ | /* deliberate use of bitwise or to avoid gratuitous short-circuit */ | ||||
ring = rang ? false : (iflib_min_tx_latency | err) || (TXQ_AVAIL(txq) < MAX_TX_DESC(ctx)); | ring = rang ? false : (iflib_min_tx_latency | err); | ||||
iflib_txd_db_check(ctx, txq, ring, txq->ift_in_use); | iflib_txd_db_check(txq, ring); | ||||
if_inc_counter(ifp, IFCOUNTER_OBYTES, bytes_sent); | if_inc_counter(ifp, IFCOUNTER_OBYTES, bytes_sent); | ||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, pkt_sent); | if_inc_counter(ifp, IFCOUNTER_OPACKETS, pkt_sent); | ||||
if (mcast_sent) | if (mcast_sent) | ||||
if_inc_counter(ifp, IFCOUNTER_OMCASTS, mcast_sent); | if_inc_counter(ifp, IFCOUNTER_OMCASTS, mcast_sent); | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
if (iflib_verbose_debug) | if (iflib_verbose_debug) | ||||
printf("consumed=%d\n", consumed); | printf("consumed=%d\n", skipped + pkt_sent); | ||||
#endif | #endif | ||||
return (consumed); | return (skipped + pkt_sent); | ||||
} | } | ||||
static uint32_t | static uint32_t | ||||
iflib_txq_drain_always(struct ifmp_ring *r) | iflib_txq_drain_always(struct ifmp_ring *r) | ||||
{ | { | ||||
return (1); | return (1); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 156 Lines • ▼ Show 20 Lines | for (txq = ctx->ifc_txqs, i = 0; i < sctx->isc_ntxqsets; i++, txq++) { | ||||
CALLOUT_UNLOCK(txq); | CALLOUT_UNLOCK(txq); | ||||
} | } | ||||
if (do_watchdog) { | if (do_watchdog) { | ||||
ctx->ifc_watchdog_events++; | ctx->ifc_watchdog_events++; | ||||
IFDI_WATCHDOG_RESET(ctx); | IFDI_WATCHDOG_RESET(ctx); | ||||
} | } | ||||
IFDI_UPDATE_ADMIN_STATUS(ctx); | IFDI_UPDATE_ADMIN_STATUS(ctx); | ||||
for (txq = ctx->ifc_txqs, i = 0; i < sctx->isc_ntxqsets; i++, txq++) { | for (txq = ctx->ifc_txqs, i = 0; i < sctx->isc_ntxqsets; i++, txq++) { | ||||
callout_reset_on(&txq->ift_timer, hz / 2, iflib_timer, txq, | callout_reset_on(&txq->ift_timer, iflib_timer_default, iflib_timer, txq, | ||||
txq->ift_timer.c_cpu); | txq->ift_timer.c_cpu); | ||||
} | } | ||||
IFDI_LINK_INTR_ENABLE(ctx); | IFDI_LINK_INTR_ENABLE(ctx); | ||||
if (do_reset) | if (do_reset) | ||||
iflib_if_init_locked(ctx); | iflib_if_init_locked(ctx); | ||||
CTX_UNLOCK(ctx); | CTX_UNLOCK(ctx); | ||||
if (LINK_ACTIVE(ctx) == 0) | if (LINK_ACTIVE(ctx) == 0) | ||||
▲ Show 20 Lines • Show All 1,377 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* - Start a fast taskqueue thread for each core | * - Start a fast taskqueue thread for each core | ||||
* - Start a taskqueue for control operations | * - Start a taskqueue for control operations | ||||
*/ | */ | ||||
static int | static int | ||||
iflib_module_init(void) | iflib_module_init(void) | ||||
{ | { | ||||
iflib_timer_default = hz / 2; | |||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
iflib_module_event_handler(module_t mod, int what, void *arg) | iflib_module_event_handler(module_t mod, int what, void *arg) | ||||
{ | { | ||||
int err; | int err; | ||||
▲ Show 20 Lines • Show All 1,544 Lines • ▼ Show 20 Lines | iflib_debugnet_transmit(if_t ifp, struct mbuf *m) | ||||
ctx = if_getsoftc(ifp); | ctx = if_getsoftc(ifp); | ||||
if ((if_getdrvflags(ifp) & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != | if ((if_getdrvflags(ifp) & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != | ||||
IFF_DRV_RUNNING) | IFF_DRV_RUNNING) | ||||
return (EBUSY); | return (EBUSY); | ||||
txq = &ctx->ifc_txqs[0]; | txq = &ctx->ifc_txqs[0]; | ||||
error = iflib_encap(txq, &m); | error = iflib_encap(txq, &m); | ||||
if (error == 0) | if (error == 0) | ||||
(void)iflib_txd_db_check(ctx, txq, true, txq->ift_in_use); | (void)iflib_txd_db_check(txq, true); | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
iflib_debugnet_poll(if_t ifp, int count) | iflib_debugnet_poll(if_t ifp, int count) | ||||
{ | { | ||||
struct epoch_tracker et; | struct epoch_tracker et; | ||||
if_ctx_t ctx; | if_ctx_t ctx; | ||||
Show All 21 Lines |