git: 22dcbd7739a1 - main - if_bnxt: port workqueue, task-queue, and synchronization kPIs to FreeBSD natives
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
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 ***