git: 22dcbd7739a1 - main - if_bnxt: port workqueue, task-queue, and synchronization kPIs to FreeBSD natives

From: Sumit Saxena <ssaxena_at_FreeBSD.org>
Date: Fri, 09 Oct 2026 10:13:02 UTC
The branch main has been updated by ssaxena:

URL: https://cgit.FreeBSD.org/src/commit/?id=22dcbd7739a174433845da800ad47fa182f37430

commit 22dcbd7739a174433845da800ad47fa182f37430
Author:     Sumit Saxena <sumit.saxena@broadcom.com>
AuthorDate: 2026-08-05 04:12:53 +0000
Commit:     Sumit Saxena <ssaxena@FreeBSD.org>
CommitDate: 2026-10-09 08:24:46 +0000

    if_bnxt: port workqueue, task-queue, and synchronization kPIs to FreeBSD natives
    
    - Replace Linux workqueue (struct workqueue_struct, bnxt_pf_wq) with a
      FreeBSD taskqueue (bnxt_taskq) shared by every attached PF. bnxt_taskq
      is created once at module load and destroyed once at module unload
      (SYSINIT/SYSUNINIT on SI_SUB_KLD), matching the module-owned-taskqueue
      idiom used elsewhere in the tree (e.g. sys/dev/cxgbe/t4_main.c's
      reset_tq). This replaces an earlier lazy, per-attach/detach
      create-or-reuse scheme guarded by a mutex and a "ready" flag, which
      had a real race: bnxt_queue_sp_work()/bnxt_queue_fw_reset_work() and
      bnxt_attach_pre() re-read the bnxt_taskq/bnxt_taskq_ready globals
      outside the mutex right after the lazy-init call returned, so a
      concurrent bnxt_detach() on another PF freeing the shared queue once
      bnxt_num_pfs hit 0 could race a still-attached PF into enqueuing onto
      a freed taskqueue. Tying the taskqueue's lifetime to the module
      instead of to any one PF's attach/detach removes that race outright,
      since the module can't unload while a PF is still attached.
    
    - Replace struct work_struct sp_task with struct task sp_task;
      replace struct delayed_work fw_reset_task with
      struct timeout_task fw_reset_tmo.
    
    - Replace INIT_WORK/INIT_DELAYED_WORK with TASK_INIT/TIMEOUT_TASK_INIT;
      queue_work/schedule_work with taskqueue_enqueue;
      queue_delayed_work/schedule_delayed_work with taskqueue_enqueue_timeout;
      cancel_work_sync/cancel_delayed_work_sync with
      taskqueue_drain/taskqueue_drain_timeout.
    
    - Rename bnxt_fw_reset_task(struct work_struct *) to
      bnxt_fw_reset_timeout_task(void *ctx, int pending) to match FreeBSD
      timeout_task callback signature.
    
    - Add inline helpers in bnxt.h to wrap all Linux test_bit/set_bit/
      clear_bit/test_and_clear_bit calls on softc->state and
      softc->sp_event: bnxt_drv_state_test/set/clear/test_and_clear,
      bnxt_sp_event_set/test_and_clear (implemented via bit_test() from
      <sys/bitstring.h> and atomic_testandset_long()/
      atomic_testandclear_long(), all bit-index based like the Linux
      bitops they replace).
    
    - Replace struct mutex lock in bnxt_fw_health with struct mtx;
      mutex_init to mtx_init.
    
    - Replace kzalloc/kfree with malloc/free (M_DEVBUF).
    
    - Replace DIV_ROUND_UP with howmany; hweight32 with bitcount32.
    
    - Replace jiffies/HZ with ticks/hz; msleep with pause_sbt(). Since
      `ticks` (unlike LinuxKPI's `unsigned long jiffies`) is a 32-bit
      `volatile int` that wraps every ~24 days at hz=1000, BNXT_TIME_AFTER
      and bnxt_sleep_until_min_elapsed() compute the ticks delta as `int`
      (matching the in-tree wraparound-safe idiom used elsewhere, e.g.
      sys/dev/axgbe/xgbe-mdio.c) rather than widening it to `long`/
      `unsigned long`, so the comparison stays correct across a wrap.
    
    - Replace IS_ERR_OR_NULL/ERR_PTR with plain NULL checks.
    
    Reviewed by:    gallatin
    MFC after:      2 weeks
    Sponsored by:   Broadcom Inc.
    Differential Revision:  https://reviews.freebsd.org/D59089
---
 sys/dev/bnxt/bnxt_en/bnxt.h               |  48 ++++-
 sys/dev/bnxt/bnxt_en/bnxt_auxbus_compat.c |   4 +-
 sys/dev/bnxt/bnxt_en/bnxt_compat.h        |   2 +-
 sys/dev/bnxt/bnxt_en/bnxt_hwrm.c          |   2 +-
 sys/dev/bnxt/bnxt_en/bnxt_ktls.c          |  12 +-
 sys/dev/bnxt/bnxt_en/bnxt_ptp.c           |   2 +-
 sys/dev/bnxt/bnxt_en/bnxt_ulp.c           |   5 +-
 sys/dev/bnxt/bnxt_en/if_bnxt.c            | 295 ++++++++++++++++++------------
 8 files changed, 230 insertions(+), 140 deletions(-)

diff --git a/sys/dev/bnxt/bnxt_en/bnxt.h b/sys/dev/bnxt/bnxt_en/bnxt.h
index 6509a89fcaec..7c5b357ec7ac 100644
--- a/sys/dev/bnxt/bnxt_en/bnxt.h
+++ b/sys/dev/bnxt/bnxt_en/bnxt.h
@@ -35,6 +35,7 @@
 #include <sys/sysctl.h>
 #include <sys/systm.h>
 #include <sys/taskqueue.h>
+#include <sys/callout.h>
 #include <sys/bitstring.h>
 
 #include <machine/bus.h>
@@ -1150,7 +1151,7 @@ struct bnxt_fw_health {
 	u32 echo_req_data1;
 	u32 echo_req_data2;
 	struct devlink_health_reporter	*fw_reporter;
-	struct mutex lock;
+	struct mtx lock;
 	enum bnxt_health_severity severity;
 	enum bnxt_health_remedy remedy;
 	u32 arrests;
@@ -1526,10 +1527,10 @@ struct bnxt_softc {
 #define BNXT_STATE_HALF_OPEN		15
 #define BNXT_STATE_UP			16
 #define BNXT_NO_FW_ACCESS(bp)		\
-	test_bit(BNXT_STATE_FW_FATAL_COND, &(bp)->state)
+	bnxt_drv_state_test((bp), BNXT_STATE_FW_FATAL_COND)
 	struct pci_dev			*pdev;
 
-	struct work_struct	sp_task;
+	struct task		sp_task;
 	unsigned long		sp_event;
 #define BNXT_RX_MASK_SP_EVENT		0
 #define BNXT_RX_NTP_FLTR_SP_EVENT	1
@@ -1557,7 +1558,7 @@ struct bnxt_softc {
 #define BNXT_FW_ECHO_REQUEST_SP_EVENT	23
 #define BNXT_VF_CFG_CHNG_SP_EVENT	24
 
-	struct delayed_work	fw_reset_task;
+	struct timeout_task	fw_reset_tmo;
 	int			fw_reset_state;
 #define BNXT_FW_RESET_STATE_POLL_VF	1
 #define BNXT_FW_RESET_STATE_RESET_FW	2
@@ -1623,6 +1624,45 @@ struct bnxt_softc {
 	uint8_t			tx_hw_coal_cnt;
 };
 
+/* softc->state helpers */
+static __inline bool
+bnxt_drv_state_test(const struct bnxt_softc *sc, unsigned int bit)
+{
+	/* Paired with the atomic RMWs the write-side helpers below use. */
+	return (atomic_load_acq_long(&sc->state) & (1UL << bit)) != 0;
+}
+
+static __inline void
+bnxt_drv_state_set(struct bnxt_softc *sc, unsigned int bit)
+{
+	atomic_testandset_long(&sc->state, bit);
+}
+
+static __inline void
+bnxt_drv_state_clear(struct bnxt_softc *sc, unsigned int bit)
+{
+	atomic_testandclear_long(&sc->state, bit);
+}
+
+static __inline bool
+bnxt_drv_state_test_and_clear(struct bnxt_softc *sc, unsigned int bit)
+{
+	return atomic_testandclear_long(&sc->state, bit);
+}
+
+/* softc->sp_event helpers */
+static __inline void
+bnxt_sp_event_set(struct bnxt_softc *sc, unsigned int bit)
+{
+	atomic_testandset_long(&sc->sp_event, bit);
+}
+
+static __inline bool
+bnxt_sp_event_test_and_clear(struct bnxt_softc *sc, unsigned int bit)
+{
+	return atomic_testandclear_long(&sc->sp_event, bit);
+}
+
 struct bnxt_filter_info {
 	STAILQ_ENTRY(bnxt_filter_info) next;
 	uint64_t	fw_l2_filter_id;
diff --git a/sys/dev/bnxt/bnxt_en/bnxt_auxbus_compat.c b/sys/dev/bnxt/bnxt_en/bnxt_auxbus_compat.c
index 1014d360015a..de7f46f6a900 100644
--- a/sys/dev/bnxt/bnxt_en/bnxt_auxbus_compat.c
+++ b/sys/dev/bnxt/bnxt_en/bnxt_auxbus_compat.c
@@ -31,8 +31,8 @@
 #include <linux/string.h>
 #include <linux/types.h>
 #include <linux/list.h>
-#include <linux/delay.h>
 
+#include "bnxt_compat.h"
 #include "bnxt_auxbus_compat.h"
 
 static struct list_head bnxt_aux_bus_dev_list = LINUX_LIST_HEAD_INIT(bnxt_aux_bus_dev_list);
@@ -92,7 +92,7 @@ int auxiliary_device_add(struct auxiliary_device *auxdev)
 	mutex_lock(&bnxt_auxbus_lock);
 	list_for_each_entry(auxdrv, &bnxt_aux_bus_drv_list, list) {
 		if (auxdrv) {
-			msleep(2 * 1000);
+			pause_sbt("bxtms", SBT_1MS * 2 * 1000, 0, C_HARDCLOCK);
 
 			id = auxiliary_match_id(auxdrv->id_table, auxdev);
 			if (id) {
diff --git a/sys/dev/bnxt/bnxt_en/bnxt_compat.h b/sys/dev/bnxt/bnxt_en/bnxt_compat.h
index 0a1c47b6cd92..3ca02fb84ee4 100644
--- a/sys/dev/bnxt/bnxt_en/bnxt_compat.h
+++ b/sys/dev/bnxt/bnxt_en/bnxt_compat.h
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/socket.h>
+#include <sys/systm.h>
 #include <sys/sysctl.h>
 #include <sys/taskqueue.h>
 #include <sys/bitstring.h>
@@ -46,7 +47,6 @@ __FBSDID("$FreeBSD$");
 #include <net/iflib.h>
 #include <linux/types.h>
 
-
 #if (__FreeBSD_version < 1500000)
 
 #define if_getmtu(ifp)	(ifp)->if_mtu
diff --git a/sys/dev/bnxt/bnxt_en/bnxt_hwrm.c b/sys/dev/bnxt/bnxt_en/bnxt_hwrm.c
index 77e43079fd96..f31b19878e55 100644
--- a/sys/dev/bnxt/bnxt_en/bnxt_hwrm.c
+++ b/sys/dev/bnxt/bnxt_en/bnxt_hwrm.c
@@ -3630,7 +3630,7 @@ int bnxt_hwrm_set_coal(struct bnxt_softc *softc)
 	struct hwrm_ring_cmpl_ring_cfg_aggint_params_input req = {0};
 	int i, rc = 0;
 
-	if (!test_bit(BNXT_STATE_UP, &softc->state))
+	if (!bnxt_drv_state_test(softc, BNXT_STATE_UP))
 		return (rc);
 
 	bnxt_hwrm_cmd_hdr_init(softc, &req,
diff --git a/sys/dev/bnxt/bnxt_en/bnxt_ktls.c b/sys/dev/bnxt/bnxt_en/bnxt_ktls.c
index 31549707d275..01f1c711ca0e 100644
--- a/sys/dev/bnxt/bnxt_en/bnxt_ktls.c
+++ b/sys/dev/bnxt/bnxt_en/bnxt_ktls.c
@@ -177,7 +177,7 @@ int bnxt_tls_snd_tag_alloc(if_t ifp, union if_snd_tag_alloc_params* params,
 	priv = iflib_get_softc(ctx);
 	ktls = priv->ktls_info;
 
-	if (!test_bit(BNXT_STATE_OPEN, &priv->state))
+	if (!bnxt_drv_state_test(priv, BNXT_STATE_OPEN))
 		return (EPROTONOSUPPORT);
 
 	if (atomic_load_acq_int(&priv->detached))
@@ -999,8 +999,8 @@ static int bnxt_crypto_del(struct bnxt_softc* softc,
 	uint32_t data;
 	uint32_t kid;
 
-	if (test_bit(BNXT_STATE_IN_FW_RESET, &softc->state) &&
-	    test_bit(BNXT_STATE_FW_FATAL_COND, &softc->state))
+	if (bnxt_drv_state_test(softc, BNXT_STATE_IN_FW_RESET) &&
+	    bnxt_drv_state_test(softc, BNXT_STATE_FW_FATAL_COND))
 		return 0;
 
 	kid = kctx_tx->kid;
@@ -1026,7 +1026,7 @@ static int bnxt_ktls_dev_add(struct bnxt_softc* softc,
 	atomic_add_32(&ktls->pending, 1);
 
 	atomic_thread_fence_seq_cst();
-	if (!test_bit(BNXT_STATE_OPEN, &softc->state)) {
+	if (!bnxt_drv_state_test(softc, BNXT_STATE_OPEN)) {
 		BNXT_DEBUG(softc->dev, "kTLS dev_add: device not open\n");
 		rc = ENODEV;
 		goto exit;
@@ -1082,7 +1082,7 @@ static void bnxt_ktls_dev_del(struct bnxt_softc* softc,
 	 * BNXT_STATE_OPEN is cleared (and MPC rings freed) in bnxt_stop();
 	 * bail out here to avoid MPC command timeouts while unloading.
 	 */
-	if (!test_bit(BNXT_STATE_OPEN, &softc->state)) {
+	if (!bnxt_drv_state_test(softc, BNXT_STATE_OPEN)) {
 		BNXT_DEBUG(softc->dev, "[KID:%u]: KTLS dev_del: device not up, freeing KID\n", kid);
 		bnxt_free_one_kctx(kctx, kid, softc->dev);
 		counter_u64_add(ktls->counters[BNXT_KTLS_TX_DEL], 1);
@@ -1095,7 +1095,7 @@ retry:
 	 * BNXT_STATE_OPEN flag.
 	 */
 	atomic_thread_fence_seq_cst();
-	while (!test_bit(BNXT_STATE_OPEN, &softc->state)) {
+	while (!bnxt_drv_state_test(softc, BNXT_STATE_OPEN)) {
 		atomic_subtract_32(&ktls->pending, 1);
 		if (retry_cnt > BNXT_RETRY_MAX) {
 			device_printf(softc->dev,
diff --git a/sys/dev/bnxt/bnxt_en/bnxt_ptp.c b/sys/dev/bnxt/bnxt_en/bnxt_ptp.c
index 73d0c24c63f1..ff3fac22538b 100644
--- a/sys/dev/bnxt/bnxt_en/bnxt_ptp.c
+++ b/sys/dev/bnxt/bnxt_en/bnxt_ptp.c
@@ -90,7 +90,7 @@ __bnxt_refclk_read(struct bnxt_softc *bp, uint64_t *ns)
 	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
 	uint32_t high_before, high_now, low;
 
-	if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
+	if (bnxt_drv_state_test(bp, BNXT_STATE_IN_FW_RESET))
 		return (EIO);
 
 	/* Refclk registers live in the HWRM BAR, not the doorbell BAR. */
diff --git a/sys/dev/bnxt/bnxt_en/bnxt_ulp.c b/sys/dev/bnxt/bnxt_en/bnxt_ulp.c
index cd6df3b17d63..00a9f5ba2a70 100644
--- a/sys/dev/bnxt/bnxt_en/bnxt_ulp.c
+++ b/sys/dev/bnxt/bnxt_en/bnxt_ulp.c
@@ -33,7 +33,6 @@
 #include <linux/pci.h>
 #include <linux/netdevice.h>
 #include <linux/bitops.h>
-#include <linux/delay.h>
 #include <asm/byteorder.h>
 #include <linux/bitmap.h>
 #include <linux/rcupdate.h>
@@ -76,7 +75,7 @@ static int bnxt_register_dev(struct bnxt_en_dev *edev, int ulp_id,
 	rcu_assign_pointer(ulp->ulp_ops, ulp_ops);
 
 	if (ulp_id == BNXT_ROCE_ULP) {
-		if (test_bit(BNXT_STATE_OPEN, &bp->state) && bp->is_dev_init)
+		if (bnxt_drv_state_test(bp, BNXT_STATE_OPEN) && bp->is_dev_init)
 			bnxt_hwrm_vnic_cfg(bp, &bp->vnic_info);
 	}
 
@@ -111,7 +110,7 @@ static int bnxt_unregister_dev(struct bnxt_en_dev *edev, int ulp_id)
 	ulp->async_events_bmap = NULL;
 	mtx_unlock(&bp->en_ops_lock);
 	while (atomic_read(&ulp->ref_count) != 0 && i < 10) {
-		msleep(100);
+		pause_sbt("bxtms", SBT_1MS * 100, 0, C_HARDCLOCK);
 		i++;
 	}
 	/* Tell the caller a ULP consumer may still hold a reference into torn-down state. */
diff --git a/sys/dev/bnxt/bnxt_en/if_bnxt.c b/sys/dev/bnxt/bnxt_en/if_bnxt.c
index c30c608875be..0c4ae738b557 100644
--- a/sys/dev/bnxt/bnxt_en/if_bnxt.c
+++ b/sys/dev/bnxt/bnxt_en/if_bnxt.c
@@ -35,6 +35,11 @@
 #include <sys/endian.h>
 #include <sys/sockio.h>
 #include <sys/priv.h>
+#include <sys/mutex.h>
+#include <sys/taskqueue.h>
+#include <sys/callout.h>
+#include <sys/libkern.h>
+#include <sys/syslog.h>
 
 #include <machine/bus.h>
 #include <machine/resource.h>
@@ -51,12 +56,11 @@
 
 #define	WANT_NATIVE_PCI_GET_SLOT
 #include <linux/pci.h>
+#include <linux/gfp.h>
 #include <linux/kmod.h>
 #include <linux/module.h>
-#include <linux/delay.h>
 #include <linux/idr.h>
 #include <linux/netdevice.h>
-#include <linux/etherdevice.h>
 #include <linux/rcupdate.h>
 #include "opt_inet.h"
 #include "opt_inet6.h"
@@ -80,6 +84,8 @@
 #include "bnxt_mpc.h"
 #include "bnxt_ktls.h"
 
+#define	BNXT_TIME_AFTER(a, b)	(((int)((a) - (b)) > 0))
+
 /*
  * PCI Device ID Table
  */
@@ -508,7 +514,33 @@ bnxt_set_flags_by_devid(struct bnxt_softc *softc)
 }
 
 #define PCI_SUBSYSTEM_ID	0x2e
-static struct workqueue_struct *bnxt_pf_wq;
+static struct taskqueue *bnxt_taskq;
+
+/* Taskqueue shared by every attached PF; created at module load, destroyed at unload. */
+static void
+bnxt_taskq_create(void *arg __unused)
+{
+
+	bnxt_taskq = taskqueue_create("bnxt", M_WAITOK,
+	    taskqueue_thread_enqueue, &bnxt_taskq);
+	if (taskqueue_start_threads(&bnxt_taskq, 1, PWAIT, "bnxt taskq") != 0) {
+		log(LOG_ERR, "bnxt: unable to start taskqueue thread\n");
+		taskqueue_free(bnxt_taskq);
+		bnxt_taskq = NULL;
+	}
+}
+SYSINIT(bnxt_taskq_create, SI_SUB_TASKQ, SI_ORDER_ANY, bnxt_taskq_create, NULL);
+
+static void
+bnxt_taskq_destroy(void *arg __unused)
+{
+
+	if (bnxt_taskq != NULL)
+		taskqueue_free(bnxt_taskq);
+}
+SYSUNINIT(bnxt_taskq_destroy, SI_SUB_TASKQ, SI_ORDER_ANY, bnxt_taskq_destroy, NULL);
+
+static void bnxt_fw_reset_timeout_task(void *ctx, int pending);
 
 extern void bnxt_destroy_irq(struct bnxt_softc *softc);
 
@@ -1153,7 +1185,7 @@ bnxt_alloc_ctx_pg_tbls(struct bnxt_softc *softc,
 	if (!mem_size)
 		return -EINVAL;
 
-	ctx_pg->nr_pages = DIV_ROUND_UP(mem_size, BNXT_PAGE_SIZE);
+	ctx_pg->nr_pages = howmany(mem_size, BNXT_PAGE_SIZE);
 	if (ctx_pg->nr_pages > MAX_CTX_TOTAL_PAGES) {
 		ctx_pg->nr_pages = 0;
 		return -EINVAL;
@@ -1162,11 +1194,11 @@ bnxt_alloc_ctx_pg_tbls(struct bnxt_softc *softc,
 		int nr_tbls, i;
 
 		rmem->depth = 2;
-		ctx_pg->ctx_pg_tbl = kzalloc(MAX_CTX_PAGES * sizeof(ctx_pg),
-					      GFP_KERNEL);
+		ctx_pg->ctx_pg_tbl = malloc(MAX_CTX_PAGES * sizeof(ctx_pg),
+		    M_DEVBUF, M_WAITOK | M_ZERO);
 		if (!ctx_pg->ctx_pg_tbl)
 			return -ENOMEM;
-		nr_tbls = DIV_ROUND_UP(ctx_pg->nr_pages, MAX_CTX_PAGES);
+		nr_tbls = howmany(ctx_pg->nr_pages, MAX_CTX_PAGES);
 		rmem->nr_pages = nr_tbls;
 		rc = bnxt_alloc_ctx_mem_blk(softc, ctx_pg);
 		if (rc)
@@ -1174,7 +1206,7 @@ bnxt_alloc_ctx_pg_tbls(struct bnxt_softc *softc,
 		for (i = 0; i < nr_tbls; i++) {
 			struct bnxt_ctx_pg_info *pg_tbl;
 
-			pg_tbl = kzalloc(sizeof(*pg_tbl), GFP_KERNEL);
+			pg_tbl = malloc(sizeof(*pg_tbl), M_DEVBUF, M_WAITOK | M_ZERO);
 			if (!pg_tbl)
 				return -ENOMEM;
 			ctx_pg->ctx_pg_tbl[i] = pg_tbl;
@@ -1194,7 +1226,7 @@ bnxt_alloc_ctx_pg_tbls(struct bnxt_softc *softc,
 				break;
 		}
 	} else {
-		rmem->nr_pages = DIV_ROUND_UP(mem_size, BNXT_PAGE_SIZE);
+		rmem->nr_pages = howmany(mem_size, BNXT_PAGE_SIZE);
 		if (rmem->nr_pages > 1 || depth)
 			rmem->depth = 1;
 		rmem->ctx_mem = ctxm;
@@ -1225,7 +1257,7 @@ void bnxt_free_ctx_pg_tbls(struct bnxt_softc *softc,
 			free(pg_tbl , M_DEVBUF);
 			ctx_pg->ctx_pg_tbl[i] = NULL;
 		}
-		kfree(ctx_pg->ctx_pg_tbl);
+		free(ctx_pg->ctx_pg_tbl, M_DEVBUF);
 		ctx_pg->ctx_pg_tbl = NULL;
 	}
 	bnxt_free_ring(softc, rmem);
@@ -1243,7 +1275,7 @@ static int bnxt_setup_ctxm_pg_tbls(struct bnxt_softc *softc,
 	if (!ctxm->entry_size || !ctx_pg)
 		return -EINVAL;
 	if (ctxm->instance_bmap)
-		n = hweight32(ctxm->instance_bmap);
+		n = bitcount32(ctxm->instance_bmap);
 	if (ctxm->entry_multiple)
 		entries = roundup(entries, ctxm->entry_multiple);
 	entries = clamp_t(u32, entries, ctxm->min_entries, ctxm->max_entries);
@@ -1274,16 +1306,16 @@ static void bnxt_free_ctx_mem(struct bnxt_softc *softc)
 		if (!ctx_pg)
 			continue;
 		if (ctxm->instance_bmap)
-			n = hweight32(ctxm->instance_bmap);
+			n = bitcount32(ctxm->instance_bmap);
 		for (i = 0; i < n; i++)
 			bnxt_free_ctx_pg_tbls(softc, &ctx_pg[i]);
 
-		kfree(ctx_pg);
+		free(ctx_pg, M_DEVBUF);
 		ctxm->pg_info = NULL;
 	}
 
 	ctx->flags &= ~BNXT_CTX_FLAG_INITED;
-	kfree(ctx);
+	free(ctx, M_DEVBUF);
 	softc->ctx_mem = NULL;
 }
 
@@ -1316,7 +1348,7 @@ bnxt_bs_trace_init(struct bnxt_softc *bp, struct bnxt_ctx_mem_type *ctxm)
 
 	mem_size = ctxm->max_entries * ctxm->entry_size;
 	rem_bytes = mem_size % BNXT_PAGE_SIZE;
-	pages = DIV_ROUND_UP(mem_size, BNXT_PAGE_SIZE);
+	pages = howmany(mem_size, BNXT_PAGE_SIZE);
 
 	last_pg = (pages - 1) & (MAX_CTX_PAGES - 1);
 	magic_byte_offset = ((rem_bytes ? rem_bytes : BNXT_PAGE_SIZE) - size);
@@ -1902,13 +1934,13 @@ static void bnxt_rtnl_lock_sp(struct bnxt_softc *bp)
 	 * rtnl() and waiting for BNXT_STATE_IN_SP_TASK to clear.  So we
 	 * must clear BNXT_STATE_IN_SP_TASK before holding rtnl().
 	 */
-	clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
+	bnxt_drv_state_clear(bp, BNXT_STATE_IN_SP_TASK);
 	rtnl_lock();
 }
 
 static void bnxt_rtnl_unlock_sp(struct bnxt_softc *bp)
 {
-	set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
+	bnxt_drv_state_set(bp, BNXT_STATE_IN_SP_TASK);
 	rtnl_unlock();
 }
 
@@ -1947,18 +1979,19 @@ static u32 bnxt_fw_health_readl(struct bnxt_softc *bp, int reg_idx)
 }
 
 /*
- * Sleep until at least min_ms milliseconds have passed since start_jiffies.
+ * Sleep until at least min_ms milliseconds have passed since start_ticks.
  */
-static void bnxt_sleep_until_min_elapsed(unsigned long start_jiffies,
+static void bnxt_sleep_until_min_elapsed(unsigned long start_ticks,
     unsigned int min_ms)
 {
-	unsigned long elapsed_time;
+	int elapsed_time;
 	unsigned int elapsed_time_ms;
 
-	elapsed_time = jiffies - start_jiffies;
-	elapsed_time_ms = (unsigned int)(elapsed_time * 1000 / HZ);
+	elapsed_time = (int)(ticks - start_ticks);
+	elapsed_time_ms = (unsigned int)(elapsed_time * 1000 / hz);
 	if (elapsed_time_ms < min_ms)
-		msleep(min_ms - elapsed_time_ms);
+		pause_sbt("bxtms", SBT_1MS * (min_ms - elapsed_time_ms), 0,
+		    C_HARDCLOCK);
 }
 
 static void bnxt_fw_reset_close(struct bnxt_softc *bp)
@@ -1969,7 +2002,7 @@ static void bnxt_fw_reset_close(struct bnxt_softc *bp)
 	 * bus master to prevent any potential bad DMAs before freeing
 	 * kernel memory.
 	 */
-	if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state)) {
+	if (bnxt_drv_state_test(bp, BNXT_STATE_FW_FATAL_COND)) {
 		u16 val = 0;
 
 		val = pci_read_config(bp->dev, PCI_SUBSYSTEM_ID, 2);
@@ -2015,18 +2048,18 @@ static bool is_bnxt_fw_ok(struct bnxt_softc *bp)
 void bnxt_fw_reset(struct bnxt_softc *bp)
 {
 	bnxt_rtnl_lock_sp(bp);
-	if (test_bit(BNXT_STATE_OPEN, &bp->state) &&
-	    !test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) {
+	if (bnxt_drv_state_test(bp, BNXT_STATE_OPEN) &&
+	    !bnxt_drv_state_test(bp, BNXT_STATE_IN_FW_RESET)) {
 		int tmo;
-		set_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
+		bnxt_drv_state_set(bp, BNXT_STATE_IN_FW_RESET);
 		bnxt_fw_reset_close(bp);
 
 		if ((bp->fw_cap & BNXT_FW_CAP_ERR_RECOVER_RELOAD)) {
 			bp->fw_reset_state = BNXT_FW_RESET_STATE_POLL_FW_DOWN;
-			tmo = HZ / 10;
+			tmo = hz / 10;
 		} else {
 			bp->fw_reset_state = BNXT_FW_RESET_STATE_ENABLE_DEV;
-			tmo = bp->fw_reset_min_dsecs * HZ /10;
+			tmo = bp->fw_reset_min_dsecs * hz /10;
 		}
 		bnxt_queue_fw_reset_work(bp, tmo);
 	}
@@ -2035,21 +2068,27 @@ void bnxt_fw_reset(struct bnxt_softc *bp)
 
 static void bnxt_queue_fw_reset_work(struct bnxt_softc *bp, unsigned long delay)
 {
-	if (!(test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)))
+	int lticks;
+
+	if (!(bnxt_drv_state_test(bp, BNXT_STATE_IN_FW_RESET)))
 		return;
 
-	if (BNXT_PF(bp))
-		queue_delayed_work(bnxt_pf_wq, &bp->fw_reset_task, delay);
-	else
-		schedule_delayed_work(&bp->fw_reset_task, delay);
+	lticks = (int)delay;
+	if ((unsigned long)lticks != delay)
+		lticks = INT_MAX;
+	if (lticks < 1)
+		lticks = 1;
+	if (bnxt_taskq == NULL)
+		return;
+	taskqueue_enqueue_timeout(bnxt_taskq, &bp->fw_reset_tmo, lticks);
 }
 
 void bnxt_queue_sp_work(struct bnxt_softc *bp)
 {
-	if (BNXT_PF(bp))
-		queue_work(bnxt_pf_wq, &bp->sp_task);
-	else
-		schedule_work(&bp->sp_task);
+
+	if (bnxt_taskq == NULL)
+		return;
+	taskqueue_enqueue(bnxt_taskq, &bp->sp_task);
 }
 
 static void bnxt_fw_reset_writel(struct bnxt_softc *bp, int reg_idx)
@@ -2080,7 +2119,7 @@ static void bnxt_fw_reset_writel(struct bnxt_softc *bp, int reg_idx)
 	}
 	if (delay_msecs) {
 		pci_read_config_dword(bp->pdev, 0, &val);
-		msleep(delay_msecs);
+		pause_sbt("bxtms", SBT_1MS * delay_msecs, 0, C_HARDCLOCK);
 	}
 }
 
@@ -2090,7 +2129,7 @@ static void bnxt_reset_all(struct bnxt_softc *bp)
 	int i, rc;
 
 	if (bp->fw_cap & BNXT_FW_CAP_ERR_RECOVER_RELOAD) {
-		bp->fw_reset_timestamp = jiffies;
+		bp->fw_reset_timestamp = ticks;
 		return;
 	}
 
@@ -2110,7 +2149,7 @@ static void bnxt_reset_all(struct bnxt_softc *bp)
 		if (rc != -ENODEV)
 			device_printf(bp->dev, "Unable to reset FW rc=%d\n", rc);
 	}
-	bp->fw_reset_timestamp = jiffies;
+	bp->fw_reset_timestamp = ticks;
 }
 
 static int __bnxt_alloc_fw_health(struct bnxt_softc *bp)
@@ -2118,14 +2157,24 @@ static int __bnxt_alloc_fw_health(struct bnxt_softc *bp)
 	if (bp->fw_health)
 		return 0;
 
-	bp->fw_health = kzalloc(sizeof(*bp->fw_health), GFP_KERNEL);
+	bp->fw_health = malloc(sizeof(*bp->fw_health), M_DEVBUF, M_WAITOK | M_ZERO);
 	if (!bp->fw_health)
 		return -ENOMEM;
 
-	mutex_init(&bp->fw_health->lock);
+	mtx_init(&bp->fw_health->lock, "bnxt_fw_health", NULL, MTX_DEF);
 	return 0;
 }
 
+static void bnxt_free_fw_health(struct bnxt_softc *bp)
+{
+	if (!bp->fw_health)
+		return;
+
+	mtx_destroy(&bp->fw_health->lock);
+	free(bp->fw_health, M_DEVBUF);
+	bp->fw_health = NULL;
+}
+
 static int bnxt_alloc_fw_health(struct bnxt_softc *bp)
 {
 	int rc;
@@ -2301,8 +2350,8 @@ static int bnxt_drv_rgtr(struct bnxt_softc *bp)
 
 static bool bnxt_fw_reset_timeout(struct bnxt_softc *bp)
 {
-	return time_after(jiffies, bp->fw_reset_timestamp +
-			  (bp->fw_reset_max_dsecs * HZ / 10));
+	return BNXT_TIME_AFTER(ticks, bp->fw_reset_timestamp +
+			  (bp->fw_reset_max_dsecs * hz / 10));
 }
 
 /* enqueue an iflib reset and wait for RUNNING/OACTIVE to flip 1->0->1. */
@@ -2418,8 +2467,8 @@ static int bnxt_open(struct bnxt_softc *bp)
 
 	bnxt_msix_intr_assign(bp->ctx, 0);
 
-	if (test_and_clear_bit(BNXT_STATE_FW_RESET_DET, &bp->state)) {
-		if (!test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) {
+	if (bnxt_drv_state_test_and_clear(bp, BNXT_STATE_FW_RESET_DET)) {
+		if (!bnxt_drv_state_test(bp, BNXT_STATE_IN_FW_RESET)) {
 			bnxt_ulp_start(bp, 0);
 		}
 	}
@@ -2436,20 +2485,24 @@ static int bnxt_open(struct bnxt_softc *bp)
 }
 static void bnxt_fw_reset_abort(struct bnxt_softc *bp, int rc)
 {
-	clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
+	bnxt_drv_state_clear(bp, BNXT_STATE_IN_FW_RESET);
 	if (bp->fw_reset_state != BNXT_FW_RESET_STATE_POLL_VF) {
 		bnxt_ulp_start(bp, rc);
 	}
 	bp->fw_reset_state = 0;
 }
 
-static void bnxt_fw_reset_task(struct work_struct *work)
+static void
+bnxt_fw_reset_timeout_task(void *ctx, int pending)
 {
-	struct bnxt_softc *bp = container_of(work, struct bnxt_softc, fw_reset_task.work);
+	struct bnxt_softc *bp = ctx;
 	int rc = 0;
 
-	if (!test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) {
-		device_printf(bp->dev, "bnxt_fw_reset_task() called when not in fw reset mode!\n");
+	(void)pending;
+
+	if (!bnxt_drv_state_test(bp, BNXT_STATE_IN_FW_RESET)) {
+		device_printf(bp->dev,
+		    "bnxt_fw_reset_timeout_task() called when not in fw reset mode!\n");
 		return;
 	}
 
@@ -2460,7 +2513,7 @@ static void bnxt_fw_reset_task(struct work_struct *work)
 		val = bnxt_fw_health_readl(bp, BNXT_FW_HEALTH_REG);
 		if (!(val & BNXT_FW_STATUS_SHUTDOWN) &&
 		    !bnxt_fw_reset_timeout(bp)) {
-			bnxt_queue_fw_reset_work(bp, HZ / 5);
+			bnxt_queue_fw_reset_work(bp, hz / 5);
 			return;
 		}
 
@@ -2468,7 +2521,7 @@ static void bnxt_fw_reset_task(struct work_struct *work)
 			u32 wait_dsecs = bp->fw_health->normal_func_wait_dsecs;
 
 			bp->fw_reset_state = BNXT_FW_RESET_STATE_ENABLE_DEV;
-			bnxt_queue_fw_reset_work(bp, wait_dsecs * HZ / 10);
+			bnxt_queue_fw_reset_work(bp, wait_dsecs * hz / 10);
 			return;
 		}
 		bp->fw_reset_state = BNXT_FW_RESET_STATE_RESET_FW;
@@ -2477,11 +2530,11 @@ static void bnxt_fw_reset_task(struct work_struct *work)
 	case BNXT_FW_RESET_STATE_RESET_FW:
 		bnxt_reset_all(bp);
 		bp->fw_reset_state = BNXT_FW_RESET_STATE_ENABLE_DEV;
-		bnxt_queue_fw_reset_work(bp, bp->fw_reset_min_dsecs * HZ / 10);
+		bnxt_queue_fw_reset_work(bp, bp->fw_reset_min_dsecs * hz / 10);
 		return;
 	case BNXT_FW_RESET_STATE_ENABLE_DEV:
 		bnxt_inv_fw_health_reg(bp);
-		if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state) &&
+		if (bnxt_drv_state_test(bp, BNXT_STATE_FW_FATAL_COND) &&
 		    !bp->fw_reset_min_dsecs) {
 			u16 val;
 
@@ -2492,12 +2545,12 @@ static void bnxt_fw_reset_task(struct work_struct *work)
 					rc = -ETIMEDOUT;
 					goto fw_reset_abort;
 				}
-				bnxt_queue_fw_reset_work(bp, HZ / 1000);
+				bnxt_queue_fw_reset_work(bp, hz / 1000);
 				return;
 			}
 		}
-		clear_bit(BNXT_STATE_FW_FATAL_COND, &bp->state);
-		clear_bit(BNXT_STATE_FW_NON_FATAL_COND, &bp->state);
+		bnxt_drv_state_clear(bp, BNXT_STATE_FW_FATAL_COND);
+		bnxt_drv_state_clear(bp, BNXT_STATE_FW_NON_FATAL_COND);
 		if (!pci_is_enabled(bp->pdev)) {
 			if (pci_enable_device(bp->pdev)) {
 				device_printf(bp->dev, "Cannot re-enable PCI device\n");
@@ -2518,7 +2571,7 @@ static void bnxt_fw_reset_task(struct work_struct *work)
 				device_printf(bp->dev, "Firmware reset aborted\n");
 				goto fw_reset_abort_status;
 			}
-			bnxt_queue_fw_reset_work(bp, HZ / 5);
+			bnxt_queue_fw_reset_work(bp, hz / 5);
 			return;
 		}
 		bp->hwrm_cmd_timeo = DFLT_HWRM_CMD_TIMEOUT;
@@ -2539,10 +2592,10 @@ static void bnxt_fw_reset_task(struct work_struct *work)
 		}
 		bp->fw_reset_state = 0;
 		smp_mb__before_atomic();
-		clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
+		bnxt_drv_state_clear(bp, BNXT_STATE_IN_FW_RESET);
 		bnxt_ulp_start(bp, 0);
-		clear_bit(BNXT_STATE_FW_ACTIVATE, &bp->state);
-		set_bit(BNXT_STATE_OPEN, &bp->state);
+		bnxt_drv_state_clear(bp, BNXT_STATE_FW_ACTIVATE);
+		bnxt_drv_state_set(bp, BNXT_STATE_OPEN);
 		bnxt_crash_dump_init(bp);
 #ifdef PCI_IOV
 		bnxt_reenable_sriov(bp);
@@ -2569,8 +2622,8 @@ static void bnxt_force_fw_reset(struct bnxt_softc *bp)
 	struct bnxt_fw_health *fw_health = bp->fw_health;
 	u32 wait_dsecs;
 
-	if (!test_bit(BNXT_STATE_OPEN, &bp->state) ||
-	    test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
+	if (!bnxt_drv_state_test(bp, BNXT_STATE_OPEN) ||
+	    bnxt_drv_state_test(bp, BNXT_STATE_IN_FW_RESET))
 		return;
 	bnxt_fw_reset_close(bp);
 	wait_dsecs = fw_health->master_func_wait_dsecs;
@@ -2579,20 +2632,20 @@ static void bnxt_force_fw_reset(struct bnxt_softc *bp)
 			wait_dsecs = 0;
 		bp->fw_reset_state = BNXT_FW_RESET_STATE_RESET_FW;
 	} else {
-		bp->fw_reset_timestamp = jiffies + wait_dsecs * HZ / 10;
+		bp->fw_reset_timestamp = ticks + wait_dsecs * hz / 10;
 		wait_dsecs = fw_health->normal_func_wait_dsecs;
 		bp->fw_reset_state = BNXT_FW_RESET_STATE_ENABLE_DEV;
 	}
 
 	bp->fw_reset_min_dsecs = fw_health->post_reset_wait_dsecs;
 	bp->fw_reset_max_dsecs = fw_health->post_reset_max_wait_dsecs;
-	bnxt_queue_fw_reset_work(bp, wait_dsecs * HZ / 10);
+	bnxt_queue_fw_reset_work(bp, wait_dsecs * hz / 10);
 }
 
 static void bnxt_fw_exception(struct bnxt_softc *bp)
 {
 	device_printf(bp->dev, "Detected firmware fatal condition, initiating reset\n");
-	set_bit(BNXT_STATE_FW_FATAL_COND, &bp->state);
+	bnxt_drv_state_set(bp, BNXT_STATE_FW_FATAL_COND);
 	bnxt_rtnl_lock_sp(bp);
 	bnxt_force_fw_reset(bp);
 	bnxt_rtnl_unlock_sp(bp);
@@ -2600,8 +2653,8 @@ static void bnxt_fw_exception(struct bnxt_softc *bp)
 
 static void __bnxt_fw_recover(struct bnxt_softc *bp)
 {
-	if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state) ||
-	    test_bit(BNXT_STATE_FW_NON_FATAL_COND, &bp->state))
+	if (bnxt_drv_state_test(bp, BNXT_STATE_FW_FATAL_COND) ||
+	    bnxt_drv_state_test(bp, BNXT_STATE_FW_NON_FATAL_COND))
 		bnxt_fw_reset(bp);
 	else
 		bnxt_fw_exception(bp);
@@ -2620,36 +2673,39 @@ static void bnxt_devlink_health_fw_report(struct bnxt_softc *bp)
 	}
 }
 
-static void bnxt_sp_task(struct work_struct *work)
+static void
+bnxt_sp_task(void *ctx, int pending)
 {
-	struct bnxt_softc *bp = container_of(work, struct bnxt_softc, sp_task);
+	struct bnxt_softc *bp = ctx;
 
-	set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
+	(void)pending;
+
+	bnxt_drv_state_set(bp, BNXT_STATE_IN_SP_TASK);
 	smp_mb__after_atomic();
-	if (!test_bit(BNXT_STATE_OPEN, &bp->state)) {
-		clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
+	if (!bnxt_drv_state_test(bp, BNXT_STATE_OPEN)) {
+		bnxt_drv_state_clear(bp, BNXT_STATE_IN_SP_TASK);
 		return;
 	}
 
 #ifdef PCI_IOV
-	if (test_and_clear_bit(BNXT_HWRM_EXEC_FWD_REQ_SP_EVENT, &bp->sp_event))
+	if (bnxt_sp_event_test_and_clear(bp, BNXT_HWRM_EXEC_FWD_REQ_SP_EVENT))
 		bnxt_hwrm_exec_fwd_req(bp);
 #endif
 
-	if (test_and_clear_bit(BNXT_FW_RESET_NOTIFY_SP_EVENT, &bp->sp_event)) {
-		if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state) ||
-		    test_bit(BNXT_STATE_FW_NON_FATAL_COND, &bp->state))
+	if (bnxt_sp_event_test_and_clear(bp, BNXT_FW_RESET_NOTIFY_SP_EVENT)) {
+		if (bnxt_drv_state_test(bp, BNXT_STATE_FW_FATAL_COND) ||
+		    bnxt_drv_state_test(bp, BNXT_STATE_FW_NON_FATAL_COND))
 			bnxt_devlink_health_fw_report(bp);
 		else
 			bnxt_fw_reset(bp);
 	}
 
-	if (test_and_clear_bit(BNXT_FW_EXCEPTION_SP_EVENT, &bp->sp_event)) {
+	if (bnxt_sp_event_test_and_clear(bp, BNXT_FW_EXCEPTION_SP_EVENT)) {
 		if (!is_bnxt_fw_ok(bp))
 			bnxt_devlink_health_fw_report(bp);
 	}
 	smp_mb__before_atomic();
-	clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
+	bnxt_drv_state_clear(bp, BNXT_STATE_IN_SP_TASK);
 }
 
 int
@@ -2730,7 +2786,7 @@ bnxt_attach_pre(if_ctx_t ctx)
 		goto pci_map_fail;
 	}
 
-	softc->pdev = kzalloc(sizeof(*softc->pdev), GFP_KERNEL);
+	softc->pdev = malloc(sizeof(*softc->pdev), M_DEVBUF, M_WAITOK | M_ZERO);
 	if (!softc->pdev) {
 		device_printf(softc->dev, "pdev alloc failed\n");
 		rc = -ENOMEM;
@@ -2807,16 +2863,6 @@ bnxt_attach_pre(if_ctx_t ctx)
 
 	/* Get NVRAM info */
 	if (BNXT_PF(softc)) {
-		if (!bnxt_pf_wq) {
-			bnxt_pf_wq =
-				create_singlethread_workqueue("bnxt_pf_wq");
-			if (!bnxt_pf_wq) {
-				device_printf(softc->dev, "Unable to create workqueue.\n");
-				rc = -ENOMEM;
-				goto nvm_alloc_fail;
-			}
-		}
-
 		softc->nvm_info = malloc(sizeof(struct bnxt_nvram_info),
 		    M_DEVBUF, M_NOWAIT | M_ZERO);
 		if (softc->nvm_info == NULL) {
@@ -3137,9 +3183,16 @@ bnxt_attach_pre(if_ctx_t ctx)
 		}
 	}
 
-	set_bit(BNXT_STATE_OPEN, &softc->state);
-	INIT_WORK(&softc->sp_task, bnxt_sp_task);
-	INIT_DELAYED_WORK(&softc->fw_reset_task, bnxt_fw_reset_task);
+	bnxt_drv_state_set(softc, BNXT_STATE_OPEN);
+	if (bnxt_taskq == NULL) {
+		device_printf(softc->dev, "Unable to create taskqueue.\n");
+		rc = -ENOMEM;
+		bnxt_drv_state_clear(softc, BNXT_STATE_OPEN);
+		goto failed;
+	}
+	TASK_INIT(&softc->sp_task, 0, bnxt_sp_task, softc);
+	TIMEOUT_TASK_INIT(bnxt_taskq, &softc->fw_reset_tmo, 0,
+	    bnxt_fw_reset_timeout_task, softc);
 
 	/* Initialize the vlan list */
 	SLIST_INIT(&softc->vnic_info.vlan_tags);
@@ -3178,7 +3231,7 @@ dma_fail:
 	if (softc->pdev)
 		linux_pci_detach_device(softc->pdev);
 pci_attach_fail:
-	kfree(softc->pdev);
+	free(softc->pdev, M_DEVBUF);
 	softc->pdev = NULL;
 free_pci_map:
 	bnxt_pci_mapping_free(softc);
@@ -3294,8 +3347,10 @@ bnxt_detach(if_ctx_t ctx)
 
 	bnxt_mpc_irq_cleanup(softc);
 	bnxt_rdma_aux_device_uninit(softc);
-	cancel_delayed_work_sync(&softc->fw_reset_task);
-	cancel_work_sync(&softc->sp_task);
+	if (bnxt_taskq != NULL) {
+		taskqueue_drain_timeout(bnxt_taskq, &softc->fw_reset_tmo);
+		taskqueue_drain(bnxt_taskq, &softc->sp_task);
+	}
 	bnxt_dcb_free(softc);
 
 #ifdef KERN_TLS
@@ -3357,6 +3412,7 @@ bnxt_detach(if_ctx_t ctx)
 	bnxt_free_mpcs(softc);
 	bnxt_free_mpc_info(softc);
 	bnxt_free_ctx_mem(softc);
+	bnxt_free_fw_health(softc);
 	bnxt_clear_ids(softc);
 	iflib_irq_free(ctx, &softc->def_cp_ring.irq);
 	/* We need to free() these here... */
@@ -3389,11 +3445,6 @@ bnxt_detach(if_ctx_t ctx)
 	bnxt_unregister_logger(softc, BNXT_LOGGER_L2);
 	mtx_destroy(&softc->log_lock);
 
-	if (!bnxt_num_pfs && bnxt_pf_wq) {
-		destroy_workqueue(bnxt_pf_wq);
-		bnxt_pf_wq = NULL;
-	}
-
 	if (softc->pdev)
 		linux_pci_detach_device(softc->pdev);
 	free(softc->state_bv, M_DEVBUF);
@@ -3510,7 +3561,7 @@ bnxt_func_reset(struct bnxt_softc *softc)
 		return;
 	}
 
-	if (!test_bit(BNXT_STATE_IN_FW_RESET, &softc->state))
+	if (!bnxt_drv_state_test(softc, BNXT_STATE_IN_FW_RESET))
 		bnxt_hwrm_resource_free(softc);
 	return;
 }
@@ -3562,7 +3613,7 @@ static void bnxt_get_port_module_status(struct bnxt_softc *softc)
 
 static void bnxt_aux_dev_free(struct bnxt_softc *softc)
 {
-	kfree(softc->aux_dev);
+	free(softc->aux_dev, M_DEVBUF);
 	softc->aux_dev = NULL;
 }
 
@@ -3570,12 +3621,12 @@ static struct bnxt_aux_dev *bnxt_aux_dev_init(struct bnxt_softc *softc)
 {
 	struct bnxt_aux_dev *bnxt_adev;
 
-	msleep(1000 * 2);
-	bnxt_adev = kzalloc(sizeof(*bnxt_adev), GFP_KERNEL);
+	pause_sbt("bxtms", SBT_1MS * 1000 * 2, 0, C_HARDCLOCK);
+	bnxt_adev = malloc(sizeof(*bnxt_adev), M_DEVBUF, M_WAITOK | M_ZERO);
 	if (!bnxt_adev)
-		return ERR_PTR(-ENOMEM);
*** 107 LINES SKIPPED ***