diff --git a/sys/net/iflib.h b/sys/net/iflib.h --- a/sys/net/iflib.h +++ b/sys/net/iflib.h @@ -393,6 +393,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 1500014 /* * These enum values are used in iflib_needs_restart to indicate to iflib @@ -491,4 +496,11 @@ if_int_delay_info_t, int, int); uint16_t iflib_get_extra_msix_vectors_sysctl(if_ctx_t ctx); +/* + * 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 @@ -1469,8 +1469,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; } @@ -6199,6 +6199,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,