Author: erj Date: Tue Aug 20 20:15:32 2019 New Revision: 351276 URL: https://svnweb.freebsd.org/changeset/base/351276
Log: MFC various iflib fixes from head Included revisions: r347418 - iflib: use default ntxd and rxd when user value is not power of 2 r348372 - iflib: provide probe wrapper for vendor drivers r350306 - iflib: fix dangling device softc pointer r350507 - iflib: remove kobject class reference increment r350509 - iflib: Prevent kernel panic caused by loading driver with a specific interrupt configuration r351152 - iflib: add iflib_deregister to help cleanup on exit Sponsored by: Intel Corporation Modified: stable/12/sys/net/iflib.c stable/12/sys/net/iflib.h Directory Properties: stable/12/ (props changed) Modified: stable/12/sys/net/iflib.c ============================================================================== --- stable/12/sys/net/iflib.c Tue Aug 20 20:04:16 2019 (r351275) +++ stable/12/sys/net/iflib.c Tue Aug 20 20:15:32 2019 (r351276) @@ -707,6 +707,7 @@ static void iflib_altq_if_start(if_t ifp); static int iflib_altq_if_transmit(if_t ifp, struct mbuf *m); #endif static int iflib_register(if_ctx_t); +static void iflib_deregister(if_ctx_t); static void iflib_init_locked(if_ctx_t ctx); static void iflib_add_device_sysctl_pre(if_ctx_t ctx); static void iflib_add_device_sysctl_post(if_ctx_t ctx); @@ -4350,6 +4351,18 @@ iflib_device_probe(device_t dev) return (ENXIO); } +int +iflib_device_probe_vendor(device_t dev) +{ + int probe; + + probe = iflib_device_probe(dev); + if (probe == BUS_PROBE_DEFAULT) + return (BUS_PROBE_VENDOR); + else + return (probe); +} + static void iflib_reset_qvalues(if_ctx_t ctx) { @@ -4360,9 +4373,6 @@ iflib_reset_qvalues(if_ctx_t ctx) scctx->isc_txrx_budget_bytes_max = IFLIB_MAX_TX_BYTES; scctx->isc_tx_qdepth = IFLIB_DEFAULT_TX_QDEPTH; - /* - * XXX sanity check that ntxd & nrxd are a power of 2 - */ if (ctx->ifc_sysctl_ntxqs != 0) scctx->isc_ntxqsets = ctx->ifc_sysctl_ntxqs; if (ctx->ifc_sysctl_nrxqs != 0) @@ -4393,6 +4403,11 @@ iflib_reset_qvalues(if_ctx_t ctx) i, scctx->isc_nrxd[i], sctx->isc_nrxd_max[i]); scctx->isc_nrxd[i] = sctx->isc_nrxd_max[i]; } + if (!powerof2(scctx->isc_nrxd[i])) { + device_printf(dev, "nrxd%d: %d is not a power of 2 - using default value of %d\n", + i, scctx->isc_nrxd[i], sctx->isc_nrxd_default[i]); + scctx->isc_nrxd[i] = sctx->isc_nrxd_default[i]; + } } for (i = 0; i < sctx->isc_ntxqs; i++) { @@ -4406,6 +4421,11 @@ iflib_reset_qvalues(if_ctx_t ctx) i, scctx->isc_ntxd[i], sctx->isc_ntxd_max[i]); scctx->isc_ntxd[i] = sctx->isc_ntxd_max[i]; } + if (!powerof2(scctx->isc_ntxd[i])) { + device_printf(dev, "ntxd%d: %d is not a power of 2 - using default value of %d\n", + i, scctx->isc_ntxd[i], sctx->isc_ntxd_default[i]); + scctx->isc_ntxd[i] = sctx->isc_ntxd_default[i]; + } } } @@ -4482,7 +4502,7 @@ iflib_device_register(device_t dev, void *sc, if_share if_softc_ctx_t scctx; kobjop_desc_t kobj_desc; kobj_method_t *kobj_method; - int err, i, msix, rid; + int err, msix, rid; uint16_t main_rxq, main_txq; ctx = malloc(sizeof(* ctx), M_IFLIB, M_WAITOK|M_ZERO); @@ -4534,23 +4554,6 @@ iflib_device_register(device_t dev, void *sc, if_share /* XXX change for per-queue sizes */ device_printf(dev, "Using %d TX descriptors and %d RX descriptors\n", scctx->isc_ntxd[main_txq], scctx->isc_nrxd[main_rxq]); - for (i = 0; i < sctx->isc_nrxqs; i++) { - if (!powerof2(scctx->isc_nrxd[i])) { - /* round down instead? */ - device_printf(dev, - "# RX descriptors must be a power of 2\n"); - err = EINVAL; - goto fail_iflib_detach; - } - } - for (i = 0; i < sctx->isc_ntxqs; i++) { - if (!powerof2(scctx->isc_ntxd[i])) { - device_printf(dev, - "# TX descriptors must be a power of 2"); - err = EINVAL; - goto fail_iflib_detach; - } - } if (scctx->isc_tx_nsegments > scctx->isc_ntxd[main_txq] / MAX_SINGLE_PACKET_FRACTION) @@ -4676,7 +4679,7 @@ iflib_device_register(device_t dev, void *sc, if_share err); goto fail_queues; } - } else { + } else if (scctx->isc_intr != IFLIB_INTR_MSIX) { rid = 0; if (scctx->isc_intr == IFLIB_INTR_MSI) { MPASS(msix == 1); @@ -4686,6 +4689,11 @@ iflib_device_register(device_t dev, void *sc, if_share device_printf(dev, "iflib_legacy_setup failed %d\n", err); goto fail_queues; } + } else { + device_printf(dev, + "Cannot use iflib with only 1 MSI-X interrupt!\n"); + err = ENODEV; + goto fail_intr_free; } ether_ifattach(ctx->ifc_ifp, ctx->ifc_mac); @@ -4725,11 +4733,13 @@ fail_intr_free: fail_queues: iflib_tx_structures_free(ctx); iflib_rx_structures_free(ctx); -fail_iflib_detach: + taskqgroup_detach(qgroup_if_config_tqg, &ctx->ifc_admin_task); IFDI_DETACH(ctx); fail_unlock: CTX_UNLOCK(ctx); + iflib_deregister(ctx); fail_ctx_free: + device_set_softc(ctx->ifc_dev, NULL); if (ctx->ifc_flags & IFC_SC_ALLOCATED) free(ctx->ifc_softc, M_IFLIB); free(ctx, M_IFLIB); @@ -4768,9 +4778,6 @@ iflib_pseudo_register(device_t dev, if_shared_ctx_t sc scctx = &ctx->ifc_softc_ctx; ifp = ctx->ifc_ifp; - /* - * XXX sanity check that ntxd & nrxd are a power of 2 - */ iflib_reset_qvalues(ctx); CTX_LOCK(ctx); if ((err = IFDI_ATTACH_PRE(ctx)) != 0) { @@ -4834,23 +4841,6 @@ iflib_pseudo_register(device_t dev, if_shared_ctx_t sc /* XXX change for per-queue sizes */ device_printf(dev, "Using %d TX descriptors and %d RX descriptors\n", scctx->isc_ntxd[main_txq], scctx->isc_nrxd[main_rxq]); - for (i = 0; i < sctx->isc_nrxqs; i++) { - if (!powerof2(scctx->isc_nrxd[i])) { - /* round down instead? */ - device_printf(dev, - "# RX descriptors must be a power of 2\n"); - err = EINVAL; - goto fail_iflib_detach; - } - } - for (i = 0; i < sctx->isc_ntxqs; i++) { - if (!powerof2(scctx->isc_ntxd[i])) { - device_printf(dev, - "# TX descriptors must be a power of 2"); - err = EINVAL; - goto fail_iflib_detach; - } - } if (scctx->isc_tx_nsegments > scctx->isc_ntxd[main_txq] / MAX_SINGLE_PACKET_FRACTION) @@ -4941,6 +4931,7 @@ fail_iflib_detach: IFDI_DETACH(ctx); fail_unlock: CTX_UNLOCK(ctx); + iflib_deregister(ctx); fail_ctx_free: free(ctx->ifc_softc, M_IFLIB); free(ctx, M_IFLIB); @@ -4957,15 +4948,7 @@ iflib_pseudo_deregister(if_ctx_t ctx) struct taskqgroup *tqg; iflib_fl_t fl; - /* Unregister VLAN events */ - if (ctx->ifc_vlan_attach_event != NULL) - EVENTHANDLER_DEREGISTER(vlan_config, ctx->ifc_vlan_attach_event); - if (ctx->ifc_vlan_detach_event != NULL) - EVENTHANDLER_DEREGISTER(vlan_unconfig, ctx->ifc_vlan_detach_event); - ether_ifdetach(ifp); - /* ether_ifdetach calls if_qflush - lock must be destroy afterwards*/ - CTX_LOCK_DESTROY(ctx); /* XXX drain any dependent tasks */ tqg = qgroup_if_io_tqg; for (txq = ctx->ifc_txqs, i = 0; i < NTXQSETS(ctx); i++, txq++) { @@ -4986,10 +4969,11 @@ iflib_pseudo_deregister(if_ctx_t ctx) if (ctx->ifc_vflr_task.gt_uniq != NULL) taskqgroup_detach(tqg, &ctx->ifc_vflr_task); - if_free(ifp); - iflib_tx_structures_free(ctx); iflib_rx_structures_free(ctx); + + iflib_deregister(ctx); + if (ctx->ifc_flags & IFC_SC_ALLOCATED) free(ctx->ifc_softc, M_IFLIB); free(ctx, M_IFLIB); @@ -5075,19 +5059,19 @@ iflib_device_deregister(if_ctx_t ctx) CTX_UNLOCK(ctx); /* ether_ifdetach calls if_qflush - lock must be destroy afterwards*/ - CTX_LOCK_DESTROY(ctx); - device_set_softc(ctx->ifc_dev, NULL); iflib_free_intr_mem(ctx); bus_generic_detach(dev); - if_free(ifp); iflib_tx_structures_free(ctx); iflib_rx_structures_free(ctx); + + iflib_deregister(ctx); + + device_set_softc(ctx->ifc_dev, NULL); if (ctx->ifc_flags & IFC_SC_ALLOCATED) free(ctx->ifc_softc, M_IFLIB); unref_ctx_core_offset(ctx); - STATE_LOCK_DESTROY(ctx); free(ctx, M_IFLIB); return (0); } @@ -5239,6 +5223,8 @@ iflib_module_event_handler(module_t mod, int what, voi static void _iflib_assert(if_shared_ctx_t sctx) { + int i; + MPASS(sctx->isc_tx_maxsize); MPASS(sctx->isc_tx_maxsegsize); @@ -5246,12 +5232,25 @@ _iflib_assert(if_shared_ctx_t sctx) MPASS(sctx->isc_rx_nsegments); MPASS(sctx->isc_rx_maxsegsize); - MPASS(sctx->isc_nrxd_min[0]); - MPASS(sctx->isc_nrxd_max[0]); - MPASS(sctx->isc_nrxd_default[0]); - MPASS(sctx->isc_ntxd_min[0]); - MPASS(sctx->isc_ntxd_max[0]); - MPASS(sctx->isc_ntxd_default[0]); + MPASS(sctx->isc_nrxqs >= 1 && sctx->isc_nrxqs <= 8); + for (i = 0; i < sctx->isc_nrxqs; i++) { + MPASS(sctx->isc_nrxd_min[i]); + MPASS(powerof2(sctx->isc_nrxd_min[i])); + MPASS(sctx->isc_nrxd_max[i]); + MPASS(powerof2(sctx->isc_nrxd_max[i])); + MPASS(sctx->isc_nrxd_default[i]); + MPASS(powerof2(sctx->isc_nrxd_default[i])); + } + + MPASS(sctx->isc_ntxqs >= 1 && sctx->isc_ntxqs <= 8); + for (i = 0; i < sctx->isc_ntxqs; i++) { + MPASS(sctx->isc_ntxd_min[i]); + MPASS(powerof2(sctx->isc_ntxd_min[i])); + MPASS(sctx->isc_ntxd_max[i]); + MPASS(powerof2(sctx->isc_ntxd_max[i])); + MPASS(sctx->isc_ntxd_default[i]); + MPASS(powerof2(sctx->isc_ntxd_default[i])); + } } static void @@ -5290,7 +5289,6 @@ iflib_register(if_ctx_t ctx) */ kobj_init((kobj_t) ctx, (kobj_class_t) driver); kobj_class_compile((kobj_class_t) driver); - driver->refs++; if_initname(ifp, device_get_name(dev), device_get_unit(dev)); if_setsoftc(ifp, ctx); @@ -5318,6 +5316,36 @@ iflib_register(if_ctx_t ctx) iflib_media_change, iflib_media_status); return (0); +} + +static void +iflib_deregister(if_ctx_t ctx) +{ + if_t ifp = ctx->ifc_ifp; + + /* Remove all media */ + ifmedia_removeall(&ctx->ifc_media); + + /* Unregister VLAN events */ + if (ctx->ifc_vlan_attach_event != NULL) { + EVENTHANDLER_DEREGISTER(vlan_config, ctx->ifc_vlan_attach_event); + ctx->ifc_vlan_attach_event = NULL; + } + if (ctx->ifc_vlan_detach_event != NULL) { + EVENTHANDLER_DEREGISTER(vlan_unconfig, ctx->ifc_vlan_detach_event); + ctx->ifc_vlan_detach_event = NULL; + } + + /* Release kobject reference */ + kobj_delete((kobj_t) ctx, NULL); + + /* Free the ifnet structure */ + if_free(ifp); + + STATE_LOCK_DESTROY(ctx); + + /* ether_ifdetach calls if_qflush - lock must be destroy afterwards*/ + CTX_LOCK_DESTROY(ctx); } static int Modified: stable/12/sys/net/iflib.h ============================================================================== --- stable/12/sys/net/iflib.h Tue Aug 20 20:04:16 2019 (r351275) +++ stable/12/sys/net/iflib.h Tue Aug 20 20:15:32 2019 (r351276) @@ -393,6 +393,13 @@ int iflib_device_suspend(device_t); int iflib_device_resume(device_t); int iflib_device_shutdown(device_t); +/* + * Use this instead of iflib_device_probe if the driver should report + * BUS_PROBE_VENDOR instead of BUS_PROBE_DEFAULT. (For example, an out-of-tree + * driver based on iflib). + */ +int iflib_device_probe_vendor(device_t); + int iflib_device_iov_init(device_t, uint16_t, const nvlist_t *); void iflib_device_iov_uninit(device_t); _______________________________________________ svn-src-all@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"