Changeset View
Changeset View
Standalone View
Standalone View
head/sys/net/iflib.c
Show First 20 Lines • Show All 954 Lines • ▼ Show 20 Lines | iflib_netmap_txsync(struct netmap_kring *kring, int flags) | ||||
* If possible do not set the report/intr bit on all slots, | * If possible do not set the report/intr bit on all slots, | ||||
* but only a few times per ring or when NS_REPORT is set. | * but only a few times per ring or when NS_REPORT is set. | ||||
* | * | ||||
* Finally, on 10G and faster drivers, it might be useful | * Finally, on 10G and faster drivers, it might be useful | ||||
* to prefetch the next slot and txr entry. | * to prefetch the next slot and txr entry. | ||||
*/ | */ | ||||
nm_i = netmap_idx_n2k(kring, kring->nr_hwcur); | nm_i = netmap_idx_n2k(kring, kring->nr_hwcur); | ||||
if (nm_i != head) { /* we have new packets to send */ | |||||
pkt_info_zero(&pi); | pkt_info_zero(&pi); | ||||
pi.ipi_segs = txq->ift_segs; | pi.ipi_segs = txq->ift_segs; | ||||
pi.ipi_qsidx = kring->ring_id; | pi.ipi_qsidx = kring->ring_id; | ||||
if (nm_i != head) { /* we have new packets to send */ | |||||
nic_i = netmap_idx_k2n(kring, nm_i); | nic_i = netmap_idx_k2n(kring, nm_i); | ||||
__builtin_prefetch(&ring->slot[nm_i]); | __builtin_prefetch(&ring->slot[nm_i]); | ||||
__builtin_prefetch(&txq->ift_sds.ifsd_m[nic_i]); | __builtin_prefetch(&txq->ift_sds.ifsd_m[nic_i]); | ||||
if (txq->ift_sds.ifsd_map) | if (txq->ift_sds.ifsd_map) | ||||
__builtin_prefetch(&txq->ift_sds.ifsd_map[nic_i]); | __builtin_prefetch(&txq->ift_sds.ifsd_map[nic_i]); | ||||
for (n = 0; nm_i != head; n++) { | for (n = 0; nm_i != head; n++) { | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | if (txq->ift_sds.ifsd_map) | ||||
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | ||||
/* (re)start the tx unit up to slot nic_i (excluded) */ | /* (re)start the tx unit up to slot nic_i (excluded) */ | ||||
ctx->isc_txd_flush(ctx->ifc_softc, txq->ift_id, nic_i); | ctx->isc_txd_flush(ctx->ifc_softc, txq->ift_id, nic_i); | ||||
} | } | ||||
/* | /* | ||||
* Second part: reclaim buffers for completed transmissions. | * Second part: reclaim buffers for completed transmissions. | ||||
* | |||||
* If there are unclaimed buffers, attempt to reclaim them. | |||||
* If none are reclaimed, and TX IRQs are not in use, do an initial | |||||
* minimal delay, then trigger the tx handler which will spin in the | |||||
* group task queue. | |||||
*/ | */ | ||||
if (kring->nr_hwtail != nm_prev(head, lim)) { | |||||
if (iflib_tx_credits_update(ctx, txq)) { | if (iflib_tx_credits_update(ctx, txq)) { | ||||
/* some tx completed, increment avail */ | /* some tx completed, increment avail */ | ||||
nic_i = txq->ift_cidx_processed; | nic_i = txq->ift_cidx_processed; | ||||
kring->nr_hwtail = nm_prev(netmap_idx_n2k(kring, nic_i), lim); | kring->nr_hwtail = nm_prev(netmap_idx_n2k(kring, nic_i), lim); | ||||
} | } | ||||
else { | |||||
if (!(ctx->ifc_flags & IFC_NETMAP_TX_IRQ)) { | |||||
DELAY(1); | |||||
GROUPTASK_ENQUEUE(&ctx->ifc_txqs[txq->ift_id].ift_task); | |||||
} | |||||
} | |||||
} | |||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Reconcile kernel and user view of the receive ring. | * Reconcile kernel and user view of the receive ring. | ||||
* Same as for the txsync, this routine must be efficient. | * Same as for the txsync, this routine must be efficient. | ||||
* The caller guarantees a single invocations, but races against | * The caller guarantees a single invocations, but races against | ||||
* the rest of the driver should be handled here. | * the rest of the driver should be handled here. | ||||
▲ Show 20 Lines • Show All 2,655 Lines • ▼ Show 20 Lines | _task_fn_tx(void *context) | ||||
struct ifnet *ifp = ctx->ifc_ifp; | struct ifnet *ifp = ctx->ifc_ifp; | ||||
#ifdef IFLIB_DIAGNOSTICS | #ifdef IFLIB_DIAGNOSTICS | ||||
txq->ift_cpu_exec_count[curcpu]++; | txq->ift_cpu_exec_count[curcpu]++; | ||||
#endif | #endif | ||||
if (!(if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_RUNNING)) | if (!(if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_RUNNING)) | ||||
return; | return; | ||||
if (if_getcapenable(ifp) & IFCAP_NETMAP) { | if (if_getcapenable(ifp) & IFCAP_NETMAP) { | ||||
/* | |||||
* If there are no available credits, and TX IRQs are not in use, | |||||
* re-schedule the task immediately. | |||||
*/ | |||||
if (ctx->isc_txd_credits_update(ctx->ifc_softc, txq->ift_id, false)) | if (ctx->isc_txd_credits_update(ctx->ifc_softc, txq->ift_id, false)) | ||||
netmap_tx_irq(ifp, txq->ift_id); | netmap_tx_irq(ifp, txq->ift_id); | ||||
else { | |||||
if (!(ctx->ifc_flags & IFC_NETMAP_TX_IRQ)) { | |||||
struct netmap_kring *kring = NA(ctx->ifc_ifp)->tx_rings[txq->ift_id]; | |||||
if (kring->nr_hwtail != nm_prev(kring->rhead, kring->nkr_num_slots - 1)) | |||||
GROUPTASK_ENQUEUE(&txq->ift_task); | |||||
} | |||||
} | |||||
IFDI_TX_QUEUE_INTR_ENABLE(ctx, txq->ift_id); | IFDI_TX_QUEUE_INTR_ENABLE(ctx, txq->ift_id); | ||||
return; | return; | ||||
} | } | ||||
if (txq->ift_db_pending) | if (txq->ift_db_pending) | ||||
ifmp_ring_enqueue(txq->ift_br, (void **)&txq, 1, TX_BATCH_SIZE); | ifmp_ring_enqueue(txq->ift_br, (void **)&txq, 1, TX_BATCH_SIZE); | ||||
ifmp_ring_check_drainage(txq->ift_br, TX_BATCH_SIZE); | ifmp_ring_check_drainage(txq->ift_br, TX_BATCH_SIZE); | ||||
if (ctx->ifc_flags & IFC_LEGACY) | if (ctx->ifc_flags & IFC_LEGACY) | ||||
IFDI_INTR_ENABLE(ctx); | IFDI_INTR_ENABLE(ctx); | ||||
▲ Show 20 Lines • Show All 1,828 Lines • ▼ Show 20 Lines | iflib_irq_alloc_generic(if_ctx_t ctx, if_irq_t irq, int rid, | ||||
case IFLIB_INTR_TX: | case IFLIB_INTR_TX: | ||||
q = &ctx->ifc_txqs[qid]; | q = &ctx->ifc_txqs[qid]; | ||||
info = &ctx->ifc_txqs[qid].ift_filter_info; | info = &ctx->ifc_txqs[qid].ift_filter_info; | ||||
gtask = &ctx->ifc_txqs[qid].ift_task; | gtask = &ctx->ifc_txqs[qid].ift_task; | ||||
tqg = qgroup_if_io_tqg; | tqg = qgroup_if_io_tqg; | ||||
fn = _task_fn_tx; | fn = _task_fn_tx; | ||||
intr_fast = iflib_fast_intr; | intr_fast = iflib_fast_intr; | ||||
GROUPTASK_INIT(gtask, 0, fn, q); | GROUPTASK_INIT(gtask, 0, fn, q); | ||||
ctx->ifc_flags |= IFC_NETMAP_TX_IRQ; | |||||
break; | break; | ||||
case IFLIB_INTR_RX: | case IFLIB_INTR_RX: | ||||
q = &ctx->ifc_rxqs[qid]; | q = &ctx->ifc_rxqs[qid]; | ||||
info = &ctx->ifc_rxqs[qid].ifr_filter_info; | info = &ctx->ifc_rxqs[qid].ifr_filter_info; | ||||
gtask = &ctx->ifc_rxqs[qid].ifr_task; | gtask = &ctx->ifc_rxqs[qid].ifr_task; | ||||
tqg = qgroup_if_io_tqg; | tqg = qgroup_if_io_tqg; | ||||
fn = _task_fn_rx; | fn = _task_fn_rx; | ||||
intr_fast = iflib_fast_intr; | intr_fast = iflib_fast_intr; | ||||
▲ Show 20 Lines • Show All 840 Lines • Show Last 20 Lines |