diff --git a/sys/net/iflib.h b/sys/net/iflib.h --- a/sys/net/iflib.h +++ b/sys/net/iflib.h @@ -426,6 +426,11 @@ * function. */ #define IFLIB_FEATURE_QUEUE_SELECT_V2 1400073 +/* + * Driver can create subinterfaces with their own Tx/Rx queues + * that all share a single device (or commonly, port) + */ +#define IFLIB_FEATURE_SUB_INTERFACES 1400083 /* * These enum values are used in iflib_needs_restart to indicate to iflib @@ -484,11 +489,14 @@ int iflib_device_register(device_t dev, void *softc, if_shared_ctx_t sctx, if_ctx_t *ctxp); int iflib_device_deregister(if_ctx_t); -int iflib_irq_alloc(if_ctx_t, if_irq_t, int, driver_filter_t, void *filter_arg, driver_intr_t, void *arg, const char *name); +int iflib_irq_alloc(if_ctx_t, if_irq_t, int, driver_filter_t, void *filter_arg, + driver_intr_t, void *arg, const char *name); int iflib_irq_alloc_generic(if_ctx_t ctx, if_irq_t irq, int rid, iflib_intr_type_t type, driver_filter_t *filter, void *filter_arg, int qid, const char *name); -void iflib_softirq_alloc_generic(if_ctx_t ctx, if_irq_t irq, iflib_intr_type_t type, void *arg, int qid, const char *name); +void iflib_softirq_alloc_generic(if_ctx_t ctx, if_irq_t irq, + iflib_intr_type_t type, void *arg, int qid, + const char *name); void iflib_irq_free(if_ctx_t ctx, if_irq_t irq); @@ -519,6 +527,7 @@ void iflib_add_int_delay_sysctl(if_ctx_t, const char *, const char *, if_int_delay_info_t, int, int); +uint16_t iflib_get_extra_msix_vectors_sysctl(if_ctx_t ctx); /* * Pseudo device support @@ -526,4 +535,11 @@ if_pseudo_t iflib_clone_register(if_shared_ctx_t); void iflib_clone_deregister(if_pseudo_t); +/* + * Sub-interface support + */ +int iflib_irq_alloc_generic_subctx(if_ctx_t ctx, if_ctx_t subctx, if_irq_t irq, + int rid, iflib_intr_type_t type, + driver_filter_t *filter, void *filter_arg, + int qid, const char *name); #endif /* __IFLIB_H_ */ diff --git a/sys/net/iflib.c b/sys/net/iflib.c --- a/sys/net/iflib.c +++ b/sys/net/iflib.c @@ -197,6 +197,7 @@ #define CORE_OFFSET_UNSPECIFIED 0xffff uint8_t ifc_sysctl_separate_txrx; uint8_t ifc_sysctl_use_logical_cores; + uint16_t ifc_sysctl_use_extra_msix_vectors; bool ifc_cpus_are_physical_cores; qidx_t ifc_sysctl_ntxds[8]; @@ -212,6 +213,7 @@ #define isc_legacy_intr ifc_txrx.ift_legacy_intr #define isc_txq_select ifc_txrx.ift_txq_select #define isc_txq_select_v2 ifc_txrx.ift_txq_select_v2 + eventhandler_tag ifc_vlan_attach_event; eventhandler_tag ifc_vlan_detach_event; struct ether_addr ifc_mac; @@ -272,6 +274,13 @@ return (ctx->ifc_sctx); } +uint16_t +iflib_get_extra_msix_vectors_sysctl(if_ctx_t ctx) +{ + + return (ctx->ifc_sysctl_use_extra_msix_vectors); +} + #define IP_ALIGNED(m) ((((uintptr_t)(m)->m_data) & 0x3) == 0x2) #define CACHE_PTR_INCREMENT (CACHE_LINE_SIZE/sizeof(void*)) #define CACHE_PTR_NEXT(ptr) ((void *)(((uintptr_t)(ptr)+CACHE_LINE_SIZE-1) & (CACHE_LINE_SIZE-1))) @@ -1469,8 +1478,8 @@ &dma->idi_tag); if (err) { device_printf(dev, - "%s: bus_dma_tag_create failed: %d\n", - __func__, err); + "%s: bus_dma_tag_create failed: %d (size=%d, align=%d)\n", + __func__, err, size, align); goto fail_0; } @@ -1961,7 +1970,7 @@ lowaddr = DMA_WIDTH_TO_BUS_LOWADDR(scctx->isc_dma_width); fl = rxq->ifr_fl; - for (int i = 0; i < rxq->ifr_nfl; i++, fl++) { + for (int i = 0; i < rxq->ifr_nfl; i++, fl++) { fl->ifl_size = scctx->isc_nrxd[rxq->ifr_fl_offset]; /* this isn't necessarily the same */ /* Set up DMA tag for RX buffers. */ err = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ @@ -2483,7 +2492,6 @@ 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; @@ -2513,7 +2521,7 @@ if (if_getcapenable(ifp) & IFCAP_TSO6) if_sethwassistbits(ifp, CSUM_IP6_TSO, 0); - for (i = 0, txq = ctx->ifc_txqs; i < sctx->isc_ntxqsets; i++, txq++) { + for (i = 0, txq = ctx->ifc_txqs; i < scctx->isc_ntxqsets; i++, txq++) { CALLOUT_LOCK(txq); callout_stop(&txq->ift_timer); #ifdef DEV_NETMAP @@ -2535,7 +2543,7 @@ #endif IFDI_INIT(ctx); MPASS(if_getdrvflags(ifp) == i); - for (i = 0, rxq = ctx->ifc_rxqs; i < sctx->isc_nrxqsets; i++, rxq++) { + for (i = 0, rxq = ctx->ifc_rxqs; i < scctx->isc_nrxqsets; i++, rxq++) { if (iflib_netmap_rxq_init(ctx, rxq) > 0) { /* This rxq is in netmap mode. Skip normal init. */ continue; @@ -2553,7 +2561,7 @@ if_setdrvflagbits(ctx->ifc_ifp, IFF_DRV_RUNNING, IFF_DRV_OACTIVE); IFDI_INTR_ENABLE(ctx); txq = ctx->ifc_txqs; - for (i = 0; i < sctx->isc_ntxqsets; i++, txq++) + for (i = 0; i < scctx->isc_ntxqsets; i++, txq++) callout_reset_on(&txq->ift_timer, iflib_timer_default, iflib_timer, txq, txq->ift_timer.c_cpu); @@ -6441,6 +6449,81 @@ return (0); } +/* + * Allocate a hardware interrupt for subctx using the parent (ctx)'s hardware + * resources. + * + * Similar to iflib_irq_alloc_generic(), but for interrupt type IFLIB_INTR_RXTX + * only. + * + * XXX: Could be removed if subctx's dev has its intr resource allocation + * methods replaced with custom ones? + */ +int +iflib_irq_alloc_generic_subctx(if_ctx_t ctx, if_ctx_t subctx, if_irq_t irq, + int rid, iflib_intr_type_t type, + driver_filter_t *filter, void *filter_arg, + int qid, const char *name) +{ + device_t dev, subdev; + struct grouptask *gtask; + struct taskqgroup *tqg; + iflib_filter_info_t info; + gtask_fn_t *fn; + int tqrid, err; + driver_filter_t *intr_fast; + void *q; + + MPASS(ctx != NULL); + MPASS(subctx != NULL); + + tqrid = rid; + dev = ctx->ifc_dev; + subdev = subctx->ifc_dev; + + switch (type) { + case IFLIB_INTR_RXTX: + q = &subctx->ifc_rxqs[qid]; + info = &subctx->ifc_rxqs[qid].ifr_filter_info; + gtask = &subctx->ifc_rxqs[qid].ifr_task; + tqg = qgroup_if_io_tqg; + fn = _task_fn_rx; + intr_fast = iflib_fast_intr_rxtx; + NET_GROUPTASK_INIT(gtask, 0, fn, q); + break; + default: + device_printf(dev, "%s: unknown net intr type for subctx %s (%d)\n", + __func__, device_get_nameunit(subdev), type); + return (EINVAL); + } + + info->ifi_filter = filter; + info->ifi_filter_arg = filter_arg; + info->ifi_task = gtask; + info->ifi_ctx = q; + + NET_GROUPTASK_INIT(gtask, 0, fn, q); + + /* Allocate interrupts from hardware using parent context */ + err = _iflib_irq_alloc(ctx, irq, rid, intr_fast, NULL, info, name); + if (err != 0) { + device_printf(dev, "_iflib_irq_alloc failed for subctx %s: %d\n", + device_get_nameunit(subdev), err); + return (err); + } + + if (tqrid != -1) { + err = iflib_irq_set_affinity(ctx, irq, type, qid, gtask, tqg, q, + name); + if (err) + return (err); + } else { + taskqgroup_attach(tqg, gtask, q, dev, irq->ii_res, name); + } + + return (0); +} + int iflib_irq_alloc_generic(if_ctx_t ctx, if_irq_t irq, int rid, iflib_intr_type_t type, driver_filter_t *filter, @@ -6530,7 +6613,8 @@ } void -iflib_softirq_alloc_generic(if_ctx_t ctx, if_irq_t irq, iflib_intr_type_t type, void *arg, int qid, const char *name) +iflib_softirq_alloc_generic(if_ctx_t ctx, if_irq_t irq, iflib_intr_type_t type, + void *arg, int qid, const char *name) { device_t dev; struct grouptask *gtask; @@ -7027,16 +7111,16 @@ SYSCTL_ADD_U16(ctx_list, oid_list, OID_AUTO, "override_ntxqs", CTLFLAG_RWTUN, &ctx->ifc_sysctl_ntxqs, 0, - "# of txqs to use, 0 => use default #"); + "# of txqs to use, 0 => use default #"); SYSCTL_ADD_U16(ctx_list, oid_list, OID_AUTO, "override_nrxqs", CTLFLAG_RWTUN, &ctx->ifc_sysctl_nrxqs, 0, - "# of rxqs to use, 0 => use default #"); + "# of rxqs to use, 0 => use default #"); SYSCTL_ADD_U16(ctx_list, oid_list, OID_AUTO, "override_qs_enable", CTLFLAG_RWTUN, &ctx->ifc_sysctl_qs_eq_override, 0, "permit #txq != #rxq"); SYSCTL_ADD_INT(ctx_list, oid_list, OID_AUTO, "disable_msix", - CTLFLAG_RWTUN, &ctx->ifc_softc_ctx.isc_disable_msix, 0, - "disable MSI-X (default 0)"); + CTLFLAG_RWTUN, &ctx->ifc_softc_ctx.isc_disable_msix, 0, + "disable MSI-X (default 0)"); SYSCTL_ADD_U16(ctx_list, oid_list, OID_AUTO, "rx_budget", CTLFLAG_RWTUN, &ctx->ifc_sysctl_rx_budget, 0, "set the RX budget"); @@ -7048,11 +7132,17 @@ CTLFLAG_RDTUN, &ctx->ifc_sysctl_core_offset, 0, "offset to start using cores at"); SYSCTL_ADD_U8(ctx_list, oid_list, OID_AUTO, "separate_txrx", - CTLFLAG_RDTUN, &ctx->ifc_sysctl_separate_txrx, 0, - "use separate cores for TX and RX"); + CTLFLAG_RDTUN, &ctx->ifc_sysctl_separate_txrx, 0, + "use separate cores for TX and RX"); SYSCTL_ADD_U8(ctx_list, oid_list, OID_AUTO, "use_logical_cores", CTLFLAG_RDTUN, &ctx->ifc_sysctl_use_logical_cores, 0, "try to make use of logical cores for TX and RX"); + SYSCTL_ADD_U16(ctx_list, oid_list, OID_AUTO, "use_extra_msix_vectors", + CTLFLAG_RDTUN, &ctx->ifc_sysctl_use_extra_msix_vectors, 0, + "try to allocate extra MSI-X vectors for runtime interface creation"); + SYSCTL_ADD_INT(ctx_list, oid_list, OID_AUTO, "allocated_msix_vectors", + CTLFLAG_RDTUN, &ctx->ifc_softc_ctx.isc_vectors, 0, + "total MSI-X vectors allocated by driver"); /* XXX change for per-queue sizes */ SYSCTL_ADD_PROC(ctx_list, oid_list, OID_AUTO, "override_ntxds",