Index: sys/net/iflib.c =================================================================== --- sys/net/iflib.c +++ sys/net/iflib.c @@ -188,6 +188,8 @@ uint16_t ifc_sysctl_qs_eq_override; uint16_t ifc_sysctl_rx_budget; uint16_t ifc_sysctl_tx_abdicate; + uint16_t ifc_sysctl_core_offset; + uint8_t ifc_sysctl_separate_txrx; qidx_t ifc_sysctl_ntxds[8]; qidx_t ifc_sysctl_nrxds[8]; @@ -725,6 +727,16 @@ static struct mbuf * iflib_fixup_rx(struct mbuf *m); #endif +static SLIST_HEAD(cpu_offset_list, cpu_offset) cpu_offsets = + SLIST_HEAD_INITIALIZER(cpu_offsets); +struct cpu_offset { + SLIST_ENTRY(cpu_offset) entries; + cpuset_t set; + uint16_t offset; +}; +static struct mtx cpu_offset_mtx; +MTX_SYSINIT(iflib_cpu_offset, &cpu_offset_mtx, "iflib_cpu_offset lock", MTX_DEF); + NETDUMP_DEFINE(iflib); #ifdef DEV_NETMAP @@ -4366,6 +4378,51 @@ } } +static uint16_t get_ctx_core_offset(if_ctx_t ctx) +{ + if_softc_ctx_t scctx = &ctx->ifc_softc_ctx; + uint16_t qc; + struct cpu_offset *op; + uint16_t ret = ctx->ifc_sysctl_core_offset; + char kename[128]; + + /* XXX This is terrible... */ + sprintf(kename, "dev.%s.%d.iflib.core_offset", + device_get_name(ctx->ifc_dev), device_get_unit(ctx->ifc_dev)); + if (testenv(kename) == 0 && ret == 0) + ret = 0xffff; + if (ret != 0xffff) + return ret; + + if (ctx->ifc_sysctl_separate_txrx) + qc = scctx->isc_ntxqsets + scctx->isc_nrxqsets; + else + qc = max(scctx->isc_ntxqsets, scctx->isc_nrxqsets); + + mtx_lock(&cpu_offset_mtx); + SLIST_FOREACH(op, &cpu_offsets, entries) { + if (CPU_CMP(&ctx->ifc_cpus, &op->set) == 0) { + ret = op->offset; + op->offset += qc; + break; + } + } + if (ret == 0xffff) { + ret = 0; + op = malloc(sizeof(struct cpu_offset), M_IFLIB, + M_NOWAIT | M_ZERO); + MPASS(op != NULL); + if (op != NULL) { + op->offset = qc; + CPU_COPY(&ctx->ifc_cpus, &op->set); + SLIST_INSERT_HEAD(&cpu_offsets, op, entries); + } + } + mtx_unlock(&cpu_offset_mtx); + + return ret; +} + int iflib_device_register(device_t dev, void *sc, if_shared_ctx_t sctx, if_ctx_t *ctxp) { @@ -4518,6 +4575,11 @@ goto fail_queues; /* + * Now that we know how many queues there are, get the core offset. + */ + ctx->ifc_sysctl_core_offset = get_ctx_core_offset(ctx); + + /* * Group taskqueues aren't properly set up until SMP is started, * so we disable interrupts until we can handle them post * SI_SUB_SMP. @@ -5558,7 +5620,7 @@ * Find the nth "close" core to the specified core * "close" is defined as the deepest level that shares * at least an L2 cache. With threads, this will be - * threads on the same core. If the sahred cache is L3 + * threads on the same core. If the shared cache is L3 * or higher, simply returns the same core. */ static int @@ -5642,10 +5704,13 @@ const char *name) { device_t dev; - int err, cpuid, tid; + int co, cpuid, err, tid; dev = ctx->ifc_dev; - cpuid = find_nth(ctx, qid); + co = ctx->ifc_sysctl_core_offset; + if (ctx->ifc_sysctl_separate_txrx && type == IFLIB_INTR_TX) + co += ctx->ifc_softc_ctx.isc_nrxqsets; + cpuid = find_nth(ctx, qid + co); tid = get_core_offset(ctx, type, qid); MPASS(tid >= 0); cpuid = find_close_core(cpuid, tid); @@ -6247,6 +6312,12 @@ SYSCTL_ADD_U16(ctx_list, oid_list, OID_AUTO, "tx_abdicate", CTLFLAG_RWTUN, &ctx->ifc_sysctl_tx_abdicate, 0, "cause tx to abdicate instead of running to completion"); + SYSCTL_ADD_U16(ctx_list, oid_list, OID_AUTO, "core_offset", + 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"); /* XXX change for per-queue sizes */ SYSCTL_ADD_PROC(ctx_list, oid_list, OID_AUTO, "override_ntxds",