git: 8945584f93ee - main - if_bnxt: add support for Thor controller
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 04 Nov 2022 22:55:46 UTC
The branch main has been updated by imp: URL: https://cgit.FreeBSD.org/src/commit/?id=8945584f93ee3689c90fd6b6ee6d824381813ef2 commit 8945584f93ee3689c90fd6b6ee6d824381813ef2 Author: Sumit Saxena <sumit.saxena@broadcom.com> AuthorDate: 2022-11-04 22:05:57 +0000 Commit: Warner Losh <imp@FreeBSD.org> CommitDate: 2022-11-04 22:05:57 +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 --- 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++) + for (i = 0; i < 8; i++) req.async_event_fwd[i] |= htole32(events[i]); *** 2070 LINES SKIPPED ***