diff options
author | Eric Joyner <erj@FreeBSD.org> | 2019-08-01 17:37:25 +0000 |
---|---|---|
committer | Eric Joyner <erj@FreeBSD.org> | 2019-08-01 17:37:25 +0000 |
commit | 197c67982470ac932c5e5c475147b6fb57df8c4a (patch) | |
tree | 0ea13ff58af49fc156969c358eb362e07396a8fb | |
parent | fdf15fd04ee7571c9c4fd652dc22c3f18a1dd420 (diff) | |
download | src-197c67982470ac932c5e5c475147b6fb57df8c4a.tar.gz src-197c67982470ac932c5e5c475147b6fb57df8c4a.zip |
iflib: Prevent kernel panic caused by loading driver with a specific interrupt configuration
If a device has only 1 MSI-X interrupt available and does not support either
MSI or legacy interrupts, iflib_device_register() will fail, leak memory and
MSI resources, and the driver will not load. Worse, if another iflib-using
driver tries to unload afterwards, a kernel panic will occur because the
previous failed iflib driver loead did not properly call "taskqgroup_detach()"
during it's cleanup.
This patch is band-aid for this situation -- don't try allocating MSI or legacy
interrupts if a single MSI-X interrupt was allocated, but fail to load instead.
As well, during the cleanup, properly call taskqgroup_detach() on the admin
task to prevent panics when other iflib drivers unload.
This whole interrupt allocation process actually needs re-doing to properly
support devices with only a single MSI-X interrupt, devices that only support
MSI-X, non-PCI devices, and multiple non-MSIX interrupts, as well.
Signed-off-by: Eric Joyner <erj@freebsd.org>
Reviewed by: marius@
MFC after: 1 week
Sponsored by: Intel Corporation
Differential Revision: https://reviews.freebsd.org/D20747
Notes
Notes:
svn path=/head/; revision=350509
-rw-r--r-- | sys/net/iflib.c | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/sys/net/iflib.c b/sys/net/iflib.c index 9b3e7d30363c..f5c7536f0aa7 100644 --- a/sys/net/iflib.c +++ b/sys/net/iflib.c @@ -4731,7 +4731,7 @@ iflib_device_register(device_t dev, void *sc, if_shared_ctx_t sctx, if_ctx_t *ct 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); @@ -4741,6 +4741,11 @@ iflib_device_register(device_t dev, void *sc, if_shared_ctx_t sctx, if_ctx_t *ct 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.octet); @@ -4781,6 +4786,7 @@ fail_intr_free: fail_queues: iflib_tx_structures_free(ctx); iflib_rx_structures_free(ctx); + taskqgroup_detach(qgroup_if_config_tqg, &ctx->ifc_admin_task); IFDI_DETACH(ctx); fail_unlock: CTX_UNLOCK(ctx); |