diff options
author | Sean Bruno <sbruno@FreeBSD.org> | 2017-01-02 00:56:33 +0000 |
---|---|---|
committer | Sean Bruno <sbruno@FreeBSD.org> | 2017-01-02 00:56:33 +0000 |
commit | 1248952a50b5a86b4b4e0a825f2e4d3c4426b8ce (patch) | |
tree | 149814b4a4201e7b77f0fb99304e4e23b4754cf2 /sys/net/iflib.c | |
parent | 1569205f0a37ee3f1a06bfabacb9f3b804df2730 (diff) | |
download | src-1248952a50b5a86b4b4e0a825f2e4d3c4426b8ce.tar.gz src-1248952a50b5a86b4b4e0a825f2e4d3c4426b8ce.zip |
Notes
Diffstat (limited to 'sys/net/iflib.c')
-rw-r--r-- | sys/net/iflib.c | 137 |
1 files changed, 99 insertions, 38 deletions
diff --git a/sys/net/iflib.c b/sys/net/iflib.c index 25f5c741a883..beeddcf6fabb 100644 --- a/sys/net/iflib.c +++ b/sys/net/iflib.c @@ -355,6 +355,9 @@ struct iflib_txq { char ift_mtx_name[MTX_NAME_LEN]; char ift_db_mtx_name[MTX_NAME_LEN]; bus_dma_segment_t ift_segs[IFLIB_MAX_TX_SEGS] __aligned(CACHE_LINE_SIZE); +#ifdef IFLIB_DIAGNOSTICS + uint64_t ift_cpu_exec_count[256]; +#endif } __aligned(CACHE_LINE_SIZE); struct iflib_fl { @@ -431,6 +434,9 @@ struct iflib_rxq { iflib_dma_info_t ifr_ifdi; /* dynamically allocate if any drivers need a value substantially larger than this */ struct if_rxd_frag ifr_frags[IFLIB_MAX_RX_SEGS] __aligned(CACHE_LINE_SIZE); +#ifdef IFLIB_DIAGNOSTICS + uint64_t ifr_cpu_exec_count[256]; +#endif } __aligned(CACHE_LINE_SIZE); /* @@ -632,7 +638,7 @@ static void iflib_init_locked(if_ctx_t ctx); static void iflib_add_device_sysctl_pre(if_ctx_t ctx); static void iflib_add_device_sysctl_post(if_ctx_t ctx); static void iflib_ifmp_purge(iflib_txq_t txq); - +static void _iflib_pre_assert(if_softc_ctx_t scctx); #ifdef DEV_NETMAP #include <sys/selinfo.h> @@ -684,7 +690,7 @@ iflib_netmap_register(struct netmap_adapter *na, int onoff) ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); if (!CTX_IS_VF(ctx)) - IFDI_CRCSTRIP_SET(ctx, onoff); + IFDI_CRCSTRIP_SET(ctx, onoff, iflib_crcstrip); /* enable or disable flags and callbacks in na and ifp */ if (onoff) { @@ -693,7 +699,7 @@ iflib_netmap_register(struct netmap_adapter *na, int onoff) nm_clear_native_flags(na); } IFDI_INIT(ctx); - IFDI_CRCSTRIP_SET(ctx, onoff); // XXX why twice ? + IFDI_CRCSTRIP_SET(ctx, onoff, iflib_crcstrip); // XXX why twice ? CTX_UNLOCK(ctx); return (ifp->if_drv_flags & IFF_DRV_RUNNING ? 0 : 1); } @@ -1192,6 +1198,9 @@ iflib_fast_intr(void *arg) iflib_filter_info_t info = arg; struct grouptask *gtask = info->ifi_task; + if (!smp_started) + return (FILTER_HANDLED); + DBG_COUNTER_INC(fast_intrs); if (info->ifi_filter != NULL && info->ifi_filter(info->ifi_filter_arg) == FILTER_HANDLED) return (FILTER_HANDLED); @@ -1410,7 +1419,7 @@ iflib_txq_setup(iflib_txq_t txq) iflib_dma_info_t di; int i; - /* Set number of descriptors available */ + /* Set number of descriptors available */ txq->ift_qstatus = IFLIB_QUEUE_IDLE; /* Reset indices */ @@ -1833,22 +1842,25 @@ static void iflib_init_locked(if_ctx_t ctx) { if_softc_ctx_t sctx = &ctx->ifc_softc_ctx; + if_softc_ctx_t scctx = &ctx->ifc_softc_ctx; if_t ifp = ctx->ifc_ifp; iflib_fl_t fl; iflib_txq_t txq; iflib_rxq_t rxq; - int i, j; + int i, j, tx_ip_csum_flags, tx_ip6_csum_flags; if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, IFF_DRV_RUNNING); IFDI_INTR_DISABLE(ctx); + tx_ip_csum_flags = scctx->isc_tx_csum_flags & (CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_SCTP); + tx_ip6_csum_flags = scctx->isc_tx_csum_flags & (CSUM_IP6_TCP | CSUM_IP6_UDP | CSUM_IP6_SCTP); /* Set hardware offload abilities */ if_clearhwassist(ifp); if (if_getcapenable(ifp) & IFCAP_TXCSUM) - if_sethwassistbits(ifp, CSUM_IP | CSUM_TCP | CSUM_UDP, 0); + if_sethwassistbits(ifp, tx_ip_csum_flags, 0); if (if_getcapenable(ifp) & IFCAP_TXCSUM_IPV6) - if_sethwassistbits(ifp, (CSUM_TCP_IPV6 | CSUM_UDP_IPV6), 0); + if_sethwassistbits(ifp, tx_ip6_csum_flags, 0); if (if_getcapenable(ifp) & IFCAP_TSO4) if_sethwassistbits(ifp, CSUM_IP_TSO, 0); if (if_getcapenable(ifp) & IFCAP_TSO6) @@ -2258,10 +2270,21 @@ print_pkt(if_pkt_info_t pi) static int iflib_parse_header(iflib_txq_t txq, if_pkt_info_t pi, struct mbuf **mp) { + if_shared_ctx_t sctx = txq->ift_ctx->ifc_sctx; struct ether_vlan_header *eh; struct mbuf *m, *n; n = m = *mp; + if ((sctx->isc_flags & IFLIB_NEED_SCRATCH) && + M_WRITABLE(m) == 0) { + if ((m = m_dup(m, M_NOWAIT)) == NULL) { + return (ENOMEM); + } else { + m_freem(*mp); + n = *mp = m; + } + } + /* * Determine where frame payload starts. * Jump over vlan headers if already present, @@ -2345,6 +2368,10 @@ iflib_parse_header(iflib_txq_t txq, if_pkt_info_t pi, struct mbuf **mp) th->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, htons(IPPROTO_TCP)); pi->ipi_tso_segsz = m->m_pkthdr.tso_segsz; + if (sctx->isc_flags & IFLIB_TSO_INIT_IP) { + ip->ip_sum = 0; + ip->ip_len = htons(pi->ipi_ip_hlen + pi->ipi_tcp_hlen + pi->ipi_tso_segsz); + } } break; } @@ -2396,10 +2423,10 @@ iflib_parse_header(iflib_txq_t txq, if_pkt_info_t pi, struct mbuf **mp) break; } *mp = m; + return (0); } - static __noinline struct mbuf * collapse_pkthdr(struct mbuf *m0) { @@ -2688,6 +2715,11 @@ defrag: ndesc += txq->ift_size; txq->ift_gen = 1; } + /* + * drivers can need as many as + * two sentinels + */ + MPASS(ndesc <= pi.ipi_nsegs + 2); MPASS(pi.ipi_new_pidx != pidx); MPASS(ndesc > 0); txq->ift_in_use += ndesc; @@ -2855,7 +2887,7 @@ iflib_txq_can_drain(struct ifmp_ring *r) iflib_txq_t txq = r->cookie; if_ctx_t ctx = txq->ift_ctx; - return ((TXQ_AVAIL(txq) >= MAX_TX_DESC(ctx)) || + return ((TXQ_AVAIL(txq) > MAX_TX_DESC(ctx) + 2) || ctx->isc_txd_credits_update(ctx->ifc_softc, txq->ift_id, txq->ift_cidx_processed, false)); } @@ -2930,13 +2962,13 @@ iflib_txq_drain(struct ifmp_ring *r, uint32_t cidx, uint32_t pidx) if (__predict_false(!(if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_RUNNING))) break; - if (desc_used > TXQ_MAX_DB_CONSUMED(txq->ift_size)) + if (desc_used >= TXQ_MAX_DB_CONSUMED(txq->ift_size)) break; } if ((iflib_min_tx_latency || iflib_txq_min_occupancy(txq)) && txq->ift_db_pending) iflib_txd_db_check(ctx, txq, TRUE); - else if ((txq->ift_db_pending || TXQ_AVAIL(txq) < MAX_TX_DESC(ctx)) && + else if ((txq->ift_db_pending || TXQ_AVAIL(txq) <= MAX_TX_DESC(ctx) + 2) && (callout_pending(&txq->ift_db_check) == 0)) { txq->ift_db_pending_queued = txq->ift_db_pending; callout_reset_on(&txq->ift_db_check, 1, iflib_txd_deferred_db_check, @@ -3004,6 +3036,9 @@ _task_fn_tx(void *context) iflib_txq_t txq = context; if_ctx_t ctx = txq->ift_ctx; +#ifdef IFLIB_DIAGNOSTICS + txq->ift_cpu_exec_count[curcpu]++; +#endif if (!(if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_RUNNING)) return; ifmp_ring_check_drainage(txq->ift_br[0], TX_BATCH_SIZE); @@ -3017,6 +3052,9 @@ _task_fn_rx(void *context) bool more; int rc; +#ifdef IFLIB_DIAGNOSTICS + rxq->ifr_cpu_exec_count[curcpu]++; +#endif DBG_COUNTER_INC(task_fn_rxs); if (__predict_false(!(if_getdrvflags(ctx->ifc_ifp) & IFF_DRV_RUNNING))) return; @@ -3520,7 +3558,6 @@ iflib_device_register(device_t dev, void *sc, if_shared_ctx_t sctx, if_ctx_t *ct ctx->ifc_sctx = sctx; ctx->ifc_dev = dev; - ctx->ifc_txrx = *sctx->isc_txrx; ctx->ifc_softc = sc; if ((err = iflib_register(ctx)) != 0) { @@ -3530,6 +3567,8 @@ iflib_device_register(device_t dev, void *sc, if_shared_ctx_t sctx, if_ctx_t *ct iflib_add_device_sysctl_pre(ctx); scctx = &ctx->ifc_softc_ctx; + ifp = ctx->ifc_ifp; + /* * XXX sanity check that ntxd & nrxd are a power of 2 */ @@ -3582,10 +3621,22 @@ iflib_device_register(device_t dev, void *sc, if_shared_ctx_t sctx, if_ctx_t *ct device_printf(dev, "IFDI_ATTACH_PRE failed %d\n", err); return (err); } - if (scctx->isc_ntxqsets_max) - scctx->isc_ntxqsets = min(scctx->isc_ntxqsets, scctx->isc_ntxqsets_max); - if (scctx->isc_nrxqsets_max) - scctx->isc_nrxqsets = min(scctx->isc_nrxqsets, scctx->isc_nrxqsets_max); + _iflib_pre_assert(scctx); + ctx->ifc_txrx = *scctx->isc_txrx; + +#ifdef INVARIANTS + MPASS(scctx->isc_capenable); + if (scctx->isc_capenable & IFCAP_TXCSUM) + MPASS(scctx->isc_tx_csum_flags); +#endif + + if_setcapabilities(ifp, scctx->isc_capenable); + if_setcapenable(ifp, scctx->isc_capenable); + + if (scctx->isc_ntxqsets == 0 || (scctx->isc_ntxqsets_max && scctx->isc_ntxqsets_max < scctx->isc_ntxqsets)) + scctx->isc_ntxqsets = scctx->isc_ntxqsets_max; + if (scctx->isc_nrxqsets == 0 || (scctx->isc_nrxqsets_max && scctx->isc_nrxqsets_max < scctx->isc_nrxqsets)) + scctx->isc_nrxqsets = scctx->isc_nrxqsets_max; #ifdef ACPI_DMAR if (dmar_get_dma_tag(device_get_parent(dev), dev) != NULL) @@ -3594,8 +3645,6 @@ iflib_device_register(device_t dev, void *sc, if_shared_ctx_t sctx, if_ctx_t *ct msix_bar = scctx->isc_msix_bar; - ifp = ctx->ifc_ifp; - if(sctx->isc_flags & IFLIB_HAS_TXCQ) main_txq = 1; else @@ -3679,6 +3728,7 @@ iflib_device_register(device_t dev, void *sc, if_shared_ctx_t sctx, if_ctx_t *ct goto fail_queues; } + IFDI_INTR_DISABLE(ctx); if (msix > 1 && (err = IFDI_MSIX_INTR_ASSIGN(ctx, msix)) != 0) { device_printf(dev, "IFDI_MSIX_INTR_ASSIGN failed %d\n", err); goto fail_intr_free; @@ -3948,15 +3998,6 @@ _iflib_assert(if_shared_ctx_t sctx) MPASS(sctx->isc_rx_nsegments); MPASS(sctx->isc_rx_maxsegsize); - - MPASS(sctx->isc_txrx->ift_txd_encap); - MPASS(sctx->isc_txrx->ift_txd_flush); - MPASS(sctx->isc_txrx->ift_txd_credits_update); - MPASS(sctx->isc_txrx->ift_rxd_available); - MPASS(sctx->isc_txrx->ift_rxd_pkt_get); - MPASS(sctx->isc_txrx->ift_rxd_refill); - MPASS(sctx->isc_txrx->ift_rxd_flush); - MPASS(sctx->isc_nrxd_min[0]); MPASS(sctx->isc_nrxd_max[0]); MPASS(sctx->isc_nrxd_default[0]); @@ -3965,9 +4006,18 @@ _iflib_assert(if_shared_ctx_t sctx) MPASS(sctx->isc_ntxd_default[0]); } -#define DEFAULT_CAPS (IFCAP_TXCSUM_IPV6 | IFCAP_RXCSUM_IPV6 | IFCAP_HWCSUM | IFCAP_LRO | \ - IFCAP_TSO4 | IFCAP_TSO6 | IFCAP_VLAN_HWTAGGING | \ - IFCAP_VLAN_MTU | IFCAP_VLAN_HWFILTER | IFCAP_VLAN_HWTSO | IFCAP_HWSTATS) +static void +_iflib_pre_assert(if_softc_ctx_t scctx) +{ + + MPASS(scctx->isc_txrx->ift_txd_encap); + MPASS(scctx->isc_txrx->ift_txd_flush); + MPASS(scctx->isc_txrx->ift_txd_credits_update); + MPASS(scctx->isc_txrx->ift_rxd_available); + MPASS(scctx->isc_txrx->ift_rxd_pkt_get); + MPASS(scctx->isc_txrx->ift_rxd_refill); + MPASS(scctx->isc_txrx->ift_rxd_flush); +} static int iflib_register(if_ctx_t ctx) @@ -4003,10 +4053,6 @@ iflib_register(if_ctx_t ctx) if_setqflushfn(ifp, iflib_if_qflush); if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); - /* XXX - move this in to the driver for non-default settings */ - if_setcapabilities(ifp, DEFAULT_CAPS); - if_setcapenable(ifp, DEFAULT_CAPS); - ctx->ifc_vlan_attach_event = EVENTHANDLER_REGISTER(vlan_config, iflib_vlan_register, ctx, EVENTHANDLER_PRI_FIRST); @@ -4507,6 +4553,13 @@ iflib_legacy_setup(if_ctx_t ctx, driver_filter_t filter, void *filter_arg, int * void *q; int err; + /* + * group taskqueues aren't properly set up until SMP is started + * so we disable interrupts until we can handle them post + * SI_SUB_SMP + */ + IFDI_INTR_DISABLE(ctx); + q = &ctx->ifc_rxqs[0]; info = &rxq[0].ifr_filter_info; gtask = &rxq[0].ifr_task; @@ -4527,9 +4580,6 @@ iflib_legacy_setup(if_ctx_t ctx, driver_filter_t filter, void *filter_arg, int * GROUPTASK_INIT(&txq->ift_task, 0, _task_fn_tx, txq); taskqgroup_attach(qgroup_if_io_tqg, &txq->ift_task, txq, tqrid, "tx"); - GROUPTASK_INIT(&ctx->ifc_admin_task, 0, _task_fn_admin, ctx); - taskqgroup_attach(qgroup_if_config_tqg, &ctx->ifc_admin_task, ctx, -1, "admin/link"); - return (0); } @@ -4558,6 +4608,12 @@ iflib_rx_intr_deferred(if_ctx_t ctx, int rxqid) void iflib_admin_intr_deferred(if_ctx_t ctx) { +#ifdef INVARIANTS + struct grouptask *gtask; + + gtask = &ctx->ifc_admin_task; + MPASS(gtask->gt_taskqueue != NULL); +#endif GROUPTASK_ENQUEUE(&ctx->ifc_admin_task); } @@ -4598,7 +4654,6 @@ iflib_link_state_change(if_ctx_t ctx, int link_state, uint64_t baudrate) if_t ifp = ctx->ifc_ifp; iflib_txq_t txq = ctx->ifc_txqs; - if_setbaudrate(ifp, baudrate); /* If link down, disable watchdog */ @@ -4614,6 +4669,9 @@ static int iflib_tx_credits_update(if_ctx_t ctx, iflib_txq_t txq) { int credits; +#ifdef INVARIANTS + int credits_pre = txq->ift_cidx_processed; +#endif if (ctx->isc_txd_credits_update == NULL) return (0); @@ -4624,6 +4682,7 @@ iflib_tx_credits_update(if_ctx_t ctx, iflib_txq_t txq) txq->ift_processed += credits; txq->ift_cidx_processed += credits; + MPASS(credits_pre + credits == txq->ift_cidx_processed); if (txq->ift_cidx_processed >= txq->ift_size) txq->ift_cidx_processed -= txq->ift_size; return (credits); @@ -4671,6 +4730,8 @@ iflib_msix_init(if_ctx_t ctx) iflib_num_tx_queues = scctx->isc_ntxqsets; iflib_num_rx_queues = scctx->isc_nrxqsets; + device_printf(dev, "msix_init qsets capped at %d\n", iflib_num_tx_queues); + bar = ctx->ifc_softc_ctx.isc_msix_bar; admincnt = sctx->isc_admin_intrcnt; /* Override by tuneable */ |