diff options
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/net/iflib.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/sys/net/iflib.c b/sys/net/iflib.c index 7b5de820fd71..461ff0ba273e 100644 --- a/sys/net/iflib.c +++ b/sys/net/iflib.c @@ -34,6 +34,7 @@ #include <sys/types.h> #include <sys/bus.h> #include <sys/eventhandler.h> +#include <sys/fail.h> #include <sys/kernel.h> #include <sys/lock.h> #include <sys/mutex.h> @@ -565,6 +566,15 @@ TASKQGROUP_DEFINE(if_config_tqg, 1, 1); static SYSCTL_NODE(_net, OID_AUTO, iflib, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "iflib driver parameters"); +static SYSCTL_NODE(_debug_fail_point, OID_AUTO, iflib, + CTLFLAG_RW | CTLFLAG_MPSAFE, 0, "iflib fail points"); + +static char iflib_register_fail_device[32]; +SYSCTL_STRING(_debug_fail_point_iflib, OID_AUTO, register_device, + CTLFLAG_RW | CTLFLAG_MPSAFE, + iflib_register_fail_device, sizeof(iflib_register_fail_device), + "device name eligible for registration fail points"); + /* * XXX need to ensure that this can't accidentally cause the head to be moved backwards */ @@ -5198,6 +5208,30 @@ unref_ctx_core_offset(if_ctx_t ctx) MPASS(!ctx->ifc_core_offset_ref); } +static bool +iflib_register_fail_device_matches(device_t dev) +{ + const char *nameunit; + + nameunit = device_get_nameunit(dev); + return (iflib_register_fail_device[0] != '\0' && nameunit != NULL && + strcmp(nameunit, iflib_register_fail_device) == 0); +} + +#define IFLIB_REGISTER_FAIL_POINT(_dev, _name, _error, _label) do { \ + KFAIL_POINT_CODE_COND(_debug_fail_point_iflib, _name, \ + iflib_register_fail_device_matches((_dev)), \ + FAIL_POINT_NONSLEEPABLE, { \ + (_error) = RETURN_VALUE; \ + if ((_error) <= 0) \ + (_error) = EIO; \ + device_printf((_dev), \ + "injecting iflib registration failure at %s: %d\n", \ + #_name, (_error)); \ + goto _label; \ + }); \ +} while (0) + int iflib_device_register(device_t dev, void *sc, if_shared_ctx_t sctx, if_ctx_t *ctxp) { @@ -5245,11 +5279,15 @@ iflib_device_register(device_t dev, void *sc, if_shared_ctx_t sctx, if_ctx_t *ct iflib_reset_qvalues(ctx); IFNET_WLOCK(); CTX_LOCK(ctx); + IFLIB_REGISTER_FAIL_POINT(dev, register_before_attach_pre, err, + fail_cleanup); if ((err = IFDI_ATTACH_PRE(ctx)) != 0) { device_printf(dev, "IFDI_ATTACH_PRE failed %d\n", err); goto fail_cleanup; } attach_pre_succeeded = true; + IFLIB_REGISTER_FAIL_POINT(dev, register_after_attach_pre, err, + fail_cleanup); _iflib_pre_assert(scctx); ctx->ifc_txrx = *scctx->isc_txrx; @@ -5333,6 +5371,8 @@ iflib_device_register(device_t dev, void *sc, if_shared_ctx_t sctx, if_ctx_t *ct TASK_INIT(&ctx->ifc_admin_task, 0, _task_fn_admin, ctx); TASK_INIT(&ctx->ifc_led_task, 0, _task_fn_led, ctx); + IFLIB_REGISTER_FAIL_POINT(dev, register_after_taskqueue, err, + fail_cleanup); /* 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) { @@ -5363,6 +5403,8 @@ iflib_device_register(device_t dev, void *sc, if_shared_ctx_t sctx, if_ctx_t *ct msix = 0; } intr_allocated = true; + IFLIB_REGISTER_FAIL_POINT(dev, register_after_interrupts, err, + fail_cleanup); /* Get memory for the station queues */ if ((err = iflib_queues_alloc(ctx))) { device_printf(dev, "Unable to allocate queue memory\n"); @@ -5377,6 +5419,8 @@ iflib_device_register(device_t dev, void *sc, if_shared_ctx_t sctx, if_ctx_t *ct * Now that we know how many queues there are, get the core offset. */ ctx->ifc_sysctl_core_offset = get_ctx_core_offset(ctx); + IFLIB_REGISTER_FAIL_POINT(dev, register_after_queues, err, + fail_cleanup); if (msix > 1) { /* @@ -5442,6 +5486,8 @@ iflib_device_register(device_t dev, void *sc, if_shared_ctx_t sctx, if_ctx_t *ct device_printf(dev, "IFDI_ATTACH_POST failed %d\n", err); goto fail_detach; } + IFLIB_REGISTER_FAIL_POINT(dev, register_after_attach_post, err, + fail_detach); /* * Tell the upper layer(s) if IFCAP_VLAN_MTU is supported. |
