Lines 346-351
struct iflib_txq {
Link Here
|
346 |
qidx_t ift_size; |
346 |
qidx_t ift_size; |
347 |
uint16_t ift_id; |
347 |
uint16_t ift_id; |
348 |
struct callout ift_timer; |
348 |
struct callout ift_timer; |
|
|
349 |
#ifdef DEV_NETMAP |
350 |
struct callout ift_netmap_timer; |
351 |
#endif /* DEV_NETMAP */ |
349 |
|
352 |
|
350 |
if_txsd_vec_t ift_sds; |
353 |
if_txsd_vec_t ift_sds; |
351 |
uint8_t ift_qstatus; |
354 |
uint8_t ift_qstatus; |
Lines 753-758
iflib_num_tx_descs(if_ctx_t ctx)
Link Here
|
753 |
MODULE_DEPEND(iflib, netmap, 1, 1, 1); |
756 |
MODULE_DEPEND(iflib, netmap, 1, 1, 1); |
754 |
|
757 |
|
755 |
static int netmap_fl_refill(iflib_rxq_t rxq, struct netmap_kring *kring, bool init); |
758 |
static int netmap_fl_refill(iflib_rxq_t rxq, struct netmap_kring *kring, bool init); |
|
|
759 |
static void iflib_netmap_timer(void *arg); |
756 |
|
760 |
|
757 |
/* |
761 |
/* |
758 |
* device-specific sysctl variables: |
762 |
* device-specific sysctl variables: |
Lines 918-923
netmap_fl_refill(iflib_rxq_t rxq, struct netmap_kring *kring, bool init)
Link Here
|
918 |
return (0); |
922 |
return (0); |
919 |
} |
923 |
} |
920 |
|
924 |
|
|
|
925 |
#define NETMAP_TX_TIMER_US 90 |
926 |
|
921 |
/* |
927 |
/* |
922 |
* Reconcile kernel and user view of the transmit ring. |
928 |
* Reconcile kernel and user view of the transmit ring. |
923 |
* |
929 |
* |
Lines 1047-1055
iflib_netmap_txsync(struct netmap_kring *kring, int flags)
Link Here
|
1047 |
* Second part: reclaim buffers for completed transmissions. |
1053 |
* Second part: reclaim buffers for completed transmissions. |
1048 |
* |
1054 |
* |
1049 |
* If there are unclaimed buffers, attempt to reclaim them. |
1055 |
* If there are unclaimed buffers, attempt to reclaim them. |
1050 |
* If none are reclaimed, and TX IRQs are not in use, do an initial |
1056 |
* If we don't manage to reclaim them all, and TX IRQs are not in use, |
1051 |
* minimal delay, then trigger the tx handler which will spin in the |
1057 |
* trigger a per-tx-queue timer to try again later. |
1052 |
* group task queue. |
|
|
1053 |
*/ |
1058 |
*/ |
1054 |
if (kring->nr_hwtail != nm_prev(kring->nr_hwcur, lim)) { |
1059 |
if (kring->nr_hwtail != nm_prev(kring->nr_hwcur, lim)) { |
1055 |
if (iflib_tx_credits_update(ctx, txq)) { |
1060 |
if (iflib_tx_credits_update(ctx, txq)) { |
Lines 1058-1068
iflib_netmap_txsync(struct netmap_kring *kring, int flags)
Link Here
|
1058 |
kring->nr_hwtail = nm_prev(netmap_idx_n2k(kring, nic_i), lim); |
1063 |
kring->nr_hwtail = nm_prev(netmap_idx_n2k(kring, nic_i), lim); |
1059 |
} |
1064 |
} |
1060 |
} |
1065 |
} |
|
|
1066 |
|
1061 |
if (!(ctx->ifc_flags & IFC_NETMAP_TX_IRQ)) |
1067 |
if (!(ctx->ifc_flags & IFC_NETMAP_TX_IRQ)) |
1062 |
if (kring->nr_hwtail != nm_prev(kring->nr_hwcur, lim)) { |
1068 |
if (kring->nr_hwtail != nm_prev(kring->nr_hwcur, lim)) { |
1063 |
callout_reset_on(&txq->ift_timer, hz < 2000 ? 1 : hz / 1000, |
1069 |
callout_reset_sbt_on(&txq->ift_netmap_timer, |
1064 |
iflib_timer, txq, txq->ift_timer.c_cpu); |
1070 |
NETMAP_TX_TIMER_US * SBT_1US, SBT_1US, |
1065 |
} |
1071 |
iflib_netmap_timer, txq, |
|
|
1072 |
txq->ift_netmap_timer.c_cpu, 0); |
1073 |
} |
1066 |
return (0); |
1074 |
return (0); |
1067 |
} |
1075 |
} |
1068 |
|
1076 |
|
Lines 1263-1290
iflib_netmap_rxq_init(if_ctx_t ctx, iflib_rxq_t rxq)
Link Here
|
1263 |
} |
1271 |
} |
1264 |
|
1272 |
|
1265 |
static void |
1273 |
static void |
1266 |
iflib_netmap_timer_adjust(if_ctx_t ctx, iflib_txq_t txq, uint32_t *reset_on) |
1274 |
iflib_netmap_timer(void *arg) |
1267 |
{ |
1275 |
{ |
1268 |
struct netmap_kring *kring; |
1276 |
iflib_txq_t txq = arg; |
1269 |
uint16_t txqid; |
1277 |
if_ctx_t ctx = txq->ift_ctx; |
1270 |
|
|
|
1271 |
txqid = txq->ift_id; |
1272 |
kring = netmap_kring_on(NA(ctx->ifc_ifp), txqid, NR_TX); |
1273 |
if (kring == NULL) |
1274 |
return; |
1275 |
|
1278 |
|
1276 |
if (kring->nr_hwcur != nm_next(kring->nr_hwtail, kring->nkr_num_slots - 1)) { |
1279 |
/* |
1277 |
bus_dmamap_sync(txq->ift_ifdi->idi_tag, txq->ift_ifdi->idi_map, |
1280 |
* Wake up the netmap application, to give it a chance to |
1278 |
BUS_DMASYNC_POSTREAD); |
1281 |
* call txsync and reclaim more completed TX buffers. |
1279 |
if (ctx->isc_txd_credits_update(ctx->ifc_softc, txqid, false)) |
1282 |
*/ |
1280 |
netmap_tx_irq(ctx->ifc_ifp, txqid); |
1283 |
netmap_tx_irq(ctx->ifc_ifp, txq->ift_id); |
1281 |
if (!(ctx->ifc_flags & IFC_NETMAP_TX_IRQ)) { |
|
|
1282 |
if (hz < 2000) |
1283 |
*reset_on = 1; |
1284 |
else |
1285 |
*reset_on = hz / 1000; |
1286 |
} |
1287 |
} |
1288 |
} |
1284 |
} |
1289 |
|
1285 |
|
1290 |
#define iflib_netmap_detach(ifp) netmap_detach(ifp) |
1286 |
#define iflib_netmap_detach(ifp) netmap_detach(ifp) |
Lines 1296-1303
iflib_netmap_timer_adjust(if_ctx_t ctx, iflib_txq_t txq, uint32_t *reset_on)
Link Here
|
1296 |
|
1292 |
|
1297 |
#define iflib_netmap_attach(ctx) (0) |
1293 |
#define iflib_netmap_attach(ctx) (0) |
1298 |
#define netmap_rx_irq(ifp, qid, budget) (0) |
1294 |
#define netmap_rx_irq(ifp, qid, budget) (0) |
1299 |
#define netmap_tx_irq(ifp, qid) do {} while (0) |
|
|
1300 |
#define iflib_netmap_timer_adjust(ctx, txq, reset_on) |
1301 |
#endif |
1295 |
#endif |
1302 |
|
1296 |
|
1303 |
#if defined(__i386__) || defined(__amd64__) |
1297 |
#if defined(__i386__) || defined(__amd64__) |
Lines 2287-2293
iflib_timer(void *arg)
Link Here
|
2287 |
if_ctx_t ctx = txq->ift_ctx; |
2281 |
if_ctx_t ctx = txq->ift_ctx; |
2288 |
if_softc_ctx_t sctx = &ctx->ifc_softc_ctx; |
2282 |
if_softc_ctx_t sctx = &ctx->ifc_softc_ctx; |
2289 |
uint64_t this_tick = ticks; |
2283 |
uint64_t this_tick = ticks; |
2290 |
uint32_t reset_on = hz / 2; |
|
|
2291 |
|
2284 |
|
2292 |
if (!(if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_RUNNING)) |
2285 |
if (!(if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_RUNNING)) |
2293 |
return; |
2286 |
return; |
Lines 2312-2328
iflib_timer(void *arg)
Link Here
|
2312 |
} |
2305 |
} |
2313 |
txq->ift_cleaned_prev = txq->ift_cleaned; |
2306 |
txq->ift_cleaned_prev = txq->ift_cleaned; |
2314 |
} |
2307 |
} |
2315 |
#ifdef DEV_NETMAP |
|
|
2316 |
if (if_getcapenable(ctx->ifc_ifp) & IFCAP_NETMAP) |
2317 |
iflib_netmap_timer_adjust(ctx, txq, &reset_on); |
2318 |
#endif |
2319 |
/* handle any laggards */ |
2308 |
/* handle any laggards */ |
2320 |
if (txq->ift_db_pending) |
2309 |
if (txq->ift_db_pending) |
2321 |
GROUPTASK_ENQUEUE(&txq->ift_task); |
2310 |
GROUPTASK_ENQUEUE(&txq->ift_task); |
2322 |
|
2311 |
|
2323 |
sctx->isc_pause_frames = 0; |
2312 |
sctx->isc_pause_frames = 0; |
2324 |
if (if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_RUNNING) |
2313 |
if (if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_RUNNING) |
2325 |
callout_reset_on(&txq->ift_timer, reset_on, iflib_timer, txq, txq->ift_timer.c_cpu); |
2314 |
callout_reset_on(&txq->ift_timer, hz / 2, iflib_timer, txq, txq->ift_timer.c_cpu); |
2326 |
return; |
2315 |
return; |
2327 |
|
2316 |
|
2328 |
hung: |
2317 |
hung: |
Lines 2396-2401
iflib_init_locked(if_ctx_t ctx)
Link Here
|
2396 |
for (i = 0, txq = ctx->ifc_txqs; i < sctx->isc_ntxqsets; i++, txq++) { |
2385 |
for (i = 0, txq = ctx->ifc_txqs; i < sctx->isc_ntxqsets; i++, txq++) { |
2397 |
CALLOUT_LOCK(txq); |
2386 |
CALLOUT_LOCK(txq); |
2398 |
callout_stop(&txq->ift_timer); |
2387 |
callout_stop(&txq->ift_timer); |
|
|
2388 |
#ifdef DEV_NETMAP |
2389 |
callout_stop(&txq->ift_netmap_timer); |
2390 |
#endif /* DEV_NETMAP */ |
2399 |
CALLOUT_UNLOCK(txq); |
2391 |
CALLOUT_UNLOCK(txq); |
2400 |
iflib_netmap_txq_init(ctx, txq); |
2392 |
iflib_netmap_txq_init(ctx, txq); |
2401 |
} |
2393 |
} |
Lines 2485-2490
iflib_stop(if_ctx_t ctx)
Link Here
|
2485 |
|
2477 |
|
2486 |
CALLOUT_LOCK(txq); |
2478 |
CALLOUT_LOCK(txq); |
2487 |
callout_stop(&txq->ift_timer); |
2479 |
callout_stop(&txq->ift_timer); |
|
|
2480 |
#ifdef DEV_NETMAP |
2481 |
callout_stop(&txq->ift_netmap_timer); |
2482 |
#endif /* DEV_NETMAP */ |
2488 |
CALLOUT_UNLOCK(txq); |
2483 |
CALLOUT_UNLOCK(txq); |
2489 |
|
2484 |
|
2490 |
/* clean any enqueued buffers */ |
2485 |
/* clean any enqueued buffers */ |
Lines 3882-3888
_task_fn_admin(void *context)
Link Here
|
3882 |
iflib_txq_t txq; |
3877 |
iflib_txq_t txq; |
3883 |
int i; |
3878 |
int i; |
3884 |
bool oactive, running, do_reset, do_watchdog, in_detach; |
3879 |
bool oactive, running, do_reset, do_watchdog, in_detach; |
3885 |
uint32_t reset_on = hz / 2; |
|
|
3886 |
|
3880 |
|
3887 |
STATE_LOCK(ctx); |
3881 |
STATE_LOCK(ctx); |
3888 |
running = (if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_RUNNING); |
3882 |
running = (if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_RUNNING); |
Lines 3910-3921
_task_fn_admin(void *context)
Link Here
|
3910 |
} |
3904 |
} |
3911 |
IFDI_UPDATE_ADMIN_STATUS(ctx); |
3905 |
IFDI_UPDATE_ADMIN_STATUS(ctx); |
3912 |
for (txq = ctx->ifc_txqs, i = 0; i < sctx->isc_ntxqsets; i++, txq++) { |
3906 |
for (txq = ctx->ifc_txqs, i = 0; i < sctx->isc_ntxqsets; i++, txq++) { |
3913 |
#ifdef DEV_NETMAP |
3907 |
callout_reset_on(&txq->ift_timer, hz / 2, iflib_timer, txq, |
3914 |
reset_on = hz / 2; |
3908 |
txq->ift_timer.c_cpu); |
3915 |
if (if_getcapenable(ctx->ifc_ifp) & IFCAP_NETMAP) |
|
|
3916 |
iflib_netmap_timer_adjust(ctx, txq, &reset_on); |
3917 |
#endif |
3918 |
callout_reset_on(&txq->ift_timer, reset_on, iflib_timer, txq, txq->ift_timer.c_cpu); |
3919 |
} |
3909 |
} |
3920 |
IFDI_LINK_INTR_ENABLE(ctx); |
3910 |
IFDI_LINK_INTR_ENABLE(ctx); |
3921 |
if (do_reset) |
3911 |
if (do_reset) |
Lines 5088-5093
iflib_pseudo_deregister(if_ctx_t ctx)
Link Here
|
5088 |
tqg = qgroup_if_io_tqg; |
5078 |
tqg = qgroup_if_io_tqg; |
5089 |
for (txq = ctx->ifc_txqs, i = 0; i < NTXQSETS(ctx); i++, txq++) { |
5079 |
for (txq = ctx->ifc_txqs, i = 0; i < NTXQSETS(ctx); i++, txq++) { |
5090 |
callout_drain(&txq->ift_timer); |
5080 |
callout_drain(&txq->ift_timer); |
|
|
5081 |
#ifdef DEV_NETMAP |
5082 |
callout_drain(&txq->ift_netmap_timer); |
5083 |
#endif /* DEV_NETMAP */ |
5091 |
if (txq->ift_task.gt_uniq != NULL) |
5084 |
if (txq->ift_task.gt_uniq != NULL) |
5092 |
taskqgroup_detach(tqg, &txq->ift_task); |
5085 |
taskqgroup_detach(tqg, &txq->ift_task); |
5093 |
} |
5086 |
} |
Lines 5174-5179
iflib_device_deregister(if_ctx_t ctx)
Link Here
|
5174 |
tqg = qgroup_if_io_tqg; |
5167 |
tqg = qgroup_if_io_tqg; |
5175 |
for (txq = ctx->ifc_txqs, i = 0; i < NTXQSETS(ctx); i++, txq++) { |
5168 |
for (txq = ctx->ifc_txqs, i = 0; i < NTXQSETS(ctx); i++, txq++) { |
5176 |
callout_drain(&txq->ift_timer); |
5169 |
callout_drain(&txq->ift_timer); |
|
|
5170 |
#ifdef DEV_NETMAP |
5171 |
callout_drain(&txq->ift_netmap_timer); |
5172 |
#endif /* DEV_NETMAP */ |
5177 |
if (txq->ift_task.gt_uniq != NULL) |
5173 |
if (txq->ift_task.gt_uniq != NULL) |
5178 |
taskqgroup_detach(tqg, &txq->ift_task); |
5174 |
taskqgroup_detach(tqg, &txq->ift_task); |
5179 |
} |
5175 |
} |
Lines 5583-5590
iflib_queues_alloc(if_ctx_t ctx)
Link Here
|
5583 |
} else { |
5579 |
} else { |
5584 |
txq->ift_br_offset = 0; |
5580 |
txq->ift_br_offset = 0; |
5585 |
} |
5581 |
} |
5586 |
/* XXX fix this */ |
|
|
5587 |
txq->ift_timer.c_cpu = cpu; |
5588 |
|
5582 |
|
5589 |
if (iflib_txsd_alloc(txq)) { |
5583 |
if (iflib_txsd_alloc(txq)) { |
5590 |
device_printf(dev, "Critical Failure setting up TX buffers\n"); |
5584 |
device_printf(dev, "Critical Failure setting up TX buffers\n"); |
Lines 5597-5602
iflib_queues_alloc(if_ctx_t ctx)
Link Here
|
5597 |
device_get_nameunit(dev), txq->ift_id); |
5591 |
device_get_nameunit(dev), txq->ift_id); |
5598 |
mtx_init(&txq->ift_mtx, txq->ift_mtx_name, NULL, MTX_DEF); |
5592 |
mtx_init(&txq->ift_mtx, txq->ift_mtx_name, NULL, MTX_DEF); |
5599 |
callout_init_mtx(&txq->ift_timer, &txq->ift_mtx, 0); |
5593 |
callout_init_mtx(&txq->ift_timer, &txq->ift_mtx, 0); |
|
|
5594 |
txq->ift_timer.c_cpu = cpu; |
5595 |
#ifdef DEV_NETMAP |
5596 |
callout_init_mtx(&txq->ift_netmap_timer, &txq->ift_mtx, 0); |
5597 |
txq->ift_netmap_timer.c_cpu = cpu; |
5598 |
#endif /* DEV_NETMAP */ |
5600 |
|
5599 |
|
5601 |
err = ifmp_ring_alloc(&txq->ift_br, 2048, txq, iflib_txq_drain, |
5600 |
err = ifmp_ring_alloc(&txq->ift_br, 2048, txq, iflib_txq_drain, |
5602 |
iflib_txq_can_drain, M_IFLIB, M_WAITOK); |
5601 |
iflib_txq_can_drain, M_IFLIB, M_WAITOK); |