Page MenuHomeFreeBSD

D12446.id35566.diff
No OneTemporary

D12446.id35566.diff

Index: sys/net/iflib.c
===================================================================
--- sys/net/iflib.c
+++ sys/net/iflib.c
@@ -4259,6 +4259,14 @@
GROUPTASK_INIT(&ctx->ifc_admin_task, 0, _task_fn_admin, ctx);
/* XXX format name */
taskqgroup_attach(qgroup_if_config_tqg, &ctx->ifc_admin_task, ctx, -1, "admin");
+
+ /* Set up cpu set. If it fails, use the set of all CPUs. */
+ if (bus_get_cpus(dev, INTR_CPUS, sizeof(ctx->ifc_cpus), &ctx->ifc_cpus) != 0) {
+ device_printf(dev, "Unable to fetch CPU list\n");
+ CPU_COPY(&all_cpus, &ctx->ifc_cpus);
+ }
+ MPASS(CPU_COUNT(&ctx->ifc_cpus) > 0);
+
/*
** Now setup MSI or MSI/X, should
** return us the number of supported
@@ -4978,14 +4986,15 @@
return (_iflib_irq_alloc(ctx, irq, rid, filter, handler, arg, name));
}
+#ifdef SMP
static int
find_nth(if_ctx_t ctx, cpuset_t *cpus, int qid)
{
- int i, cpuid, eqid, count;
+ int i, cpuid, eqid;
CPU_COPY(&ctx->ifc_cpus, cpus);
- count = CPU_COUNT(&ctx->ifc_cpus);
- eqid = qid % count;
+
+ eqid = qid % CPU_COUNT(cpus);
/* clear up to the qid'th bit */
for (i = 0; i < eqid; i++) {
cpuid = CPU_FFS(cpus);
@@ -4997,6 +5006,106 @@
return (cpuid-1);
}
+static int
+find_child_with_core(int cpu, struct cpu_group *grp)
+{
+ int i;
+
+ if (grp->cg_children == 0)
+ return -1;
+
+ MPASS(grp->cg_child);
+ for (i = 0; i < grp->cg_children; i++) {
+ if (CPU_ISSET(cpu, &grp->cg_child[i].cg_mask))
+ return i;
+ }
+
+ return -1;
+}
+
+/*
+ * Find the nth thread on the specified core
+ */
+static int
+find_thread(int cpu, int thread_num)
+{
+ struct cpu_group *grp;
+ int i;
+ cpuset_t cs;
+
+ grp = smp_topo();
+ if (grp == NULL)
+ return cpu;
+ i = 0;
+ while ((i = find_child_with_core(cpu, grp)) != -1) {
+ /* If the child only has one cpu, don't descend */
+ if (grp->cg_child[i].cg_count <= 1)
+ break;
+ grp = &grp->cg_child[i];
+ }
+
+ /* If they don't share at least an L2 cache, use the same CPU */
+ if (grp->cg_level > CG_SHARE_L2 || grp->cg_level == CG_SHARE_NONE)
+ return cpu;
+
+ /* Now pick one */
+ CPU_COPY(&grp->cg_mask, &cs);
+ for (i = thread_num % grp->cg_count; i > 0; i--) {
+ MPASS(CPU_FFS(&cs));
+ CPU_CLR(CPU_FFS(&cs) - 1, &cs);
+ }
+ MPASS(CPU_FFS(&cs));
+ return CPU_FFS(&cs) - 1;
+}
+
+static int
+get_thread_num(if_ctx_t ctx, iflib_intr_type_t type, int qid)
+{
+ switch (type) {
+ case IFLIB_INTR_TX:
+ /* TX queues get threads on the same core as the corresponding RX queue */
+ /* XXX handle multiple RX threads per core and more than two threads per core */
+ return qid / CPU_COUNT(&ctx->ifc_cpus) + 1;
+ case IFLIB_INTR_RX:
+ case IFLIB_INTR_RXTX:
+ /* RX queues get the first thread on their core */
+ return qid / CPU_COUNT(&ctx->ifc_cpus);
+ default:
+ return -1;
+ }
+}
+#else
+#define get_thread_num(ctx, type, qid) 0
+#define find_thread(cpuid, tid) 0
+#define find_nth(ctx, cpus, gid) 0
+#endif
+
+/* Just to avoid copy/paste */
+static inline int
+iflib_irq_set_affinity(if_ctx_t ctx, int irq, iflib_intr_type_t type, int qid,
+ struct grouptask *gtask, struct taskqgroup *tqg, void *uniq, char *name)
+{
+ cpuset_t cpus;
+ int cpuid;
+ int err, tid;
+
+ cpuid = find_nth(ctx, &cpus, qid);
+ tid = get_thread_num(ctx, type, qid);
+ MPASS(tid >= 0);
+ cpuid = find_thread(cpuid, tid);
+ err = taskqgroup_attach_cpu(tqg, gtask, uniq, cpuid, irq, name);
+ if (err) {
+ device_printf(ctx->ifc_dev, "taskqgroup_attach_cpu failed %d\n", err);
+ return (err);
+ }
+#ifdef notyet
+ if (cpuid > ctx->ifc_cpuid_highest)
+ ctx->ifc_cpuid_highest = cpuid;
+#endif
+ MPASS(gtask->gt_taskqueue != NULL);
+ 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,
@@ -5005,9 +5114,8 @@
struct grouptask *gtask;
struct taskqgroup *tqg;
iflib_filter_info_t info;
- cpuset_t cpus;
gtask_fn_t *fn;
- int tqrid, err, cpuid;
+ int tqrid, err;
driver_filter_t *intr_fast;
void *q;
@@ -5070,8 +5178,9 @@
return (0);
if (tqrid != -1) {
- cpuid = find_nth(ctx, &cpus, qid);
- taskqgroup_attach_cpu(tqg, gtask, q, cpuid, rman_get_start(irq->ii_res), name);
+ err = iflib_irq_set_affinity(ctx, rman_get_start(irq->ii_res), type, qid, gtask, tqg, q, name);
+ if (err)
+ return (err);
} else {
taskqgroup_attach(tqg, gtask, q, rman_get_start(irq->ii_res), name);
}
@@ -5087,6 +5196,7 @@
gtask_fn_t *fn;
void *q;
int irq_num = -1;
+ int err;
switch (type) {
case IFLIB_INTR_TX:
@@ -5115,7 +5225,14 @@
panic("unknown net intr type");
}
GROUPTASK_INIT(gtask, 0, fn, q);
- taskqgroup_attach(tqg, gtask, q, irq_num, name);
+ if (irq_num != -1) {
+ err = iflib_irq_set_affinity(ctx, irq_num, type, qid, gtask, tqg, q, name);
+ if (err)
+ taskqgroup_attach(tqg, gtask, q, irq_num, name);
+ }
+ else {
+ taskqgroup_attach(tqg, gtask, q, irq_num, name);
+ }
}
void
@@ -5391,20 +5508,14 @@
#else
queuemsgs = msgs - admincnt;
#endif
- if (bus_get_cpus(dev, INTR_CPUS, sizeof(ctx->ifc_cpus), &ctx->ifc_cpus) == 0) {
#ifdef RSS
- queues = imin(queuemsgs, rss_getnumbuckets());
+ queues = imin(queuemsgs, rss_getnumbuckets());
#else
- queues = queuemsgs;
+ queues = queuemsgs;
#endif
- queues = imin(CPU_COUNT(&ctx->ifc_cpus), queues);
- device_printf(dev, "pxm cpus: %d queue msgs: %d admincnt: %d\n",
- CPU_COUNT(&ctx->ifc_cpus), queuemsgs, admincnt);
- } else {
- device_printf(dev, "Unable to fetch CPU list\n");
- /* Figure out a reasonable auto config value */
- queues = min(queuemsgs, mp_ncpus);
- }
+ queues = imin(CPU_COUNT(&ctx->ifc_cpus), queues);
+ device_printf(dev, "pxm cpus: %d queue msgs: %d admincnt: %d\n",
+ CPU_COUNT(&ctx->ifc_cpus), queuemsgs, admincnt);
#ifdef RSS
/* If we're doing RSS, clamp at the number of RSS buckets */
if (queues > rss_getnumbuckets())

File Metadata

Mime Type
text/plain
Expires
Fri, Jul 3, 5:27 PM (12 h, 53 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34632085
Default Alt Text
D12446.id35566.diff (5 KB)

Event Timeline