git: de0aaf9eca0a - stable/13 - if_bnxt: add support for Thor controller

From: Warner Losh <imp_at_FreeBSD.org>
Date: Thu, 19 Jan 2023 03:52:12 UTC
The branch stable/13 has been updated by imp:

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

commit de0aaf9eca0ae7d7f44042c24fba92a6db491b98
Author:     Sumit Saxena <sumit.saxena@broadcom.com>
AuthorDate: 2022-11-04 22:05:57 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2023-01-19 01:00:05 +0000

    if_bnxt: add support for Thor controller
    
    Added support for Thor controller.
    Below are the supported operations:
    
    1. IPv4 ping (ICMP)
    2. iperf / netperf (IPv4 TCP)
    3. Promiscuous (tcpdump)
    4. Can achieve 20 Gbps on a 25 G link (Uni-Di)
    5. Can achieve 60 Gbps on a 100 G link (Uni-Di)
    6. Port level and queue level driver stats.
    
    Reviewed by: imp
    Differential Revision: https://reviews.freebsd.org/D36438
    
    (cherry picked from commit 8945584f93ee3689c90fd6b6ee6d824381813ef2)
---
 sys/dev/bnxt/bnxt.h        | 187 +++++++++-
 sys/dev/bnxt/bnxt_hwrm.c   | 520 +++++++++++++++++++++++++---
 sys/dev/bnxt/bnxt_hwrm.h   |  11 +-
 sys/dev/bnxt/bnxt_sysctl.c | 285 +++++++--------
 sys/dev/bnxt/bnxt_txrx.c   |   5 +-
 sys/dev/bnxt/if_bnxt.c     | 840 +++++++++++++++++++++++++++++++++++++++------
 6 files changed, 1547 insertions(+), 301 deletions(-)

diff --git a/sys/dev/bnxt/bnxt.h b/sys/dev/bnxt/bnxt.h
index 8d806c3a4877..5a68b24e44f5 100644
--- a/sys/dev/bnxt/bnxt.h
+++ b/sys/dev/bnxt/bnxt.h
@@ -80,6 +80,9 @@ __FBSDID("$FreeBSD$");
 #define BCM57417_SFP	0x16e2
 #define BCM57454	0x1614
 #define BCM58700	0x16cd
+#define BCM57508  	0x1750
+#define BCM57504  	0x1751
+#define BCM57502  	0x1752
 #define NETXTREME_C_VF1	0x16cb
 #define NETXTREME_C_VF2	0x16e1
 #define NETXTREME_C_VF3	0x16e5
@@ -110,10 +113,52 @@ __FBSDID("$FreeBSD$");
 #define bnxt_wol_supported(softc)	(!((softc)->flags & BNXT_FLAG_VF) && \
 					  ((softc)->flags & BNXT_FLAG_WOL_CAP ))
 
+/* 64-bit doorbell */
+#define DBR_INDEX_MASK                                  0x0000000000ffffffULL
+#define DBR_PI_LO_MASK                                  0xff000000UL
+#define DBR_PI_LO_SFT                                   24
+#define DBR_XID_MASK                                    0x000fffff00000000ULL
+#define DBR_XID_SFT                                     32
+#define DBR_PI_HI_MASK                                  0xf0000000000000ULL
+#define DBR_PI_HI_SFT                                   52
+#define DBR_PATH_L2                                     (0x1ULL << 56)
+#define DBR_VALID                                       (0x1ULL << 58)
+#define DBR_TYPE_SQ                                     (0x0ULL << 60)
+#define DBR_TYPE_RQ                                     (0x1ULL << 60)
+#define DBR_TYPE_SRQ                                    (0x2ULL << 60)
+#define DBR_TYPE_SRQ_ARM                                (0x3ULL << 60)
+#define DBR_TYPE_CQ                                     (0x4ULL << 60)
+#define DBR_TYPE_CQ_ARMSE                               (0x5ULL << 60)
+#define DBR_TYPE_CQ_ARMALL                              (0x6ULL << 60)
+#define DBR_TYPE_CQ_ARMENA                              (0x7ULL << 60)
+#define DBR_TYPE_SRQ_ARMENA                             (0x8ULL << 60)
+#define DBR_TYPE_CQ_CUTOFF_ACK                          (0x9ULL << 60)
+#define DBR_TYPE_NQ                                     (0xaULL << 60)
+#define DBR_TYPE_NQ_ARM                                 (0xbULL << 60)
+#define DBR_TYPE_PUSH_START                             (0xcULL << 60)
+#define DBR_TYPE_PUSH_END                               (0xdULL << 60)
+#define DBR_TYPE_NULL                                   (0xfULL << 60)
+
+#define BNXT_MAX_NUM_QUEUES 32
+
 /* Completion related defines */
 #define CMP_VALID(cmp, v_bit) \
 	((!!(((struct cmpl_base *)(cmp))->info3_v & htole32(CMPL_BASE_V))) == !!(v_bit) )
 
+/* Chip class phase 5 */
+#define BNXT_CHIP_P5(sc) ((softc->flags & BNXT_FLAG_CHIP_P5))
+
+#define DB_PF_OFFSET_P5                                 0x10000
+#define NQ_VALID(cmp, v_bit) \
+	((!!(((nq_cn_t *)(cmp))->v & htole32(NQ_CN_V))) == !!(v_bit) )
+
+#ifndef DIV_ROUND_UP
+#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
+#endif
+#ifndef roundup
+#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
+#endif
+
 #define NEXT_CP_CONS_V(ring, cons, v_bit) do {				    \
 	if (__predict_false(++(cons) == (ring)->ring_size))		    \
 		((cons) = 0, (v_bit) = !v_bit);				    \
@@ -400,6 +445,7 @@ struct bnxt_ring {
 	uint32_t		ring_size;	/* Must be a power of two */
 	uint16_t		id;		/* Logical ID */
 	uint16_t		phys_id;
+	uint16_t		idx;
 	struct bnxt_full_tpa_start *tpa_start;
 };
 
@@ -413,6 +459,7 @@ struct bnxt_cp_ring {
 	uint32_t		last_idx;	/* Used by RX rings only
 						 * set to the last read pidx
 						 */
+	uint64_t 		int_count;
 };
 
 struct bnxt_full_tpa_start {
@@ -484,12 +531,129 @@ struct bnxt_hw_lro {
 	uint32_t min_agg_len;
 };
 
+/* The hardware supports certain page sizes.  Use the supported page sizes
+ * to allocate the rings.
+ */
+#if (PAGE_SHIFT < 12)
+#define BNXT_PAGE_SHIFT 12
+#elif (PAGE_SHIFT <= 13)
+#define BNXT_PAGE_SHIFT PAGE_SHIFT
+#elif (PAGE_SHIFT < 16)
+#define BNXT_PAGE_SHIFT 13
+#else
+#define BNXT_PAGE_SHIFT 16
+#endif
+
+#define BNXT_PAGE_SIZE  (1 << BNXT_PAGE_SHIFT)
+
+#define MAX_CTX_PAGES	(BNXT_PAGE_SIZE / 8)
+#define MAX_CTX_TOTAL_PAGES	(MAX_CTX_PAGES * MAX_CTX_PAGES)
+struct bnxt_ring_mem_info {
+        int                     nr_pages;
+        int                     page_size;
+        uint16_t                     flags;
+#define BNXT_RMEM_VALID_PTE_FLAG        1
+#define BNXT_RMEM_RING_PTE_FLAG         2
+#define BNXT_RMEM_USE_FULL_PAGE_FLAG    4
+        uint16_t		depth;
+	uint8_t			init_val;
+        struct iflib_dma_info	*pg_arr;
+        struct iflib_dma_info	pg_tbl;
+        int                     vmem_size;
+        void                    **vmem;
+};
+
+struct bnxt_ctx_pg_info {
+	uint32_t		entries;
+	uint32_t		nr_pages;
+	struct iflib_dma_info   ctx_arr[MAX_CTX_PAGES];
+	struct bnxt_ring_mem_info ring_mem;
+	struct bnxt_ctx_pg_info **ctx_pg_tbl;
+};
+
+struct bnxt_ctx_mem_info {
+	uint32_t	qp_max_entries;
+	uint16_t	qp_min_qp1_entries;
+	uint16_t	qp_max_l2_entries;
+	uint16_t	qp_entry_size;
+	uint16_t	srq_max_l2_entries;
+	uint32_t	srq_max_entries;
+	uint16_t	srq_entry_size;
+	uint16_t	cq_max_l2_entries;
+	uint32_t	cq_max_entries;
+	uint16_t	cq_entry_size;
+	uint16_t	vnic_max_vnic_entries;
+	uint16_t	vnic_max_ring_table_entries;
+	uint16_t	vnic_entry_size;
+	uint32_t	stat_max_entries;
+	uint16_t	stat_entry_size;
+	uint16_t	tqm_entry_size;
+	uint32_t	tqm_min_entries_per_ring;
+	uint32_t	tqm_max_entries_per_ring;
+	uint32_t	mrav_max_entries;
+	uint16_t	mrav_entry_size;
+	uint16_t	tim_entry_size;
+	uint32_t	tim_max_entries;
+	uint8_t		tqm_entries_multiple;
+	uint8_t		ctx_kind_initializer;
+
+	uint32_t	flags;
+	#define BNXT_CTX_FLAG_INITED	0x01
+
+	struct bnxt_ctx_pg_info qp_mem;
+	struct bnxt_ctx_pg_info srq_mem;
+	struct bnxt_ctx_pg_info cq_mem;
+	struct bnxt_ctx_pg_info vnic_mem;
+	struct bnxt_ctx_pg_info stat_mem;
+	struct bnxt_ctx_pg_info mrav_mem;
+	struct bnxt_ctx_pg_info tim_mem;
+	struct bnxt_ctx_pg_info *tqm_mem[9];
+};
+
+struct bnxt_hw_resc {
+        uint16_t     min_rsscos_ctxs;
+        uint16_t     max_rsscos_ctxs;
+        uint16_t     min_cp_rings;
+        uint16_t     max_cp_rings;
+        uint16_t     resv_cp_rings;
+        uint16_t     min_tx_rings;
+        uint16_t     max_tx_rings;
+        uint16_t     resv_tx_rings;
+        uint16_t     max_tx_sch_inputs;
+        uint16_t     min_rx_rings;
+        uint16_t     max_rx_rings;
+        uint16_t     resv_rx_rings;
+        uint16_t     min_hw_ring_grps;
+        uint16_t     max_hw_ring_grps;
+        uint16_t     resv_hw_ring_grps;
+        uint16_t     min_l2_ctxs;
+        uint16_t     max_l2_ctxs;
+        uint16_t     min_vnics;
+        uint16_t     max_vnics;
+        uint16_t     resv_vnics;
+        uint16_t     min_stat_ctxs;
+        uint16_t     max_stat_ctxs;
+        uint16_t     resv_stat_ctxs;
+        uint16_t     max_nqs;
+        uint16_t     max_irqs;
+        uint16_t     resv_irqs;
+};
+
+#define BNXT_LLQ(q_profile)     \
+        ((q_profile) == HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID0_SERVICE_PROFILE_LOSSLESS_ROCE)
+#define BNXT_CNPQ(q_profile)    \
+        ((q_profile) == HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID0_SERVICE_PROFILE_LOSSY_ROCE_CNP)
+
+#define BNXT_HWRM_MAX_REQ_LEN		(softc->hwrm_max_req_len)
+
 struct bnxt_softc {
 	device_t	dev;
 	if_ctx_t	ctx;
 	if_softc_ctx_t	scctx;
 	if_shared_ctx_t	sctx;
 	struct ifmedia	*media;
+	struct bnxt_ctx_mem_info *ctx_mem;
+	struct bnxt_hw_resc hw_resc;
 
 	struct bnxt_bar_info	hwrm_bar;
 	struct bnxt_bar_info	doorbell_bar;
@@ -497,7 +661,10 @@ struct bnxt_softc {
 #define BNXT_FLAG_VF		0x0001
 #define BNXT_FLAG_NPAR		0x0002
 #define BNXT_FLAG_WOL_CAP	0x0004
-#define BNXT_FLAG_SHORT_CMD	0x0008 
+#define BNXT_FLAG_SHORT_CMD	0x0008
+#define BNXT_FLAG_FW_CAP_NEW_RM 0x0010
+#define BNXT_FLAG_CHIP_P5 	0x0020
+#define BNXT_FLAG_TPA	 	0x0040
 	uint32_t		flags;
 	uint32_t		total_msix;
 
@@ -514,10 +681,16 @@ struct bnxt_softc {
 	struct if_irq		irq;
 	struct mtx		hwrm_lock;
 	uint16_t		hwrm_max_req_len;
+	uint16_t		hwrm_max_ext_req_len;
+	uint32_t		hwrm_spec_code;
 
-#define BNXT_MAX_QUEUE		8
+#define BNXT_MAX_COS_QUEUE	8
 	uint8_t			max_tc;
-	struct bnxt_cos_queue	q_info[BNXT_MAX_QUEUE];
+        uint8_t			max_lltc;       /* lossless TCs */
+	struct bnxt_cos_queue	q_info[BNXT_MAX_COS_QUEUE];
+        uint8_t			tc_to_qidx[BNXT_MAX_COS_QUEUE];
+        uint8_t			q_ids[BNXT_MAX_COS_QUEUE];
+        uint8_t			max_q;
 
 	uint64_t		admin_ticks;
 	struct iflib_dma_info	hw_rx_port_stats;
@@ -527,9 +700,11 @@ struct bnxt_softc {
 
 	int			num_cp_rings;
 
+	struct bnxt_cp_ring	*nq_rings;
+
 	struct bnxt_ring	*tx_rings;
 	struct bnxt_cp_ring	*tx_cp_rings;
-	struct iflib_dma_info	tx_stats;
+	struct iflib_dma_info	tx_stats[BNXT_MAX_NUM_QUEUES];
 	int			ntxqsets;
 
 	struct bnxt_vnic_info	vnic_info;
@@ -537,11 +712,13 @@ struct bnxt_softc {
 	struct bnxt_ring	*rx_rings;
 	struct bnxt_cp_ring	*rx_cp_rings;
 	struct bnxt_grp_info	*grp_info;
-	struct iflib_dma_info	rx_stats;
+	struct iflib_dma_info	rx_stats[BNXT_MAX_NUM_QUEUES];
 	int			nrxqsets;
 
 	struct bnxt_cp_ring	def_cp_ring;
+	struct bnxt_cp_ring	def_nq_ring;
 	struct iflib_dma_info	def_cp_ring_mem;
+	struct iflib_dma_info	def_nq_ring_mem;
 	struct grouptask	def_cp_task;
 	struct bnxt_doorbell_ops db_ops;
 
diff --git a/sys/dev/bnxt/bnxt_hwrm.c b/sys/dev/bnxt/bnxt_hwrm.c
index d474e5b81e19..981bab37c181 100644
--- a/sys/dev/bnxt/bnxt_hwrm.c
+++ b/sys/dev/bnxt/bnxt_hwrm.c
@@ -121,19 +121,30 @@ _hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
 	int i;
 	uint8_t *valid;
 	uint16_t err;
-	uint16_t max_req_len = HWRM_MAX_REQ_LEN;
+	uint16_t max_req_len = BNXT_HWRM_MAX_REQ_LEN;
 	struct hwrm_short_input short_input = {0};
 
 	/* TODO: DMASYNC in here. */
 	req->seq_id = htole16(softc->hwrm_cmd_seq++);
 	memset(resp, 0, PAGE_SIZE);
 
-	if (softc->flags & BNXT_FLAG_SHORT_CMD) {
+	if ((softc->flags & BNXT_FLAG_SHORT_CMD) ||
+	    msg_len > BNXT_HWRM_MAX_REQ_LEN) {
 		void *short_cmd_req = softc->hwrm_short_cmd_req_addr.idi_vaddr;
+                uint16_t max_msg_len;
+
+                /* Set boundary for maximum extended request length for short
+                 * cmd format. If passed up from device use the max supported
+                 * internal req length.
+		 */
+
+		max_msg_len = softc->hwrm_max_ext_req_len;
+
 
 		memcpy(short_cmd_req, req, msg_len);
-		memset((uint8_t *) short_cmd_req + msg_len, 0, softc->hwrm_max_req_len-
-		    msg_len);
+                if (msg_len < max_msg_len)
+			memset((uint8_t *) short_cmd_req + msg_len, 0,
+				max_msg_len - msg_len);
 
 		short_input.req_type = req->req_type;
 		short_input.signature =
@@ -228,12 +239,12 @@ hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
 int
 bnxt_hwrm_queue_qportcfg(struct bnxt_softc *softc)
 {
+	int rc = 0;
 	struct hwrm_queue_qportcfg_input req = {0};
 	struct hwrm_queue_qportcfg_output *resp =
 	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
-
-	int	rc = 0;
-	uint8_t	*qptr;
+	uint8_t i, j, *qptr;
+	bool no_rdma;
 
 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_QPORTCFG);
 
@@ -247,18 +258,283 @@ bnxt_hwrm_queue_qportcfg(struct bnxt_softc *softc)
 		goto qportcfg_exit;
 	}
 	softc->max_tc = resp->max_configurable_queues;
-	if (softc->max_tc > BNXT_MAX_QUEUE)
-		softc->max_tc = BNXT_MAX_QUEUE;
+	softc->max_lltc = resp->max_configurable_lossless_queues;
+	if (softc->max_tc > BNXT_MAX_COS_QUEUE)
+		softc->max_tc = BNXT_MAX_COS_QUEUE;
+
+	/* Currently no RDMA support */
+	no_rdma = true;
 
 	qptr = &resp->queue_id0;
-	for (int i = 0; i < softc->max_tc; i++) {
-		softc->q_info[i].id = *qptr++;
-		softc->q_info[i].profile = *qptr++;
+	for (i = 0, j = 0; i < softc->max_tc; i++) {
+		softc->q_info[j].id = *qptr;
+		softc->q_ids[i] = *qptr++;
+		softc->q_info[j].profile = *qptr++;
+		softc->tc_to_qidx[j] = j;
+		if (!BNXT_CNPQ(softc->q_info[j].profile) ||
+				(no_rdma && BNXT_PF(softc)))
+			j++;
 	}
+	softc->max_q = softc->max_tc;
+	softc->max_tc = max_t(uint32_t, j, 1);
+
+	if (resp->queue_cfg_info & HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_CFG_INFO_ASYM_CFG)
+		softc->max_tc = 1;
+
+	if (softc->max_lltc > softc->max_tc)
+		softc->max_lltc = softc->max_tc;
 
 qportcfg_exit:
 	BNXT_HWRM_UNLOCK(softc);
-	return (rc);
+	return rc;
+}
+
+int bnxt_hwrm_func_backing_store_qcaps(struct bnxt_softc *softc)
+{
+	struct hwrm_func_backing_store_qcaps_input req = {0};
+	struct hwrm_func_backing_store_qcaps_output *resp =
+	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
+	int rc;
+
+	if (softc->hwrm_spec_code < 0x10902 || BNXT_VF(softc) || softc->ctx_mem)
+		return 0;
+
+	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_BACKING_STORE_QCAPS);
+	BNXT_HWRM_LOCK(softc);
+	rc = _hwrm_send_message(softc, &req, sizeof(req));
+	if (!rc) {
+		struct bnxt_ctx_pg_info *ctx_pg;
+		struct bnxt_ctx_mem_info *ctx;
+		int i;
+
+		ctx = malloc(sizeof(*ctx), M_DEVBUF, M_NOWAIT | M_ZERO);
+		if (!ctx) {
+			rc = -ENOMEM;
+			goto ctx_err;
+		}
+		ctx_pg = malloc(sizeof(*ctx_pg) * (softc->max_q + 1),
+				M_DEVBUF, M_NOWAIT | M_ZERO);
+		if (!ctx_pg) {
+			free(ctx, M_DEVBUF);
+			rc = -ENOMEM;
+			goto ctx_err;
+		}
+		for (i = 0; i < softc->max_q + 1; i++, ctx_pg++)
+			ctx->tqm_mem[i] = ctx_pg;
+
+		softc->ctx_mem = ctx;
+		ctx->qp_max_entries = le32toh(resp->qp_max_entries);
+		ctx->qp_min_qp1_entries = le16toh(resp->qp_min_qp1_entries);
+		ctx->qp_max_l2_entries = le16toh(resp->qp_max_l2_entries);
+		ctx->qp_entry_size = le16toh(resp->qp_entry_size);
+		ctx->srq_max_l2_entries = le16toh(resp->srq_max_l2_entries);
+		ctx->srq_max_entries = le32toh(resp->srq_max_entries);
+		ctx->srq_entry_size = le16toh(resp->srq_entry_size);
+		ctx->cq_max_l2_entries = le16toh(resp->cq_max_l2_entries);
+		ctx->cq_max_entries = le32toh(resp->cq_max_entries);
+		ctx->cq_entry_size = le16toh(resp->cq_entry_size);
+		ctx->vnic_max_vnic_entries =
+			le16toh(resp->vnic_max_vnic_entries);
+		ctx->vnic_max_ring_table_entries =
+			le16toh(resp->vnic_max_ring_table_entries);
+		ctx->vnic_entry_size = le16toh(resp->vnic_entry_size);
+		ctx->stat_max_entries = le32toh(resp->stat_max_entries);
+		ctx->stat_entry_size = le16toh(resp->stat_entry_size);
+		ctx->tqm_entry_size = le16toh(resp->tqm_entry_size);
+		ctx->tqm_min_entries_per_ring =
+			le32toh(resp->tqm_min_entries_per_ring);
+		ctx->tqm_max_entries_per_ring =
+			le32toh(resp->tqm_max_entries_per_ring);
+		ctx->tqm_entries_multiple = resp->tqm_entries_multiple;
+		if (!ctx->tqm_entries_multiple)
+			ctx->tqm_entries_multiple = 1;
+		ctx->mrav_max_entries = le32toh(resp->mrav_max_entries);
+		ctx->mrav_entry_size = le16toh(resp->mrav_entry_size);
+		ctx->tim_entry_size = le16toh(resp->tim_entry_size);
+		ctx->tim_max_entries = le32toh(resp->tim_max_entries);
+		ctx->ctx_kind_initializer = resp->ctx_kind_initializer;
+	} else {
+		rc = 0;
+	}
+ctx_err:
+	BNXT_HWRM_UNLOCK(softc);
+	return rc;
+}
+
+#define HWRM_FUNC_BACKING_STORE_CFG_INPUT_DFLT_ENABLES                 \
+        (HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_QP |                \
+         HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_SRQ |               \
+         HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_CQ |                \
+         HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_VNIC |              \
+         HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_STAT)
+
+static void bnxt_hwrm_set_pg_attr(struct bnxt_ring_mem_info *rmem, uint8_t *pg_attr,
+				  uint64_t *pg_dir)
+{
+	uint8_t pg_size = 0;
+
+	if (BNXT_PAGE_SHIFT == 13)
+		pg_size = 1 << 4;
+	else if (BNXT_PAGE_SIZE == 16)
+		pg_size = 2 << 4;
+
+	*pg_attr = pg_size;
+	if (rmem->depth >= 1) {
+		if (rmem->depth == 2)
+			*pg_attr |= HWRM_FUNC_BACKING_STORE_CFG_INPUT_QPC_LVL_LVL_2;
+		else
+			*pg_attr |= HWRM_FUNC_BACKING_STORE_CFG_INPUT_QPC_LVL_LVL_1;
+		*pg_dir = htole64(rmem->pg_tbl.idi_paddr);
+	} else {
+		*pg_dir = htole64(rmem->pg_arr[0].idi_paddr);
+	}
+}
+
+int bnxt_hwrm_func_backing_store_cfg(struct bnxt_softc *softc, uint32_t enables)
+{
+	struct hwrm_func_backing_store_cfg_input req = {0};
+	struct bnxt_ctx_mem_info *ctx = softc->ctx_mem;
+	struct bnxt_ctx_pg_info *ctx_pg;
+	uint32_t *num_entries;
+	uint64_t *pg_dir;
+	uint8_t *pg_attr;
+	int i, rc;
+	uint32_t ena;
+
+	if (!ctx)
+		return 0;
+
+	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_BACKING_STORE_CFG);
+	req.enables = htole32(enables);
+
+	if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_QP) {
+		ctx_pg = &ctx->qp_mem;
+		req.qp_num_entries = htole32(ctx_pg->entries);
+		req.qp_num_qp1_entries = htole16(ctx->qp_min_qp1_entries);
+		req.qp_num_l2_entries = htole16(ctx->qp_max_l2_entries);
+		req.qp_entry_size = htole16(ctx->qp_entry_size);
+		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
+				&req.qpc_pg_size_qpc_lvl,
+				&req.qpc_page_dir);
+	}
+	if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_SRQ) {
+		ctx_pg = &ctx->srq_mem;
+		req.srq_num_entries = htole32(ctx_pg->entries);
+		req.srq_num_l2_entries = htole16(ctx->srq_max_l2_entries);
+		req.srq_entry_size = htole16(ctx->srq_entry_size);
+		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
+				&req.srq_pg_size_srq_lvl,
+				&req.srq_page_dir);
+	}
+	if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_CQ) {
+		ctx_pg = &ctx->cq_mem;
+		req.cq_num_entries = htole32(ctx_pg->entries);
+		req.cq_num_l2_entries = htole16(ctx->cq_max_l2_entries);
+		req.cq_entry_size = htole16(ctx->cq_entry_size);
+		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem, &req.cq_pg_size_cq_lvl,
+				&req.cq_page_dir);
+	}
+	if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_MRAV) {
+		ctx_pg = &ctx->mrav_mem;
+		req.mrav_num_entries = htole32(ctx_pg->entries);
+		req.mrav_entry_size = htole16(ctx->mrav_entry_size);
+		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
+				&req.mrav_pg_size_mrav_lvl,
+				&req.mrav_page_dir);
+	}
+	if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_TIM) {
+		ctx_pg = &ctx->tim_mem;
+		req.tim_num_entries = htole32(ctx_pg->entries);
+		req.tim_entry_size = htole16(ctx->tim_entry_size);
+		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
+				&req.tim_pg_size_tim_lvl,
+				&req.tim_page_dir);
+	}
+	if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_VNIC) {
+		ctx_pg = &ctx->vnic_mem;
+		req.vnic_num_vnic_entries =
+			htole16(ctx->vnic_max_vnic_entries);
+		req.vnic_num_ring_table_entries =
+			htole16(ctx->vnic_max_ring_table_entries);
+		req.vnic_entry_size = htole16(ctx->vnic_entry_size);
+		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
+				&req.vnic_pg_size_vnic_lvl,
+				&req.vnic_page_dir);
+	}
+	if (enables & HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_STAT) {
+		ctx_pg = &ctx->stat_mem;
+		req.stat_num_entries = htole32(ctx->stat_max_entries);
+		req.stat_entry_size = htole16(ctx->stat_entry_size);
+		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem,
+				&req.stat_pg_size_stat_lvl,
+				&req.stat_page_dir);
+	}
+	for (i = 0, num_entries = &req.tqm_sp_num_entries,
+			pg_attr = &req.tqm_sp_pg_size_tqm_sp_lvl,
+			pg_dir = &req.tqm_sp_page_dir,
+			ena = HWRM_FUNC_BACKING_STORE_CFG_INPUT_ENABLES_TQM_SP;
+			i < 9; i++, num_entries++, pg_attr++, pg_dir++, ena <<= 1) {
+		if (!(enables & ena))
+			continue;
+
+		req.tqm_entry_size = htole16(ctx->tqm_entry_size);
+		ctx_pg = ctx->tqm_mem[i];
+		*num_entries = htole32(ctx_pg->entries);
+		bnxt_hwrm_set_pg_attr(&ctx_pg->ring_mem, pg_attr, pg_dir);
+	}
+	rc = hwrm_send_message(softc, &req, sizeof(req));
+	if (rc)
+		rc = -EIO;
+	return rc;
+}
+
+int bnxt_hwrm_func_resc_qcaps(struct bnxt_softc *softc, bool all)
+{
+        struct hwrm_func_resource_qcaps_output *resp =
+	    (void *)softc->hwrm_cmd_resp.idi_vaddr;
+        struct hwrm_func_resource_qcaps_input req = {0};
+        struct bnxt_hw_resc *hw_resc = &softc->hw_resc;
+        int rc;
+
+        bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_RESOURCE_QCAPS);
+        req.fid = htole16(0xffff);
+
+	BNXT_HWRM_LOCK(softc);
+        rc = _hwrm_send_message(softc, &req, sizeof(req));
+        if (rc) {
+                rc = -EIO;
+                goto hwrm_func_resc_qcaps_exit;
+        }
+
+        hw_resc->max_tx_sch_inputs = le16toh(resp->max_tx_scheduler_inputs);
+        if (!all)
+                goto hwrm_func_resc_qcaps_exit;
+
+        hw_resc->min_rsscos_ctxs = le16toh(resp->min_rsscos_ctx);
+        hw_resc->max_rsscos_ctxs = le16toh(resp->max_rsscos_ctx);
+        hw_resc->min_cp_rings = le16toh(resp->min_cmpl_rings);
+        hw_resc->max_cp_rings = le16toh(resp->max_cmpl_rings);
+        hw_resc->min_tx_rings = le16toh(resp->min_tx_rings);
+        hw_resc->max_tx_rings = le16toh(resp->max_tx_rings);
+        hw_resc->min_rx_rings = le16toh(resp->min_rx_rings);
+        hw_resc->max_rx_rings = le16toh(resp->max_rx_rings);
+        hw_resc->min_hw_ring_grps = le16toh(resp->min_hw_ring_grps);
+        hw_resc->max_hw_ring_grps = le16toh(resp->max_hw_ring_grps);
+        hw_resc->min_l2_ctxs = le16toh(resp->min_l2_ctxs);
+        hw_resc->max_l2_ctxs = le16toh(resp->max_l2_ctxs);
+        hw_resc->min_vnics = le16toh(resp->min_vnics);
+        hw_resc->max_vnics = le16toh(resp->max_vnics);
+        hw_resc->min_stat_ctxs = le16toh(resp->min_stat_ctx);
+        hw_resc->max_stat_ctxs = le16toh(resp->max_stat_ctx);
+
+	if (BNXT_CHIP_P5(softc)) {
+                hw_resc->max_nqs = le16toh(resp->max_msix);
+                hw_resc->max_hw_ring_grps = hw_resc->max_rx_rings;
+        }
+
+hwrm_func_resc_qcaps_exit:
+	BNXT_HWRM_UNLOCK(softc);
+        return rc;
 }
 
 int
@@ -297,6 +573,16 @@ bnxt_hwrm_ver_get(struct bnxt_softc *softc)
 	strlcpy(softc->ver_info->hwrm_fw_name, resp->hwrm_fw_name,
 	    BNXT_NAME_SIZE);
 
+	 softc->hwrm_spec_code = resp->hwrm_intf_maj_8b << 16 |
+                             resp->hwrm_intf_min_8b << 8 |
+                             resp->hwrm_intf_upd_8b;
+	if (resp->hwrm_intf_maj_8b < 1) {
+		 device_printf(softc->dev, "HWRM interface %d.%d.%d is older "
+			       "than 1.0.0.\n", resp->hwrm_intf_maj_8b,
+			       resp->hwrm_intf_min_8b, resp->hwrm_intf_upd_8b);
+		 device_printf(softc->dev, "Please update firmware with HWRM "
+				"interface 1.0.0 or newer.\n");
+	 }
 	if (resp->mgmt_fw_major == 0 && resp->mgmt_fw_minor == 0 &&
 	    resp->mgmt_fw_build == 0) {
 		strlcpy(softc->ver_info->mgmt_fw_ver, naver, BNXT_VERSTR_SIZE);
@@ -341,10 +627,16 @@ bnxt_hwrm_ver_get(struct bnxt_softc *softc)
 	softc->ver_info->chip_bond_id = resp->chip_bond_id;
 	softc->ver_info->chip_type = resp->chip_platform_type;
 
-	if (resp->max_req_win_len)
+
+	if (resp->hwrm_intf_maj_8b >= 1) {
 		softc->hwrm_max_req_len = le16toh(resp->max_req_win_len);
-	if (resp->def_req_timeout)
-		softc->hwrm_cmd_timeo = le16toh(resp->def_req_timeout);
+		softc->hwrm_max_ext_req_len = le16toh(resp->max_ext_req_len);
+	}
+#define DFLT_HWRM_CMD_TIMEOUT		500
+	softc->hwrm_cmd_timeo = le16toh(resp->def_req_timeout);
+	if (!softc->hwrm_cmd_timeo)
+		softc->hwrm_cmd_timeo = DFLT_HWRM_CMD_TIMEOUT;
+
 
 	dev_caps_cfg = le32toh(resp->dev_caps_cfg);
 	if ((dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_SUPPORTED) &&
@@ -464,7 +756,7 @@ fail:
 	return rc;
 }
 
-int 
+int
 bnxt_hwrm_func_qcfg(struct bnxt_softc *softc)
 {
         struct hwrm_func_qcfg_input req = {0};
@@ -609,11 +901,11 @@ bnxt_hwrm_set_link_setting(struct bnxt_softc *softc, bool set_pause,
 
 	if (!rc) {
 		if (set_pause) {
-			/* since changing of 'force pause' setting doesn't 
+			/* since changing of 'force pause' setting doesn't
 			 * trigger any link change event, the driver needs to
 			 * update the current pause result upon successfully i
 			 * return of the phy_cfg command */
-			if (!softc->link_info.flow_ctrl.autoneg) 
+			if (!softc->link_info.flow_ctrl.autoneg)
 				bnxt_report_link(softc);
 		}
 	}
@@ -634,14 +926,25 @@ bnxt_hwrm_vnic_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
 		req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_BD_STALL_MODE);
 	if (vnic->flags & BNXT_VNIC_FLAG_VLAN_STRIP)
 		req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_VLAN_STRIP_MODE);
-	req.enables = htole32(HWRM_VNIC_CFG_INPUT_ENABLES_DFLT_RING_GRP |
-	    HWRM_VNIC_CFG_INPUT_ENABLES_RSS_RULE |
-	    HWRM_VNIC_CFG_INPUT_ENABLES_MRU);
-	req.vnic_id = htole16(vnic->id);
-	req.dflt_ring_grp = htole16(vnic->def_ring_grp);
+	if (BNXT_CHIP_P5 (softc)) {
+		req.default_rx_ring_id =
+			htole16(softc->rx_rings[0].phys_id);
+		req.default_cmpl_ring_id =
+			htole16(softc->rx_cp_rings[0].ring.phys_id);
+		req.enables |=
+			htole32(HWRM_VNIC_CFG_INPUT_ENABLES_DEFAULT_RX_RING_ID |
+			    HWRM_VNIC_CFG_INPUT_ENABLES_DEFAULT_CMPL_RING_ID);
+		req.vnic_id = htole16(vnic->id);
+	} else {
+		req.enables = htole32(HWRM_VNIC_CFG_INPUT_ENABLES_DFLT_RING_GRP |
+				HWRM_VNIC_CFG_INPUT_ENABLES_RSS_RULE);
+		req.vnic_id = htole16(vnic->id);
+		req.dflt_ring_grp = htole16(vnic->def_ring_grp);
+	}
 	req.rss_rule = htole16(vnic->rss_id);
 	req.cos_rule = htole16(vnic->cos_rule);
 	req.lb_rule = htole16(vnic->lb_rule);
+	req.enables |= htole32(HWRM_VNIC_CFG_INPUT_ENABLES_MRU);
 	req.mru = htole16(vnic->mru);
 
 	return hwrm_send_message(softc, &req, sizeof(req));
@@ -719,6 +1022,9 @@ bnxt_hwrm_ring_grp_alloc(struct bnxt_softc *softc, struct bnxt_grp_info *grp)
 		return EDOOFUS;
 	}
 
+	if (BNXT_CHIP_P5 (softc))
+		return 0;
+
 	resp = (void *)softc->hwrm_cmd_resp.idi_vaddr;
 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_GRP_ALLOC);
 	req.cr = htole16(grp->cp_ring_id);
@@ -743,11 +1049,12 @@ fail:
  */
 int
 bnxt_hwrm_ring_alloc(struct bnxt_softc *softc, uint8_t type,
-    struct bnxt_ring *ring, uint16_t cmpl_ring_id, uint32_t stat_ctx_id,
-    bool irq)
+                     struct bnxt_ring *ring)
 {
 	struct hwrm_ring_alloc_input req = {0};
 	struct hwrm_ring_alloc_output *resp;
+	uint16_t idx = ring->idx;
+	struct bnxt_cp_ring *cp_ring;
 	int rc;
 
 	if (ring->phys_id != (uint16_t)HWRM_NA_SIGNATURE) {
@@ -760,27 +1067,72 @@ bnxt_hwrm_ring_alloc(struct bnxt_softc *softc, uint8_t type,
 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_ALLOC);
 	req.enables = htole32(0);
 	req.fbo = htole32(0);
-
-	if (stat_ctx_id != HWRM_NA_SIGNATURE) {
-		req.enables |= htole32(
-		    HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
-		req.stat_ctx_id = htole32(stat_ctx_id);
-	}
 	req.ring_type = type;
 	req.page_tbl_addr = htole64(ring->paddr);
-	req.length = htole32(ring->ring_size);
 	req.logical_id = htole16(ring->id);
-	req.cmpl_ring_id = htole16(cmpl_ring_id);
-	req.queue_id = htole16(softc->q_info[0].id);
-#if 0
-	/* MODE_POLL appears to crash the firmware */
-	if (irq)
-		req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
-	else
-		req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_POLL;
-#else
-	req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
-#endif
+	req.length = htole32(ring->ring_size);
+
+	switch (type) {
+        case HWRM_RING_ALLOC_INPUT_RING_TYPE_TX:
+		cp_ring = &softc->tx_cp_rings[idx];
+
+                req.cmpl_ring_id = htole16(cp_ring->ring.phys_id);
+		/* queue_id - what CoS queue the TX ring is associated with */
+                req.queue_id = htole16(softc->q_info[0].id);
+
+                req.stat_ctx_id = htole32(cp_ring->stats_ctx_id);
+		req.enables |= htole32(
+		    HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
+                break;
+        case HWRM_RING_ALLOC_INPUT_RING_TYPE_RX:
+		if (!BNXT_CHIP_P5(softc))
+			break;
+
+		cp_ring = &softc->rx_cp_rings[idx];
+
+                req.stat_ctx_id = htole32(cp_ring->stats_ctx_id);
+		req.rx_buf_size = htole16(
+			softc->scctx->isc_max_frame_size);
+                req.enables |= htole32(
+			HWRM_RING_ALLOC_INPUT_ENABLES_RX_BUF_SIZE_VALID |
+			HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
+                break;
+        case HWRM_RING_ALLOC_INPUT_RING_TYPE_RX_AGG:
+		if (!BNXT_CHIP_P5(softc)) {
+                        req.ring_type = HWRM_RING_ALLOC_INPUT_RING_TYPE_RX;
+			break;
+                }
+
+		cp_ring = &softc->rx_cp_rings[idx];
+
+                req.rx_ring_id = htole16(softc->rx_rings[idx].phys_id);
+		req.stat_ctx_id = htole32(cp_ring->stats_ctx_id);
+		req.rx_buf_size = htole16(
+			softc->scctx->isc_max_frame_size);
+                req.enables |= htole32(
+                            HWRM_RING_ALLOC_INPUT_ENABLES_RX_RING_ID_VALID |
+                            HWRM_RING_ALLOC_INPUT_ENABLES_RX_BUF_SIZE_VALID |
+			    HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
+                break;
+       case HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL:
+		if (!BNXT_CHIP_P5(softc)) {
+                        req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
+			break;
+		}
+
+                req.cq_handle = htole64(ring->id);
+		req.nq_ring_id = htole16(softc->nq_rings[idx].ring.phys_id);
+		req.enables |= htole32(
+			HWRM_RING_ALLOC_INPUT_ENABLES_NQ_RING_ID_VALID);
+                break;
+        case HWRM_RING_ALLOC_INPUT_RING_TYPE_NQ:
+                req.int_mode = HWRM_RING_ALLOC_INPUT_INT_MODE_MSIX;
+                break;
+        default:
+                printf("hwrm alloc invalid ring type %d\n", type);
+                return -1;
+        }
+
 	BNXT_HWRM_LOCK(softc);
 	rc = _hwrm_send_message(softc, &req, sizeof(req));
 	if (rc)
@@ -813,6 +1165,10 @@ bnxt_hwrm_stat_ctx_alloc(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr,
 
 	req.update_period_ms = htole32(1000);
 	req.stats_dma_addr = htole64(paddr);
+	if (BNXT_CHIP_P5(softc))
+		req.stats_dma_length = htole16(sizeof(struct ctx_hw_stats_ext) - 8);
+	else
+		req.stats_dma_length = htole16(sizeof(struct ctx_hw_stats));
 
 	BNXT_HWRM_LOCK(softc);
 	rc = _hwrm_send_message(softc, &req, sizeof(req));
@@ -943,6 +1299,9 @@ bnxt_hwrm_rss_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic,
 {
 	struct hwrm_vnic_rss_cfg_input	req = {0};
 
+	/* TBD */
+	if (BNXT_CHIP_P5(softc))
+		return 0;
 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_CFG);
 
 	req.hash_type = htole32(hash_type);
@@ -953,6 +1312,32 @@ bnxt_hwrm_rss_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic,
 	return hwrm_send_message(softc, &req, sizeof(req));
 }
 
+int
+bnxt_hwrm_reserve_pf_rings(struct bnxt_softc *softc)
+{
+	struct hwrm_func_cfg_input req = {0};
+
+	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_CFG);
+
+	req.fid = htole16(0xffff);
+	req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_RSSCOS_CTXS);
+	req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_CMPL_RINGS);
+	req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_TX_RINGS);
+	req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_RX_RINGS);
+	req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_VNICS);
+	req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_MSIX);
+	req.enables |= htole32(HWRM_FUNC_CFG_INPUT_ENABLES_NUM_STAT_CTXS);
+	req.num_msix = htole16(BNXT_MAX_NUM_QUEUES);
+	req.num_rsscos_ctxs = htole16(0x8);
+	req.num_cmpl_rings = htole16(BNXT_MAX_NUM_QUEUES * 2);
+	req.num_tx_rings = htole16(BNXT_MAX_NUM_QUEUES);
+	req.num_rx_rings = htole16(BNXT_MAX_NUM_QUEUES);
+	req.num_vnics = htole16(BNXT_MAX_NUM_QUEUES);
+	req.num_stat_ctxs = htole16(BNXT_MAX_NUM_QUEUES * 2);
+
+	return hwrm_send_message(softc, &req, sizeof(req));
+}
+
 int
 bnxt_cfg_async_cr(struct bnxt_softc *softc)
 {
@@ -1008,6 +1393,9 @@ bnxt_hwrm_vnic_tpa_cfg(struct bnxt_softc *softc)
 		return 0;
 	}
 
+	if (!(softc->flags & BNXT_FLAG_TPA))
+		return 0;
+
 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_TPA_CFG);
 
 	if (softc->hw_lro.enable) {
@@ -1548,14 +1936,14 @@ bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc)
 	link_info->auto_mode = resp->auto_mode;
 
         /*
-         * When AUTO_PAUSE_AUTONEG_PAUSE bit is set to 1, 
+         * When AUTO_PAUSE_AUTONEG_PAUSE bit is set to 1,
          * the advertisement of pause is enabled.
          * 1. When the auto_mode is not set to none and this flag is set to 1,
          *    then the auto_pause bits on this port are being advertised and
          *    autoneg pause results are being interpreted.
          * 2. When the auto_mode is not set to none and this flag is set to 0,
-         *    the pause is forced as indicated in force_pause, and also 
-	 *    advertised as auto_pause bits, but the autoneg results are not 
+         *    the pause is forced as indicated in force_pause, and also
+	 *    advertised as auto_pause bits, but the autoneg results are not
 	 *    interpreted since the pause configuration is being forced.
          * 3. When the auto_mode is set to none and this flag is set to 1,
          *    auto_pause bits should be ignored and should be set to 0.
@@ -1565,7 +1953,7 @@ bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc)
 	link_info->flow_ctrl.tx = false;
 	link_info->flow_ctrl.rx = false;
 
-	if ((resp->auto_mode) && 
+	if ((resp->auto_mode) &&
             (resp->auto_pause & BNXT_AUTO_PAUSE_AUTONEG_PAUSE)) {
 			link_info->flow_ctrl.autoneg = true;
 	}
@@ -1739,7 +2127,7 @@ int bnxt_hwrm_set_coal(struct bnxt_softc *softc)
                                   buf_tmr_irq << 16 | buf_tmr, flags, &req_tx);
 
         for (i = 0; i < softc->nrxqsets; i++) {
-                
+
 		req = &req_rx;
                 /*
                  * TBD:
@@ -1765,14 +2153,18 @@ int bnxt_hwrm_func_rgtr_async_events(struct bnxt_softc *softc, unsigned long *bm
 	uint32_t *events;
 	int i;
 
-#define AE_BMAP_SZ_BITS	256
-	async_events_bmap = bit_alloc(AE_BMAP_SZ_BITS, M_DEVBUF, M_WAITOK);
+#define BNXT_MAX_NUM_ASYNC_EVENTS 256
+	async_events_bmap = bit_alloc(BNXT_MAX_NUM_ASYNC_EVENTS, M_DEVBUF,
+			M_WAITOK|M_ZERO);
+	events = (uint32_t *)async_events_bmap;
 
 	bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR);
 
 	req.enables =
 		htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_ASYNC_EVENT_FWD);
 
+	memset(async_events_bmap, 0, sizeof(BNXT_MAX_NUM_ASYNC_EVENTS / 8));
+
 	bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE);
 	bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD);
 	bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED);
@@ -1786,14 +2178,30 @@ int bnxt_hwrm_func_rgtr_async_events(struct bnxt_softc *softc, unsigned long *bm
 		}
 	}
 
-#define AE_BMAP_SZ_WORDS	(AE_BMAP_SZ_BITS / 8 / sizeof(uint32_t))
-	events = (uint32_t *)async_events_bmap;
-	for (i = 0; i < AE_BMAP_SZ_WORDS; i++)
*** 2072 LINES SKIPPED ***