Changeset View
Changeset View
Standalone View
Standalone View
head/sys/net/iflib.c
Show First 20 Lines • Show All 4,475 Lines • ▼ Show 20 Lines | if (if_getcapabilities(ifp) & IFCAP_TSO) { | ||||
if_sethwtsomaxsegsize(ifp, scctx->isc_tx_tso_segsize_max); | if_sethwtsomaxsegsize(ifp, scctx->isc_tx_tso_segsize_max); | ||||
} | } | ||||
if (scctx->isc_rss_table_size == 0) | if (scctx->isc_rss_table_size == 0) | ||||
scctx->isc_rss_table_size = 64; | scctx->isc_rss_table_size = 64; | ||||
scctx->isc_rss_table_mask = scctx->isc_rss_table_size-1; | scctx->isc_rss_table_mask = scctx->isc_rss_table_size-1; | ||||
GROUPTASK_INIT(&ctx->ifc_admin_task, 0, _task_fn_admin, ctx); | GROUPTASK_INIT(&ctx->ifc_admin_task, 0, _task_fn_admin, ctx); | ||||
/* XXX format name */ | /* XXX format name */ | ||||
taskqgroup_attach(qgroup_if_config_tqg, &ctx->ifc_admin_task, ctx, -1, "admin"); | taskqgroup_attach(qgroup_if_config_tqg, &ctx->ifc_admin_task, ctx, | ||||
NULL, NULL, "admin"); | |||||
/* Set up cpu set. If it fails, use the set of all CPUs. */ | /* 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) { | if (bus_get_cpus(dev, INTR_CPUS, sizeof(ctx->ifc_cpus), &ctx->ifc_cpus) != 0) { | ||||
device_printf(dev, "Unable to fetch CPU list\n"); | device_printf(dev, "Unable to fetch CPU list\n"); | ||||
CPU_COPY(&all_cpus, &ctx->ifc_cpus); | CPU_COPY(&all_cpus, &ctx->ifc_cpus); | ||||
} | } | ||||
MPASS(CPU_COUNT(&ctx->ifc_cpus) > 0); | MPASS(CPU_COUNT(&ctx->ifc_cpus) > 0); | ||||
▲ Show 20 Lines • Show All 244 Lines • ▼ Show 20 Lines | if (if_getcapabilities(ifp) & IFCAP_TSO) { | ||||
if_sethwtsomaxsegsize(ifp, scctx->isc_tx_tso_segsize_max); | if_sethwtsomaxsegsize(ifp, scctx->isc_tx_tso_segsize_max); | ||||
} | } | ||||
if (scctx->isc_rss_table_size == 0) | if (scctx->isc_rss_table_size == 0) | ||||
scctx->isc_rss_table_size = 64; | scctx->isc_rss_table_size = 64; | ||||
scctx->isc_rss_table_mask = scctx->isc_rss_table_size-1; | scctx->isc_rss_table_mask = scctx->isc_rss_table_size-1; | ||||
GROUPTASK_INIT(&ctx->ifc_admin_task, 0, _task_fn_admin, ctx); | GROUPTASK_INIT(&ctx->ifc_admin_task, 0, _task_fn_admin, ctx); | ||||
/* XXX format name */ | /* XXX format name */ | ||||
taskqgroup_attach(qgroup_if_config_tqg, &ctx->ifc_admin_task, ctx, -1, "admin"); | taskqgroup_attach(qgroup_if_config_tqg, &ctx->ifc_admin_task, ctx, | ||||
NULL, NULL, "admin"); | |||||
/* XXX --- can support > 1 -- but keep it simple for now */ | /* XXX --- can support > 1 -- but keep it simple for now */ | ||||
scctx->isc_intr = IFLIB_INTR_LEGACY; | scctx->isc_intr = IFLIB_INTR_LEGACY; | ||||
/* Get memory for the station queues */ | /* Get memory for the station queues */ | ||||
if ((err = iflib_queues_alloc(ctx))) { | if ((err = iflib_queues_alloc(ctx))) { | ||||
device_printf(dev, "Unable to allocate queue memory\n"); | device_printf(dev, "Unable to allocate queue memory\n"); | ||||
goto fail_iflib_detach; | goto fail_iflib_detach; | ||||
▲ Show 20 Lines • Show All 875 Lines • ▼ Show 20 Lines | |||||
#else | #else | ||||
#define get_core_offset(ctx, type, qid) CPU_FIRST() | #define get_core_offset(ctx, type, qid) CPU_FIRST() | ||||
#define find_close_core(cpuid, tid) CPU_FIRST() | #define find_close_core(cpuid, tid) CPU_FIRST() | ||||
#define find_nth(ctx, gid) CPU_FIRST() | #define find_nth(ctx, gid) CPU_FIRST() | ||||
#endif | #endif | ||||
/* Just to avoid copy/paste */ | /* Just to avoid copy/paste */ | ||||
static inline int | static inline int | ||||
iflib_irq_set_affinity(if_ctx_t ctx, int irq, iflib_intr_type_t type, int qid, | iflib_irq_set_affinity(if_ctx_t ctx, if_irq_t irq, iflib_intr_type_t type, | ||||
struct grouptask *gtask, struct taskqgroup *tqg, void *uniq, const char *name) | int qid, struct grouptask *gtask, struct taskqgroup *tqg, void *uniq, | ||||
const char *name) | |||||
{ | { | ||||
int cpuid; | device_t dev; | ||||
int err, tid; | int err, cpuid, tid; | ||||
dev = ctx->ifc_dev; | |||||
cpuid = find_nth(ctx, qid); | cpuid = find_nth(ctx, qid); | ||||
tid = get_core_offset(ctx, type, qid); | tid = get_core_offset(ctx, type, qid); | ||||
MPASS(tid >= 0); | MPASS(tid >= 0); | ||||
cpuid = find_close_core(cpuid, tid); | cpuid = find_close_core(cpuid, tid); | ||||
err = taskqgroup_attach_cpu(tqg, gtask, uniq, cpuid, irq, name); | err = taskqgroup_attach_cpu(tqg, gtask, uniq, cpuid, dev, irq->ii_res, | ||||
name); | |||||
if (err) { | if (err) { | ||||
device_printf(ctx->ifc_dev, "taskqgroup_attach_cpu failed %d\n", err); | device_printf(dev, "taskqgroup_attach_cpu failed %d\n", err); | ||||
return (err); | return (err); | ||||
} | } | ||||
#ifdef notyet | #ifdef notyet | ||||
if (cpuid > ctx->ifc_cpuid_highest) | if (cpuid > ctx->ifc_cpuid_highest) | ||||
ctx->ifc_cpuid_highest = cpuid; | ctx->ifc_cpuid_highest = cpuid; | ||||
#endif | #endif | ||||
return 0; | return 0; | ||||
} | } | ||||
int | int | ||||
iflib_irq_alloc_generic(if_ctx_t ctx, if_irq_t irq, int rid, | iflib_irq_alloc_generic(if_ctx_t ctx, if_irq_t irq, int rid, | ||||
iflib_intr_type_t type, driver_filter_t *filter, | iflib_intr_type_t type, driver_filter_t *filter, | ||||
void *filter_arg, int qid, const char *name) | void *filter_arg, int qid, const char *name) | ||||
{ | { | ||||
device_t dev; | |||||
struct grouptask *gtask; | struct grouptask *gtask; | ||||
struct taskqgroup *tqg; | struct taskqgroup *tqg; | ||||
iflib_filter_info_t info; | iflib_filter_info_t info; | ||||
gtask_fn_t *fn; | gtask_fn_t *fn; | ||||
int tqrid, err; | int tqrid, err; | ||||
driver_filter_t *intr_fast; | driver_filter_t *intr_fast; | ||||
void *q; | void *q; | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | default: | ||||
panic("unknown net intr type"); | panic("unknown net intr type"); | ||||
} | } | ||||
info->ifi_filter = filter; | info->ifi_filter = filter; | ||||
info->ifi_filter_arg = filter_arg; | info->ifi_filter_arg = filter_arg; | ||||
info->ifi_task = gtask; | info->ifi_task = gtask; | ||||
info->ifi_ctx = q; | info->ifi_ctx = q; | ||||
dev = ctx->ifc_dev; | |||||
err = _iflib_irq_alloc(ctx, irq, rid, intr_fast, NULL, info, name); | err = _iflib_irq_alloc(ctx, irq, rid, intr_fast, NULL, info, name); | ||||
if (err != 0) { | if (err != 0) { | ||||
device_printf(ctx->ifc_dev, "_iflib_irq_alloc failed %d\n", err); | device_printf(dev, "_iflib_irq_alloc failed %d\n", err); | ||||
return (err); | return (err); | ||||
} | } | ||||
if (type == IFLIB_INTR_ADMIN) | if (type == IFLIB_INTR_ADMIN) | ||||
return (0); | return (0); | ||||
if (tqrid != -1) { | if (tqrid != -1) { | ||||
err = iflib_irq_set_affinity(ctx, rman_get_start(irq->ii_res), type, qid, gtask, tqg, q, name); | err = iflib_irq_set_affinity(ctx, irq, type, qid, gtask, tqg, | ||||
q, name); | |||||
if (err) | if (err) | ||||
return (err); | return (err); | ||||
} else { | } else { | ||||
taskqgroup_attach(tqg, gtask, q, rman_get_start(irq->ii_res), name); | taskqgroup_attach(tqg, gtask, q, dev, irq->ii_res, name); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
void | 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) | ||||
{ | { | ||||
struct grouptask *gtask; | struct grouptask *gtask; | ||||
struct taskqgroup *tqg; | struct taskqgroup *tqg; | ||||
gtask_fn_t *fn; | gtask_fn_t *fn; | ||||
void *q; | void *q; | ||||
int irq_num = -1; | |||||
int err; | int err; | ||||
switch (type) { | switch (type) { | ||||
case IFLIB_INTR_TX: | case IFLIB_INTR_TX: | ||||
q = &ctx->ifc_txqs[qid]; | q = &ctx->ifc_txqs[qid]; | ||||
gtask = &ctx->ifc_txqs[qid].ift_task; | gtask = &ctx->ifc_txqs[qid].ift_task; | ||||
tqg = qgroup_if_io_tqg; | tqg = qgroup_if_io_tqg; | ||||
fn = _task_fn_tx; | fn = _task_fn_tx; | ||||
if (irq != NULL) | |||||
irq_num = rman_get_start(irq->ii_res); | |||||
break; | break; | ||||
case IFLIB_INTR_RX: | case IFLIB_INTR_RX: | ||||
q = &ctx->ifc_rxqs[qid]; | q = &ctx->ifc_rxqs[qid]; | ||||
gtask = &ctx->ifc_rxqs[qid].ifr_task; | gtask = &ctx->ifc_rxqs[qid].ifr_task; | ||||
tqg = qgroup_if_io_tqg; | tqg = qgroup_if_io_tqg; | ||||
fn = _task_fn_rx; | fn = _task_fn_rx; | ||||
if (irq != NULL) | |||||
irq_num = rman_get_start(irq->ii_res); | |||||
break; | break; | ||||
case IFLIB_INTR_IOV: | case IFLIB_INTR_IOV: | ||||
q = ctx; | q = ctx; | ||||
gtask = &ctx->ifc_vflr_task; | gtask = &ctx->ifc_vflr_task; | ||||
tqg = qgroup_if_config_tqg; | tqg = qgroup_if_config_tqg; | ||||
fn = _task_fn_iov; | fn = _task_fn_iov; | ||||
break; | break; | ||||
default: | default: | ||||
panic("unknown net intr type"); | panic("unknown net intr type"); | ||||
} | } | ||||
GROUPTASK_INIT(gtask, 0, fn, q); | GROUPTASK_INIT(gtask, 0, fn, q); | ||||
if (irq_num != -1) { | if (irq != NULL) { | ||||
err = iflib_irq_set_affinity(ctx, irq_num, type, qid, gtask, tqg, q, name); | err = iflib_irq_set_affinity(ctx, irq, type, qid, gtask, tqg, | ||||
q, name); | |||||
if (err) | if (err) | ||||
taskqgroup_attach(tqg, gtask, q, irq_num, name); | taskqgroup_attach(tqg, gtask, q, ctx->ifc_dev, | ||||
irq->ii_res, name); | |||||
} else { | |||||
taskqgroup_attach(tqg, gtask, q, NULL, NULL, name); | |||||
} | } | ||||
else { | |||||
taskqgroup_attach(tqg, gtask, q, irq_num, name); | |||||
} | } | ||||
} | |||||
void | void | ||||
iflib_irq_free(if_ctx_t ctx, if_irq_t irq) | iflib_irq_free(if_ctx_t ctx, if_irq_t irq) | ||||
{ | { | ||||
if (irq->ii_tag) | if (irq->ii_tag) | ||||
bus_teardown_intr(ctx->ifc_dev, irq->ii_res, irq->ii_tag); | bus_teardown_intr(ctx->ifc_dev, irq->ii_res, irq->ii_tag); | ||||
if (irq->ii_res) | if (irq->ii_res) | ||||
bus_release_resource(ctx->ifc_dev, SYS_RES_IRQ, | bus_release_resource(ctx->ifc_dev, SYS_RES_IRQ, | ||||
rman_get_rid(irq->ii_res), irq->ii_res); | rman_get_rid(irq->ii_res), irq->ii_res); | ||||
} | } | ||||
static int | static int | ||||
iflib_legacy_setup(if_ctx_t ctx, driver_filter_t filter, void *filter_arg, int *rid, const char *name) | iflib_legacy_setup(if_ctx_t ctx, driver_filter_t filter, void *filter_arg, int *rid, const char *name) | ||||
{ | { | ||||
iflib_txq_t txq = ctx->ifc_txqs; | iflib_txq_t txq = ctx->ifc_txqs; | ||||
iflib_rxq_t rxq = ctx->ifc_rxqs; | iflib_rxq_t rxq = ctx->ifc_rxqs; | ||||
if_irq_t irq = &ctx->ifc_legacy_irq; | if_irq_t irq = &ctx->ifc_legacy_irq; | ||||
iflib_filter_info_t info; | iflib_filter_info_t info; | ||||
device_t dev; | |||||
struct grouptask *gtask; | struct grouptask *gtask; | ||||
struct resource *res; | |||||
struct taskqgroup *tqg; | struct taskqgroup *tqg; | ||||
gtask_fn_t *fn; | gtask_fn_t *fn; | ||||
int tqrid; | int tqrid; | ||||
void *q; | void *q; | ||||
int err; | int err; | ||||
q = &ctx->ifc_rxqs[0]; | q = &ctx->ifc_rxqs[0]; | ||||
info = &rxq[0].ifr_filter_info; | info = &rxq[0].ifr_filter_info; | ||||
gtask = &rxq[0].ifr_task; | gtask = &rxq[0].ifr_task; | ||||
tqg = qgroup_if_io_tqg; | tqg = qgroup_if_io_tqg; | ||||
tqrid = irq->ii_rid = *rid; | tqrid = irq->ii_rid = *rid; | ||||
fn = _task_fn_rx; | fn = _task_fn_rx; | ||||
ctx->ifc_flags |= IFC_LEGACY; | ctx->ifc_flags |= IFC_LEGACY; | ||||
info->ifi_filter = filter; | info->ifi_filter = filter; | ||||
info->ifi_filter_arg = filter_arg; | info->ifi_filter_arg = filter_arg; | ||||
info->ifi_task = gtask; | info->ifi_task = gtask; | ||||
info->ifi_ctx = ctx; | info->ifi_ctx = ctx; | ||||
dev = ctx->ifc_dev; | |||||
/* We allocate a single interrupt resource */ | /* We allocate a single interrupt resource */ | ||||
if ((err = _iflib_irq_alloc(ctx, irq, tqrid, iflib_fast_intr_ctx, NULL, info, name)) != 0) | if ((err = _iflib_irq_alloc(ctx, irq, tqrid, iflib_fast_intr_ctx, NULL, info, name)) != 0) | ||||
return (err); | return (err); | ||||
GROUPTASK_INIT(gtask, 0, fn, q); | GROUPTASK_INIT(gtask, 0, fn, q); | ||||
taskqgroup_attach(tqg, gtask, q, rman_get_start(irq->ii_res), name); | res = irq->ii_res; | ||||
taskqgroup_attach(tqg, gtask, q, dev, res, name); | |||||
GROUPTASK_INIT(&txq->ift_task, 0, _task_fn_tx, txq); | GROUPTASK_INIT(&txq->ift_task, 0, _task_fn_tx, txq); | ||||
taskqgroup_attach(qgroup_if_io_tqg, &txq->ift_task, txq, rman_get_start(irq->ii_res), "tx"); | taskqgroup_attach(qgroup_if_io_tqg, &txq->ift_task, txq, dev, res, | ||||
"tx"); | |||||
return (0); | return (0); | ||||
} | } | ||||
void | void | ||||
iflib_led_create(if_ctx_t ctx) | iflib_led_create(if_ctx_t ctx) | ||||
{ | { | ||||
ctx->ifc_led_dev = led_create(iflib_led_func, ctx, | ctx->ifc_led_dev = led_create(iflib_led_func, ctx, | ||||
Show All 33 Lines | iflib_iov_intr_deferred(if_ctx_t ctx) | ||||
GROUPTASK_ENQUEUE(&ctx->ifc_vflr_task); | GROUPTASK_ENQUEUE(&ctx->ifc_vflr_task); | ||||
} | } | ||||
void | void | ||||
iflib_io_tqg_attach(struct grouptask *gt, void *uniq, int cpu, char *name) | iflib_io_tqg_attach(struct grouptask *gt, void *uniq, int cpu, char *name) | ||||
{ | { | ||||
taskqgroup_attach_cpu(qgroup_if_io_tqg, gt, uniq, cpu, -1, name); | taskqgroup_attach_cpu(qgroup_if_io_tqg, gt, uniq, cpu, NULL, NULL, | ||||
name); | |||||
} | } | ||||
void | void | ||||
iflib_config_gtask_init(void *ctx, struct grouptask *gtask, gtask_fn_t *fn, | iflib_config_gtask_init(void *ctx, struct grouptask *gtask, gtask_fn_t *fn, | ||||
const char *name) | const char *name) | ||||
{ | { | ||||
GROUPTASK_INIT(gtask, 0, fn, ctx); | GROUPTASK_INIT(gtask, 0, fn, ctx); | ||||
taskqgroup_attach(qgroup_if_config_tqg, gtask, gtask, -1, name); | taskqgroup_attach(qgroup_if_config_tqg, gtask, gtask, NULL, NULL, | ||||
name); | |||||
} | } | ||||
void | void | ||||
iflib_config_gtask_deinit(struct grouptask *gtask) | iflib_config_gtask_deinit(struct grouptask *gtask) | ||||
{ | { | ||||
taskqgroup_detach(qgroup_if_config_tqg, gtask); | taskqgroup_detach(qgroup_if_config_tqg, gtask); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 623 Lines • Show Last 20 Lines |