Changeset View
Changeset View
Standalone View
Standalone View
sys/net/iflib.c
Show First 20 Lines • Show All 4,281 Lines • ▼ Show 20 Lines | if (sc == NULL) { | ||||
ctx->ifc_flags |= IFC_SC_ALLOCATED; | ctx->ifc_flags |= IFC_SC_ALLOCATED; | ||||
} | } | ||||
ctx->ifc_sctx = sctx; | ctx->ifc_sctx = sctx; | ||||
ctx->ifc_dev = dev; | ctx->ifc_dev = dev; | ||||
ctx->ifc_softc = sc; | ctx->ifc_softc = sc; | ||||
if ((err = iflib_register(ctx)) != 0) { | if ((err = iflib_register(ctx)) != 0) { | ||||
if (ctx->ifc_flags & IFC_SC_ALLOCATED) | |||||
free(sc, M_IFLIB); | |||||
free(ctx, M_IFLIB); | |||||
device_printf(dev, "iflib_register failed %d\n", err); | device_printf(dev, "iflib_register failed %d\n", err); | ||||
return (err); | goto fail_early; | ||||
} | } | ||||
iflib_add_device_sysctl_pre(ctx); | iflib_add_device_sysctl_pre(ctx); | ||||
scctx = &ctx->ifc_softc_ctx; | scctx = &ctx->ifc_softc_ctx; | ||||
ifp = ctx->ifc_ifp; | ifp = ctx->ifc_ifp; | ||||
iflib_reset_qvalues(ctx); | iflib_reset_qvalues(ctx); | ||||
CTX_LOCK(ctx); | CTX_LOCK(ctx); | ||||
if ((err = IFDI_ATTACH_PRE(ctx)) != 0) { | if ((err = IFDI_ATTACH_PRE(ctx)) != 0) { | ||||
CTX_UNLOCK(ctx); | |||||
device_printf(dev, "IFDI_ATTACH_PRE failed %d\n", err); | device_printf(dev, "IFDI_ATTACH_PRE failed %d\n", err); | ||||
return (err); | goto fail_unlock; | ||||
} | } | ||||
_iflib_pre_assert(scctx); | _iflib_pre_assert(scctx); | ||||
ctx->ifc_txrx = *scctx->isc_txrx; | ctx->ifc_txrx = *scctx->isc_txrx; | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
MPASS(scctx->isc_capabilities); | MPASS(scctx->isc_capabilities); | ||||
if (scctx->isc_capabilities & IFCAP_TXCSUM) | if (scctx->isc_capabilities & IFCAP_TXCSUM) | ||||
MPASS(scctx->isc_tx_csum_flags); | MPASS(scctx->isc_tx_csum_flags); | ||||
Show All 13 Lines | #endif | ||||
/* XXX change for per-queue sizes */ | /* XXX change for per-queue sizes */ | ||||
device_printf(dev, "using %d tx descriptors and %d rx descriptors\n", | device_printf(dev, "using %d tx descriptors and %d rx descriptors\n", | ||||
scctx->isc_ntxd[main_txq], scctx->isc_nrxd[main_rxq]); | scctx->isc_ntxd[main_txq], scctx->isc_nrxd[main_rxq]); | ||||
for (i = 0; i < sctx->isc_nrxqs; i++) { | for (i = 0; i < sctx->isc_nrxqs; i++) { | ||||
if (!powerof2(scctx->isc_nrxd[i])) { | if (!powerof2(scctx->isc_nrxd[i])) { | ||||
/* round down instead? */ | /* round down instead? */ | ||||
device_printf(dev, "# rx descriptors must be a power of 2\n"); | device_printf(dev, "# rx descriptors must be a power of 2\n"); | ||||
err = EINVAL; | err = EINVAL; | ||||
goto fail; | goto fail_iflib_detach; | ||||
} | } | ||||
} | } | ||||
for (i = 0; i < sctx->isc_ntxqs; i++) { | for (i = 0; i < sctx->isc_ntxqs; i++) { | ||||
if (!powerof2(scctx->isc_ntxd[i])) { | if (!powerof2(scctx->isc_ntxd[i])) { | ||||
device_printf(dev, | device_printf(dev, | ||||
"# tx descriptors must be a power of 2"); | "# tx descriptors must be a power of 2"); | ||||
err = EINVAL; | err = EINVAL; | ||||
goto fail; | goto fail_iflib_detach; | ||||
} | } | ||||
} | } | ||||
if (scctx->isc_tx_nsegments > scctx->isc_ntxd[main_txq] / | if (scctx->isc_tx_nsegments > scctx->isc_ntxd[main_txq] / | ||||
MAX_SINGLE_PACKET_FRACTION) | MAX_SINGLE_PACKET_FRACTION) | ||||
scctx->isc_tx_nsegments = max(1, scctx->isc_ntxd[main_txq] / | scctx->isc_tx_nsegments = max(1, scctx->isc_ntxd[main_txq] / | ||||
MAX_SINGLE_PACKET_FRACTION); | MAX_SINGLE_PACKET_FRACTION); | ||||
if (scctx->isc_tx_tso_segments_max > scctx->isc_ntxd[main_txq] / | if (scctx->isc_tx_tso_segments_max > scctx->isc_ntxd[main_txq] / | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | else { | ||||
scctx->isc_ntxqsets = 1; | scctx->isc_ntxqsets = 1; | ||||
scctx->isc_nrxqsets = 1; | scctx->isc_nrxqsets = 1; | ||||
scctx->isc_intr = IFLIB_INTR_LEGACY; | scctx->isc_intr = IFLIB_INTR_LEGACY; | ||||
msix = 0; | msix = 0; | ||||
} | } | ||||
/* 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; | goto fail_intr_free; | ||||
} | } | ||||
if ((err = iflib_qset_structures_setup(ctx))) | if ((err = iflib_qset_structures_setup(ctx))) | ||||
goto fail_queues; | goto fail_queues; | ||||
/* | /* | ||||
* Group taskqueues aren't properly set up until SMP is started, | * Group taskqueues aren't properly set up until SMP is started, | ||||
* so we disable interrupts until we can handle them post | * so we disable interrupts until we can handle them post | ||||
* SI_SUB_SMP. | * SI_SUB_SMP. | ||||
* | * | ||||
* XXX: disabling interrupts doesn't actually work, at least for | * XXX: disabling interrupts doesn't actually work, at least for | ||||
* the non-MSI case. When they occur before SI_SUB_SMP completes, | * the non-MSI case. When they occur before SI_SUB_SMP completes, | ||||
* we do null handling and depend on this not causing too large an | * we do null handling and depend on this not causing too large an | ||||
* interrupt storm. | * interrupt storm. | ||||
*/ | */ | ||||
IFDI_INTR_DISABLE(ctx); | IFDI_INTR_DISABLE(ctx); | ||||
if (msix > 1 && (err = IFDI_MSIX_INTR_ASSIGN(ctx, msix)) != 0) { | if (msix > 1 && (err = IFDI_MSIX_INTR_ASSIGN(ctx, msix)) != 0) { | ||||
device_printf(dev, "IFDI_MSIX_INTR_ASSIGN failed %d\n", err); | device_printf(dev, "IFDI_MSIX_INTR_ASSIGN failed %d\n", err); | ||||
goto fail_intr_free; | goto fail_queues; | ||||
} | } | ||||
if (msix <= 1) { | if (msix <= 1) { | ||||
rid = 0; | rid = 0; | ||||
if (scctx->isc_intr == IFLIB_INTR_MSI) { | if (scctx->isc_intr == IFLIB_INTR_MSI) { | ||||
MPASS(msix == 1); | MPASS(msix == 1); | ||||
rid = 1; | rid = 1; | ||||
} | } | ||||
if ((err = iflib_legacy_setup(ctx, ctx->isc_legacy_intr, ctx->ifc_softc, &rid, "irq0")) != 0) { | if ((err = iflib_legacy_setup(ctx, ctx->isc_legacy_intr, ctx->ifc_softc, &rid, "irq0")) != 0) { | ||||
device_printf(dev, "iflib_legacy_setup failed %d\n", err); | device_printf(dev, "iflib_legacy_setup failed %d\n", err); | ||||
goto fail_intr_free; | goto fail_queues; | ||||
} | } | ||||
} | } | ||||
ether_ifattach(ctx->ifc_ifp, ctx->ifc_mac); | ether_ifattach(ctx->ifc_ifp, ctx->ifc_mac); | ||||
if ((err = IFDI_ATTACH_POST(ctx)) != 0) { | if ((err = IFDI_ATTACH_POST(ctx)) != 0) { | ||||
device_printf(dev, "IFDI_ATTACH_POST failed %d\n", err); | device_printf(dev, "IFDI_ATTACH_POST failed %d\n", err); | ||||
goto fail_detach; | goto fail_detach; | ||||
Show All 19 Lines | #endif | ||||
iflib_add_device_sysctl_post(ctx); | iflib_add_device_sysctl_post(ctx); | ||||
ctx->ifc_flags |= IFC_INIT_DONE; | ctx->ifc_flags |= IFC_INIT_DONE; | ||||
CTX_UNLOCK(ctx); | CTX_UNLOCK(ctx); | ||||
return (0); | return (0); | ||||
fail_detach: | fail_detach: | ||||
ether_ifdetach(ctx->ifc_ifp); | ether_ifdetach(ctx->ifc_ifp); | ||||
fail_intr_free: | fail_intr_free: | ||||
iflib_free_intr_mem(ctx); | |||||
fail_queues: | fail_queues: | ||||
iflib_tx_structures_free(ctx); | iflib_tx_structures_free(ctx); | ||||
iflib_rx_structures_free(ctx); | iflib_rx_structures_free(ctx); | ||||
fail: | fail_iflib_detach: | ||||
iflib_free_intr_mem(ctx); | |||||
IFDI_DETACH(ctx); | IFDI_DETACH(ctx); | ||||
fail_unlock: | |||||
CTX_UNLOCK(ctx); | CTX_UNLOCK(ctx); | ||||
fail_early: | |||||
if (ctx->ifc_flags & IFC_SC_ALLOCATED) | |||||
free(ctx->ifc_softc, M_IFLIB); | |||||
free(ctx, M_IFLIB); | |||||
return (err); | return (err); | ||||
} | } | ||||
int | int | ||||
iflib_pseudo_register(device_t dev, if_shared_ctx_t sctx, if_ctx_t *ctxp, | iflib_pseudo_register(device_t dev, if_shared_ctx_t sctx, if_ctx_t *ctxp, | ||||
struct iflib_cloneattach_ctx *clctx) | struct iflib_cloneattach_ctx *clctx) | ||||
{ | { | ||||
int err; | int err; | ||||
Show All 12 Lines | if (sctx->isc_flags & (IFLIB_PSEUDO|IFLIB_VIRTUAL)) | ||||
ctx->ifc_flags |= IFC_PSEUDO; | ctx->ifc_flags |= IFC_PSEUDO; | ||||
ctx->ifc_sctx = sctx; | ctx->ifc_sctx = sctx; | ||||
ctx->ifc_softc = sc; | ctx->ifc_softc = sc; | ||||
ctx->ifc_dev = dev; | ctx->ifc_dev = dev; | ||||
if ((err = iflib_register(ctx)) != 0) { | if ((err = iflib_register(ctx)) != 0) { | ||||
device_printf(dev, "%s: iflib_register failed %d\n", __func__, err); | device_printf(dev, "%s: iflib_register failed %d\n", __func__, err); | ||||
free(sc, M_IFLIB); | goto fail; | ||||
free(ctx, M_IFLIB); | |||||
return (err); | |||||
} | } | ||||
iflib_add_device_sysctl_pre(ctx); | iflib_add_device_sysctl_pre(ctx); | ||||
scctx = &ctx->ifc_softc_ctx; | scctx = &ctx->ifc_softc_ctx; | ||||
ifp = ctx->ifc_ifp; | ifp = ctx->ifc_ifp; | ||||
/* | /* | ||||
* XXX sanity check that ntxd & nrxd are a power of 2 | * XXX sanity check that ntxd & nrxd are a power of 2 | ||||
*/ | */ | ||||
iflib_reset_qvalues(ctx); | iflib_reset_qvalues(ctx); | ||||
if ((err = IFDI_ATTACH_PRE(ctx)) != 0) { | if ((err = IFDI_ATTACH_PRE(ctx)) != 0) { | ||||
device_printf(dev, "IFDI_ATTACH_PRE failed %d\n", err); | device_printf(dev, "IFDI_ATTACH_PRE failed %d\n", err); | ||||
return (err); | goto fail; | ||||
} | } | ||||
if (sctx->isc_flags & IFLIB_GEN_MAC) | if (sctx->isc_flags & IFLIB_GEN_MAC) | ||||
iflib_gen_mac(ctx); | iflib_gen_mac(ctx); | ||||
if ((err = IFDI_CLONEATTACH(ctx, clctx->cc_ifc, clctx->cc_name, | if ((err = IFDI_CLONEATTACH(ctx, clctx->cc_ifc, clctx->cc_name, | ||||
clctx->cc_params)) != 0) { | clctx->cc_params)) != 0) { | ||||
device_printf(dev, "IFDI_CLONEATTACH failed %d\n", err); | device_printf(dev, "IFDI_CLONEATTACH failed %d\n", err); | ||||
return (err); | goto fail; | ||||
} | } | ||||
ifmedia_add(&ctx->ifc_media, IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL); | ifmedia_add(&ctx->ifc_media, IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL); | ||||
ifmedia_add(&ctx->ifc_media, IFM_ETHER | IFM_AUTO, 0, NULL); | ifmedia_add(&ctx->ifc_media, IFM_ETHER | IFM_AUTO, 0, NULL); | ||||
ifmedia_set(&ctx->ifc_media, IFM_ETHER | IFM_AUTO); | ifmedia_set(&ctx->ifc_media, IFM_ETHER | IFM_AUTO); | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
MPASS(scctx->isc_capabilities); | MPASS(scctx->isc_capabilities); | ||||
if (scctx->isc_capabilities & IFCAP_TXCSUM) | if (scctx->isc_capabilities & IFCAP_TXCSUM) | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | #endif | ||||
/* XXX change for per-queue sizes */ | /* XXX change for per-queue sizes */ | ||||
device_printf(dev, "using %d tx descriptors and %d rx descriptors\n", | device_printf(dev, "using %d tx descriptors and %d rx descriptors\n", | ||||
scctx->isc_ntxd[main_txq], scctx->isc_nrxd[main_rxq]); | scctx->isc_ntxd[main_txq], scctx->isc_nrxd[main_rxq]); | ||||
for (i = 0; i < sctx->isc_nrxqs; i++) { | for (i = 0; i < sctx->isc_nrxqs; i++) { | ||||
if (!powerof2(scctx->isc_nrxd[i])) { | if (!powerof2(scctx->isc_nrxd[i])) { | ||||
/* round down instead? */ | /* round down instead? */ | ||||
device_printf(dev, "# rx descriptors must be a power of 2\n"); | device_printf(dev, "# rx descriptors must be a power of 2\n"); | ||||
err = EINVAL; | err = EINVAL; | ||||
goto fail; | goto fail_iflib_detach; | ||||
} | } | ||||
} | } | ||||
for (i = 0; i < sctx->isc_ntxqs; i++) { | for (i = 0; i < sctx->isc_ntxqs; i++) { | ||||
if (!powerof2(scctx->isc_ntxd[i])) { | if (!powerof2(scctx->isc_ntxd[i])) { | ||||
device_printf(dev, | device_printf(dev, | ||||
"# tx descriptors must be a power of 2"); | "# tx descriptors must be a power of 2"); | ||||
err = EINVAL; | err = EINVAL; | ||||
goto fail; | goto fail_iflib_detach; | ||||
} | } | ||||
} | } | ||||
if (scctx->isc_tx_nsegments > scctx->isc_ntxd[main_txq] / | if (scctx->isc_tx_nsegments > scctx->isc_ntxd[main_txq] / | ||||
MAX_SINGLE_PACKET_FRACTION) | MAX_SINGLE_PACKET_FRACTION) | ||||
scctx->isc_tx_nsegments = max(1, scctx->isc_ntxd[main_txq] / | scctx->isc_tx_nsegments = max(1, scctx->isc_ntxd[main_txq] / | ||||
MAX_SINGLE_PACKET_FRACTION); | MAX_SINGLE_PACKET_FRACTION); | ||||
if (scctx->isc_tx_tso_segments_max > scctx->isc_ntxd[main_txq] / | if (scctx->isc_tx_tso_segments_max > scctx->isc_ntxd[main_txq] / | ||||
Show All 29 Lines | #endif | ||||
taskqgroup_attach(qgroup_if_config_tqg, &ctx->ifc_admin_task, ctx, -1, "admin"); | taskqgroup_attach(qgroup_if_config_tqg, &ctx->ifc_admin_task, ctx, -1, "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; | goto fail_iflib_detach; | ||||
} | } | ||||
if ((err = iflib_qset_structures_setup(ctx))) { | if ((err = iflib_qset_structures_setup(ctx))) { | ||||
device_printf(dev, "qset structure setup failed %d\n", err); | device_printf(dev, "qset structure setup failed %d\n", err); | ||||
goto fail_queues; | goto fail_queues; | ||||
} | } | ||||
/* | /* | ||||
Show All 23 Lines | #endif | ||||
iflib_add_device_sysctl_post(ctx); | iflib_add_device_sysctl_post(ctx); | ||||
ctx->ifc_flags |= IFC_INIT_DONE; | ctx->ifc_flags |= IFC_INIT_DONE; | ||||
return (0); | return (0); | ||||
fail_detach: | fail_detach: | ||||
ether_ifdetach(ctx->ifc_ifp); | ether_ifdetach(ctx->ifc_ifp); | ||||
fail_queues: | fail_queues: | ||||
iflib_tx_structures_free(ctx); | iflib_tx_structures_free(ctx); | ||||
iflib_rx_structures_free(ctx); | iflib_rx_structures_free(ctx); | ||||
fail: | fail_iflib_detach: | ||||
IFDI_DETACH(ctx); | IFDI_DETACH(ctx); | ||||
fail: | |||||
free(ctx->ifc_softc, M_IFLIB); | |||||
free(ctx, M_IFLIB); | |||||
return (err); | return (err); | ||||
} | } | ||||
int | int | ||||
iflib_pseudo_deregister(if_ctx_t ctx) | iflib_pseudo_deregister(if_ctx_t ctx) | ||||
{ | { | ||||
if_t ifp = ctx->ifc_ifp; | if_t ifp = ctx->ifc_ifp; | ||||
iflib_txq_t txq; | iflib_txq_t txq; | ||||
▲ Show 20 Lines • Show All 1,699 Lines • Show Last 20 Lines |