git: 107e02d70619 - stable/14 - bnxt_en: L2-RoCE driver communication interface
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 03 Jun 2024 19:25:02 UTC
The branch stable/14 has been updated by imp: URL: https://cgit.FreeBSD.org/src/commit/?id=107e02d70619c9f660deb67fba7f4525ad100ef2 commit 107e02d70619c9f660deb67fba7f4525ad100ef2 Author: Chandrakanth patil <chandrakanth.patil@broadcom.com> AuthorDate: 2024-04-28 12:29:34 +0000 Commit: Warner Losh <imp@FreeBSD.org> CommitDate: 2024-06-03 19:23:14 +0000 bnxt_en: L2-RoCE driver communication interface - Added Aux bus support for RoCE. - Implemented the ulp ops that are required by RoCE driver. - Restructure context memory data structures - DBR pacing support Reviewed by: imp Approved by: imp Differential revision: https://reviews.freebsd.org/D45006 (cherry picked from commit 050d28e13cdede7528944c0abf8d0455729c63fd) --- sys/dev/bnxt/bnxt_en/bnxt.h | 252 +++++++++++--- sys/dev/bnxt/bnxt_en/bnxt_auxbus_compat.c | 194 +++++++++++ sys/dev/bnxt/bnxt_en/bnxt_auxbus_compat.h | 75 ++++ sys/dev/bnxt/bnxt_en/bnxt_hwrm.c | 488 +++++++++++++++++--------- sys/dev/bnxt/bnxt_en/bnxt_hwrm.h | 7 +- sys/dev/bnxt/bnxt_en/bnxt_sysctl.c | 3 - sys/dev/bnxt/bnxt_en/bnxt_ulp.c | 524 ++++++++++++++++++++++++++++ sys/dev/bnxt/bnxt_en/bnxt_ulp.h | 161 +++++++++ sys/dev/bnxt/bnxt_en/hsi_struct_def.h | 7 +- sys/dev/bnxt/bnxt_en/if_bnxt.c | 551 +++++++++++++++++++++++------- sys/modules/bnxt/bnxt_en/Makefile | 6 +- 11 files changed, 1928 insertions(+), 340 deletions(-) diff --git a/sys/dev/bnxt/bnxt_en/bnxt.h b/sys/dev/bnxt/bnxt_en/bnxt.h index e68943fd6286..ab60ddf74672 100644 --- a/sys/dev/bnxt/bnxt_en/bnxt.h +++ b/sys/dev/bnxt/bnxt_en/bnxt.h @@ -42,9 +42,13 @@ #include <net/if.h> #include <net/if_var.h> #include <net/iflib.h> +#include <linux/types.h> #include "hsi_struct_def.h" #include "bnxt_dcb.h" +#include "bnxt_auxbus_compat.h" + +#define DFLT_HWRM_CMD_TIMEOUT 500 /* PCI IDs */ #define BROADCOM_VENDOR_ID 0x14E4 @@ -90,6 +94,58 @@ #define NETXTREME_E_VF2 0x16d3 #define NETXTREME_E_VF3 0x16dc +#define EVENT_DATA1_RESET_NOTIFY_FATAL(data1) \ + (((data1) & \ + HWRM_ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_MASK) ==\ + HWRM_ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_FW_EXCEPTION_FATAL) + +#define BNXT_EVENT_ERROR_REPORT_TYPE(data1) \ + (((data1) & \ + HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_MASK) >> \ + HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_SFT) + +#define BNXT_EVENT_INVALID_SIGNAL_DATA(data2) \ + (((data2) & \ + HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_INVALID_SIGNAL_EVENT_DATA2_PIN_ID_MASK) >> \ + HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_INVALID_SIGNAL_EVENT_DATA2_PIN_ID_SFT) + +#define BNXT_EVENT_DBR_EPOCH(data) \ + (((data) & HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_DOORBELL_DROP_THRESHOLD_EVENT_DATA1_EPOCH_MASK) >> \ + HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_DOORBELL_DROP_THRESHOLD_EVENT_DATA1_EPOCH_SFT) + +#define BNXT_EVENT_THERMAL_THRESHOLD_TEMP(data2) \ + (((data2) & \ + HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA2_THRESHOLD_TEMP_MASK) >> \ + HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA2_THRESHOLD_TEMP_SFT) + +#define EVENT_DATA2_NVM_ERR_ADDR(data2) \ + (((data2) & \ + HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_NVM_EVENT_DATA2_ERR_ADDR_MASK) >> \ + HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_NVM_EVENT_DATA2_ERR_ADDR_SFT) + +#define EVENT_DATA1_THERMAL_THRESHOLD_DIR_INCREASING(data1) \ + (((data1) & \ + HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_TRANSITION_DIR) == \ + HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_TRANSITION_DIR_INCREASING) + +#define EVENT_DATA1_NVM_ERR_TYPE_WRITE(data1) \ + (((data1) & \ + HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_NVM_EVENT_DATA1_NVM_ERR_TYPE_MASK) == \ + HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_NVM_EVENT_DATA1_NVM_ERR_TYPE_WRITE) + +#define EVENT_DATA1_NVM_ERR_TYPE_ERASE(data1) \ + (((data1) & \ + HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_NVM_EVENT_DATA1_NVM_ERR_TYPE_MASK) == \ + HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_NVM_EVENT_DATA1_NVM_ERR_TYPE_ERASE) + +#define EVENT_DATA1_THERMAL_THRESHOLD_TYPE(data1) \ + ((data1) & HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_MASK) + +#define BNXT_EVENT_THERMAL_CURRENT_TEMP(data2) \ + ((data2) & HWRM_ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA2_CURRENT_TEMP_MASK) + +#define INVALID_STATS_CTX_ID -1 + /* Maximum numbers of RX and TX descriptors. iflib requires this to be a power * of two. The hardware has no particular limitation. */ #define BNXT_MAX_RXD ((INT32_MAX >> 1) + 1) @@ -139,16 +195,20 @@ #define DBR_TYPE_PUSH_END (0xdULL << 60) #define DBR_TYPE_NULL (0xfULL << 60) -#define BNXT_MAX_NUM_QUEUES 32 +#define BNXT_MAX_L2_QUEUES 128 +#define BNXT_ROCE_IRQ_COUNT 9 + +#define BNXT_MAX_NUM_QUEUES (BNXT_MAX_L2_QUEUES + BNXT_ROCE_IRQ_COUNT) /* 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 BNXT_CHIP_P5(sc) ((sc->flags & BNXT_FLAG_CHIP_P5)) #define DB_PF_OFFSET_P5 0x10000 +#define DB_VF_OFFSET_P5 0x4000 #define NQ_VALID(cmp, v_bit) \ ((!!(((nq_cn_t *)(cmp))->v & htole32(NQ_CN_V))) == !!(v_bit) ) @@ -509,10 +569,9 @@ struct bnxt_ver_info { uint8_t hwrm_if_update; char hwrm_if_ver[BNXT_VERSTR_SIZE]; char driver_hwrm_if_ver[BNXT_VERSTR_SIZE]; - char hwrm_fw_ver[BNXT_VERSTR_SIZE]; - char mgmt_fw_ver[BNXT_VERSTR_SIZE]; - char netctrl_fw_ver[BNXT_VERSTR_SIZE]; - char roce_fw_ver[BNXT_VERSTR_SIZE]; + char mgmt_fw_ver[FW_VER_STR_LEN]; + char netctrl_fw_ver[FW_VER_STR_LEN]; + char roce_fw_ver[FW_VER_STR_LEN]; char fw_ver_str[FW_VER_STR_LEN]; char phy_ver[BNXT_VERSTR_SIZE]; char pkg_ver[64]; @@ -589,19 +648,22 @@ struct bnxt_hw_lro { #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; + 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; + uint16_t depth; + struct bnxt_ctx_mem_type *ctx_mem; + + struct iflib_dma_info *pg_arr; + struct iflib_dma_info pg_tbl; + + int vmem_size; + void **vmem; }; struct bnxt_ctx_pg_info { @@ -612,43 +674,85 @@ struct bnxt_ctx_pg_info { struct bnxt_ctx_pg_info **ctx_pg_tbl; }; +#define BNXT_MAX_TQM_SP_RINGS 1 +#define BNXT_MAX_TQM_FP_LEGACY_RINGS 8 +#define BNXT_MAX_TQM_FP_RINGS 9 +#define BNXT_MAX_TQM_LEGACY_RINGS \ + (BNXT_MAX_TQM_SP_RINGS + BNXT_MAX_TQM_FP_LEGACY_RINGS) +#define BNXT_MAX_TQM_RINGS \ + (BNXT_MAX_TQM_SP_RINGS + BNXT_MAX_TQM_FP_RINGS) + +#define BNXT_BACKING_STORE_CFG_LEGACY_LEN 256 +#define BNXT_BACKING_STORE_CFG_LEN \ + sizeof(struct hwrm_func_backing_store_cfg_input) + +#define BNXT_SET_CTX_PAGE_ATTR(attr) \ +do { \ + if (BNXT_PAGE_SIZE == 0x2000) \ + attr = HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_SRQ_PG_SIZE_PG_8K; \ + else if (BNXT_PAGE_SIZE == 0x10000) \ + attr = HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_QPC_PG_SIZE_PG_64K; \ + else \ + attr = HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_QPC_PG_SIZE_PG_4K; \ +} while (0) + +struct bnxt_ctx_mem_type { + u16 type; + u16 entry_size; + u32 flags; +#define BNXT_CTX_MEM_TYPE_VALID HWRM_FUNC_BACKING_STORE_QCAPS_V2_OUTPUT_FLAGS_TYPE_VALID + u32 instance_bmap; + u8 init_value; + u8 entry_multiple; + u16 init_offset; +#define BNXT_CTX_INIT_INVALID_OFFSET 0xffff + u32 max_entries; + u32 min_entries; + u8 split_entry_cnt; +#define BNXT_MAX_SPLIT_ENTRY 4 + union { + struct { + u32 qp_l2_entries; + u32 qp_qp1_entries; + }; + u32 srq_l2_entries; + u32 cq_l2_entries; + u32 vnic_entries; + struct { + u32 mrav_av_entries; + u32 mrav_num_entries_units; + }; + u32 split[BNXT_MAX_SPLIT_ENTRY]; + }; + struct bnxt_ctx_pg_info *pg_info; +}; + +#define BNXT_CTX_QP HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_QP +#define BNXT_CTX_SRQ HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_SRQ +#define BNXT_CTX_CQ HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_CQ +#define BNXT_CTX_VNIC HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_VNIC +#define BNXT_CTX_STAT HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_STAT +#define BNXT_CTX_STQM HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_SP_TQM_RING +#define BNXT_CTX_FTQM HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_FP_TQM_RING +#define BNXT_CTX_MRAV HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_MRAV +#define BNXT_CTX_TIM HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_TIM +#define BNXT_CTX_TKC HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_TKC +#define BNXT_CTX_RKC HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_RKC +#define BNXT_CTX_MTQM HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_MP_TQM_RING +#define BNXT_CTX_SQDBS HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_SQ_DB_SHADOW +#define BNXT_CTX_RQDBS HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_RQ_DB_SHADOW +#define BNXT_CTX_SRQDBS HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_SRQ_DB_SHADOW +#define BNXT_CTX_CQDBS HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_CQ_DB_SHADOW +#define BNXT_CTX_QTKC HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_QUIC_TKC +#define BNXT_CTX_QRKC HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_QUIC_RKC +#define BNXT_CTX_MAX (BNXT_CTX_QRKC + 1) + 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; + u8 tqm_fp_rings_count; - uint32_t flags; + u32 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_ctx_mem_type ctx_arr[BNXT_CTX_MAX]; }; struct bnxt_hw_resc { @@ -678,7 +782,7 @@ struct bnxt_hw_resc { uint16_t max_nqs; uint16_t max_irqs; uint16_t resv_irqs; -} +}; enum bnxt_type_ets { BNXT_TYPE_ETS_TSA = 0, @@ -710,11 +814,23 @@ struct bnxt_softc_list { #define BIT_ULL(nr) (1ULL << (nr)) #endif +struct bnxt_aux_dev { + struct auxiliary_device aux_dev; + struct bnxt_en_dev *edev; + int id; +}; + +struct bnxt_msix_tbl { + uint32_t entry; + uint32_t vector; +}; + struct bnxt_softc { device_t dev; if_ctx_t ctx; if_softc_ctx_t scctx; if_shared_ctx_t sctx; + if_t ifp; uint32_t domain; uint32_t bus; uint32_t slot; @@ -738,11 +854,16 @@ struct bnxt_softc { #define BNXT_FLAG_FW_CAP_EXT_STATS 0x0080 #define BNXT_FLAG_MULTI_HOST 0x0100 #define BNXT_FLAG_MULTI_ROOT 0x0200 +#define BNXT_FLAG_ROCEV1_CAP 0x0400 +#define BNXT_FLAG_ROCEV2_CAP 0x0800 +#define BNXT_FLAG_ROCE_CAP (BNXT_FLAG_ROCEV1_CAP | BNXT_FLAG_ROCEV2_CAP) uint32_t flags; #define BNXT_STATE_LINK_CHANGE (0) #define BNXT_STATE_MAX (BNXT_STATE_LINK_CHANGE + 1) bitstr_t *state_bv; - uint32_t total_msix; + + uint32_t total_irqs; + struct bnxt_msix_tbl *irq_tbl; struct bnxt_func_info func; struct bnxt_func_qcfg fn_qcfg; @@ -812,6 +933,8 @@ struct bnxt_softc { struct iflib_dma_info def_cp_ring_mem; struct iflib_dma_info def_nq_ring_mem; struct grouptask def_cp_task; + int db_size; + int legacy_db_size; struct bnxt_doorbell_ops db_ops; struct sysctl_ctx_list hw_stats; @@ -908,6 +1031,33 @@ struct bnxt_softc { #define BNXT_PHY_FL_NO_PAUSE (HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS2_PAUSE_UNSUPPORTED << 8) #define BNXT_PHY_FL_NO_PFC (HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS2_PFC_UNSUPPORTED << 8) #define BNXT_PHY_FL_BANK_SEL (HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS2_BANK_ADDR_SUPPORTED << 8) + struct bnxt_aux_dev *aux_dev; + struct net_device *net_dev; + struct mtx en_ops_lock; + uint8_t port_partition_type; + struct bnxt_en_dev *edev; + unsigned long state; +#define BNXT_STATE_OPEN 0 +#define BNXT_STATE_IN_SP_TASK 1 +#define BNXT_STATE_READ_STATS 2 +#define BNXT_STATE_FW_RESET_DET 3 +#define BNXT_STATE_IN_FW_RESET 4 +#define BNXT_STATE_ABORT_ERR 5 +#define BNXT_STATE_FW_FATAL_COND 6 +#define BNXT_STATE_DRV_REGISTERED 7 +#define BNXT_STATE_PCI_CHANNEL_IO_FROZEN 8 +#define BNXT_STATE_NAPI_DISABLED 9 +#define BNXT_STATE_L2_FILTER_RETRY 10 +#define BNXT_STATE_FW_ACTIVATE 11 +#define BNXT_STATE_RECOVER 12 +#define BNXT_STATE_FW_NON_FATAL_COND 13 +#define BNXT_STATE_FW_ACTIVATE_RESET 14 +#define BNXT_STATE_HALF_OPEN 15 +#define BNXT_NO_FW_ACCESS(bp) \ + test_bit(BNXT_STATE_FW_FATAL_COND, &(bp)->state) + struct pci_dev *pdev; + + int fw_reset_state; }; struct bnxt_filter_info { diff --git a/sys/dev/bnxt/bnxt_en/bnxt_auxbus_compat.c b/sys/dev/bnxt/bnxt_en/bnxt_auxbus_compat.c new file mode 100644 index 000000000000..1014d360015a --- /dev/null +++ b/sys/dev/bnxt/bnxt_en/bnxt_auxbus_compat.c @@ -0,0 +1,194 @@ +/*- + * Broadcom NetXtreme-C/E network driver. + * + * Copyright (c) 2024 Broadcom, All Rights Reserved. + * The term Broadcom refers to Broadcom Limited and/or its subsidiaries + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <linux/device.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/types.h> +#include <linux/list.h> +#include <linux/delay.h> + +#include "bnxt_auxbus_compat.h" + +static struct list_head bnxt_aux_bus_dev_list = LINUX_LIST_HEAD_INIT(bnxt_aux_bus_dev_list); +static struct list_head bnxt_aux_bus_drv_list = LINUX_LIST_HEAD_INIT(bnxt_aux_bus_drv_list); +static DEFINE_MUTEX(bnxt_auxbus_lock); + +static const struct auxiliary_device_id *auxiliary_match_id(const struct auxiliary_device_id *id, + const struct auxiliary_device *auxdev) +{ + for (; id->name[0]; id++) { + const char *p = strrchr(dev_name(&auxdev->dev), '.'); + int match_size; + + if (!p) + continue; + match_size = p - dev_name(&auxdev->dev); + + if (strlen(id->name) == match_size && + !strncmp(dev_name(&auxdev->dev), id->name, match_size)) + return id; + } + return NULL; +} + +int auxiliary_device_init(struct auxiliary_device *auxdev) +{ + struct device *dev = &auxdev->dev; + char *modname = KBUILD_MODNAME; + int ret; + + if (!dev->parent) { + pr_err("auxiliary_device has a NULL dev->parent\n"); + return -EINVAL; + } + + if (!auxdev->name) { + pr_err("auxiliary_device has a NULL name\n"); + return -EINVAL; + } + + ret = dev_set_name(dev, "%s.%s.%d", modname, auxdev->name, auxdev->id); + if (ret) { + dev_err(dev, "auxiliary device dev_set_name failed: %d\n", ret); + return ret; + } + + return 0; +} + +int auxiliary_device_add(struct auxiliary_device *auxdev) +{ + const struct auxiliary_device_id *id; + struct auxiliary_driver *auxdrv = NULL; + bool found = true; + int ret = 0; + + mutex_lock(&bnxt_auxbus_lock); + list_for_each_entry(auxdrv, &bnxt_aux_bus_drv_list, list) { + if (auxdrv) { + msleep(2 * 1000); + + id = auxiliary_match_id(auxdrv->id_table, auxdev); + if (id) { + ret = auxdrv->probe(auxdev, id); + if (!ret) + auxdev->dev.driver = &auxdrv->driver; + else + found = false; + break; + } + } + } + + if (found) + list_add_tail(&auxdev->list, &bnxt_aux_bus_dev_list); + mutex_unlock(&bnxt_auxbus_lock); + + return ret; +} + +void auxiliary_device_uninit(struct auxiliary_device *auxdev) +{ + return; +} + +void auxiliary_device_delete(struct auxiliary_device *auxdev) +{ + struct auxiliary_driver *auxdrv; + + mutex_lock(&bnxt_auxbus_lock); + list_for_each_entry(auxdrv, &bnxt_aux_bus_drv_list, list) { + if (auxdev->dev.driver != &auxdrv->driver) + continue; + if (auxdrv->remove) + auxdrv->remove(auxdev); + auxdev->dev.driver = NULL; + } + list_del(&auxdev->list); + mutex_unlock(&bnxt_auxbus_lock); +} + +int auxiliary_driver_register(struct auxiliary_driver *auxdrv) +{ + const struct auxiliary_device_id *id; + struct auxiliary_device *auxdev; + int ret = 0; + + if (WARN_ON(!auxdrv->probe) || WARN_ON(!auxdrv->id_table)) + return -EINVAL; + + if (auxdrv->name) + auxdrv->driver.name = kasprintf(GFP_KERNEL, "%s.%s", KBUILD_MODNAME, + auxdrv->name); + else + auxdrv->driver.name = kasprintf(GFP_KERNEL, "%s", KBUILD_MODNAME); + if (!auxdrv->driver.name) + return -ENOMEM; + + mutex_lock(&bnxt_auxbus_lock); + list_for_each_entry(auxdev, &bnxt_aux_bus_dev_list, list) { + if (auxdev->dev.driver) + continue; + + id = auxiliary_match_id(auxdrv->id_table, auxdev); + if (id) { + ret = auxdrv->probe(auxdev, id); + if (ret) + continue; + auxdev->dev.driver = &auxdrv->driver; + } + } + list_add_tail(&auxdrv->list, &bnxt_aux_bus_drv_list); + mutex_unlock(&bnxt_auxbus_lock); + return 0; +} +EXPORT_SYMBOL(auxiliary_driver_register); + +void auxiliary_driver_unregister(struct auxiliary_driver *auxdrv) +{ + struct auxiliary_device *auxdev; + + /* PF auxiliary devices are added to the list first and then VF devices. + * If we remove PF aux device driver first, it causes failures while + * removing VF driver. + * We need to remove VF auxiliary drivers first, so walk backwards. + */ + mutex_lock(&bnxt_auxbus_lock); + list_for_each_entry_reverse(auxdev, &bnxt_aux_bus_dev_list, list) { + if (auxdev->dev.driver != &auxdrv->driver) + continue; + if (auxdrv->remove) + auxdrv->remove(auxdev); + auxdev->dev.driver = NULL; + } + kfree(auxdrv->driver.name); + list_del(&auxdrv->list); + mutex_unlock(&bnxt_auxbus_lock); +} +EXPORT_SYMBOL(auxiliary_driver_unregister); diff --git a/sys/dev/bnxt/bnxt_en/bnxt_auxbus_compat.h b/sys/dev/bnxt/bnxt_en/bnxt_auxbus_compat.h new file mode 100644 index 000000000000..1d844a67c928 --- /dev/null +++ b/sys/dev/bnxt/bnxt_en/bnxt_auxbus_compat.h @@ -0,0 +1,75 @@ +/*- + * Broadcom NetXtreme-C/E network driver. + * + * Copyright (c) 2024 Broadcom, All Rights Reserved. + * The term Broadcom refers to Broadcom Limited and/or its subsidiaries + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _BNXT_AUXILIARY_COMPAT_H_ +#define _BNXT_AUXILIARY_COMPAT_H_ + +#include <linux/device.h> +#include <linux/idr.h> + +#define KBUILD_MODNAME "if_bnxt" +#define AUXILIARY_NAME_SIZE 32 + +struct auxiliary_device_id { + char name[AUXILIARY_NAME_SIZE]; + uint64_t driver_data; +}; + +struct auxiliary_device { + struct device dev; + const char *name; + uint32_t id; + struct list_head list; +}; + +struct auxiliary_driver { + int (*probe)(struct auxiliary_device *auxdev, const struct auxiliary_device_id *id); + void (*remove)(struct auxiliary_device *auxdev); + const char *name; + struct device_driver driver; + const struct auxiliary_device_id *id_table; + struct list_head list; +}; + +int auxiliary_device_init(struct auxiliary_device *auxdev); +int auxiliary_device_add(struct auxiliary_device *auxdev); +void auxiliary_device_uninit(struct auxiliary_device *auxdev); +void auxiliary_device_delete(struct auxiliary_device *auxdev); +int auxiliary_driver_register(struct auxiliary_driver *auxdrv); +void auxiliary_driver_unregister(struct auxiliary_driver *auxdrv); + +static inline void *auxiliary_get_drvdata(struct auxiliary_device *auxdev) +{ + return dev_get_drvdata(&auxdev->dev); +} + +static inline void auxiliary_set_drvdata(struct auxiliary_device *auxdev, void *data) +{ + dev_set_drvdata(&auxdev->dev, data); +} +#endif /* _BNXT_AUXILIARY_COMPAT_H_ */ diff --git a/sys/dev/bnxt/bnxt_en/bnxt_hwrm.c b/sys/dev/bnxt/bnxt_en/bnxt_hwrm.c index 6bc56aeb69a0..07834aeca363 100644 --- a/sys/dev/bnxt/bnxt_en/bnxt_hwrm.c +++ b/sys/dev/bnxt/bnxt_en/bnxt_hwrm.c @@ -28,6 +28,7 @@ #include <sys/cdefs.h> #include <sys/endian.h> +#include <linux/pci.h> #include "bnxt.h" #include "bnxt_hwrm.h" @@ -122,6 +123,10 @@ _hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len) req->seq_id = htole16(softc->hwrm_cmd_seq++); memset(resp, 0, PAGE_SIZE); + if (BNXT_NO_FW_ACCESS(softc) && + (req->req_type != HWRM_FUNC_RESET && req->req_type != HWRM_VER_GET)) + return -EINVAL; + 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; @@ -313,6 +318,39 @@ qportcfg_exit: return rc; } +static int bnxt_alloc_all_ctx_pg_info(struct bnxt_softc *softc) +{ + struct bnxt_ctx_mem_info *ctx = softc->ctx_mem; + u16 type; + + for (type = 0; type < BNXT_CTX_MAX; type++) { + struct bnxt_ctx_mem_type *ctxm = &ctx->ctx_arr[type]; + int n = 1; + + if (!ctxm->max_entries || ctxm->pg_info) + continue; + + if (ctxm->instance_bmap) + n = hweight32(ctxm->instance_bmap); + ctxm->pg_info = kcalloc(n, sizeof(*ctxm->pg_info), GFP_KERNEL); + if (!ctxm->pg_info) + return -ENOMEM; + } + return 0; +} + +static void bnxt_init_ctx_initializer(struct bnxt_ctx_mem_type *ctxm, + u8 init_val, u8 init_offset, + bool init_mask_set) +{ + ctxm->init_value = init_val; + ctxm->init_offset = BNXT_CTX_INIT_INVALID_OFFSET; + if (init_mask_set) + ctxm->init_offset = init_offset * 4; + else + ctxm->init_value = 0; +} + int bnxt_hwrm_func_backing_store_qcaps(struct bnxt_softc *softc) { struct hwrm_func_backing_store_qcaps_input req = {0}; @@ -320,63 +358,110 @@ int bnxt_hwrm_func_backing_store_qcaps(struct bnxt_softc *softc) (void *)softc->hwrm_cmd_resp.idi_vaddr; int rc; - if (softc->hwrm_spec_code < 0x10902 || BNXT_VF(softc) || softc->ctx_mem) + if (softc->hwrm_spec_code < 0x10902 || softc->ctx_mem) + return 0; + + if (BNXT_VF(softc)) 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_type *ctxm; struct bnxt_ctx_mem_info *ctx; - int i; + u8 init_val, init_idx = 0; + u16 init_mask; - ctx = malloc(sizeof(*ctx), M_DEVBUF, M_NOWAIT | M_ZERO); + ctx = softc->ctx_mem; if (!ctx) { - rc = -ENOMEM; - goto ctx_err; + ctx = malloc(sizeof(*ctx), M_DEVBUF, M_NOWAIT | M_ZERO); + if (!ctx) { + rc = -ENOMEM; + goto ctx_err; + } + softc->ctx_mem = ctx; } - ctx_pg = malloc(sizeof(*ctx_pg) * (softc->rx_max_q + 1), - M_DEVBUF, M_NOWAIT | M_ZERO); - if (!ctx_pg) { - free(ctx, M_DEVBUF); - rc = -ENOMEM; - goto ctx_err; + init_val = resp->ctx_kind_initializer; + init_mask = le16_to_cpu(resp->ctx_init_mask); + + ctxm = &ctx->ctx_arr[BNXT_CTX_QP]; + ctxm->max_entries = le32_to_cpu(resp->qp_max_entries); + ctxm->qp_qp1_entries = le16_to_cpu(resp->qp_min_qp1_entries); + ctxm->qp_l2_entries = le16_to_cpu(resp->qp_max_l2_entries); + ctxm->entry_size = le16_to_cpu(resp->qp_entry_size); + bnxt_init_ctx_initializer(ctxm, init_val, resp->qp_init_offset, + (init_mask & (1 << init_idx++)) != 0); + + ctxm = &ctx->ctx_arr[BNXT_CTX_SRQ]; + ctxm->srq_l2_entries = le16_to_cpu(resp->srq_max_l2_entries); + ctxm->max_entries = le32_to_cpu(resp->srq_max_entries); + ctxm->entry_size = le16_to_cpu(resp->srq_entry_size); + bnxt_init_ctx_initializer(ctxm, init_val, resp->srq_init_offset, + (init_mask & (1 << init_idx++)) != 0); + + ctxm = &ctx->ctx_arr[BNXT_CTX_CQ]; + ctxm->cq_l2_entries = le16_to_cpu(resp->cq_max_l2_entries); + ctxm->max_entries = le32_to_cpu(resp->cq_max_entries); + ctxm->entry_size = le16_to_cpu(resp->cq_entry_size); + bnxt_init_ctx_initializer(ctxm, init_val, resp->cq_init_offset, + (init_mask & (1 << init_idx++)) != 0); + + ctxm = &ctx->ctx_arr[BNXT_CTX_VNIC]; + ctxm->vnic_entries = le32_to_cpu(resp->vnic_max_vnic_entries); + ctxm->max_entries = ctxm->vnic_entries + + le16_to_cpu(resp->vnic_max_ring_table_entries); + ctxm->entry_size = le16_to_cpu(resp->vnic_entry_size); + bnxt_init_ctx_initializer(ctxm, init_val, + resp->vnic_init_offset, + (init_mask & (1 << init_idx++)) != 0); + + ctxm = &ctx->ctx_arr[BNXT_CTX_STAT]; + ctxm->max_entries = le32_to_cpu(resp->stat_max_entries); + ctxm->entry_size = le16_to_cpu(resp->stat_entry_size); + bnxt_init_ctx_initializer(ctxm, init_val, + resp->stat_init_offset, + (init_mask & (1 << init_idx++)) != 0); + + ctxm = &ctx->ctx_arr[BNXT_CTX_STQM]; + ctxm->entry_size = le16_to_cpu(resp->tqm_entry_size); + ctxm->min_entries = le32_to_cpu(resp->tqm_min_entries_per_ring); + ctxm->max_entries = le32_to_cpu(resp->tqm_max_entries_per_ring); + ctxm->entry_multiple = resp->tqm_entries_multiple; + if (!ctxm->entry_multiple) + ctxm->entry_multiple = 1; + + memcpy(&ctx->ctx_arr[BNXT_CTX_FTQM], ctxm, sizeof(*ctxm)); + + ctxm = &ctx->ctx_arr[BNXT_CTX_MRAV]; + ctxm->max_entries = le32_to_cpu(resp->mrav_max_entries); + ctxm->entry_size = le16_to_cpu(resp->mrav_entry_size); + ctxm->mrav_num_entries_units = + le16_to_cpu(resp->mrav_num_entries_units); + bnxt_init_ctx_initializer(ctxm, init_val, + resp->mrav_init_offset, + (init_mask & (1 << init_idx++)) != 0); + + ctxm = &ctx->ctx_arr[BNXT_CTX_TIM]; + ctxm->entry_size = le16_to_cpu(resp->tim_entry_size); + ctxm->max_entries = le32_to_cpu(resp->tim_max_entries); + + ctx->tqm_fp_rings_count = resp->tqm_fp_rings_count; + if (!ctx->tqm_fp_rings_count) + ctx->tqm_fp_rings_count = softc->tx_max_q; + else if (ctx->tqm_fp_rings_count > BNXT_MAX_TQM_FP_LEGACY_RINGS) + ctx->tqm_fp_rings_count = BNXT_MAX_TQM_FP_LEGACY_RINGS; + if (ctx->tqm_fp_rings_count == BNXT_MAX_TQM_FP_LEGACY_RINGS && + softc->hwrm_max_ext_req_len >= BNXT_BACKING_STORE_CFG_LEN) { + ctx->tqm_fp_rings_count += resp->tqm_fp_rings_count_ext; + if (ctx->tqm_fp_rings_count > BNXT_MAX_TQM_FP_RINGS) + ctx->tqm_fp_rings_count = BNXT_MAX_TQM_FP_RINGS; } - for (i = 0; i < softc->rx_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; + ctxm = &ctx->ctx_arr[BNXT_CTX_FTQM]; + memcpy(ctxm, &ctx->ctx_arr[BNXT_CTX_STQM], sizeof(*ctxm)); + ctxm->instance_bmap = (1 << ctx->tqm_fp_rings_count) - 1; + + rc = bnxt_alloc_all_ctx_pg_info(softc); } else { rc = 0; } @@ -419,150 +504,213 @@ 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, req_len = sizeof(req); - uint64_t *pg_dir; - uint8_t *pg_attr; - int i, rc; - uint32_t ena; + struct bnxt_ctx_mem_type *ctxm; + u32 req_len = sizeof(req); + __le32 *num_entries; + u32 ena, flags = 0; + __le64 *pg_dir; + u8 *pg_attr; + int i; if (!ctx) return 0; + if (req_len > softc->hwrm_max_ext_req_len) + req_len = BNXT_BACKING_STORE_CFG_LEGACY_LEN; + 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); + ctxm = &ctx->ctx_arr[BNXT_CTX_QP]; + ctx_pg = ctxm->pg_info; + req.qp_num_entries = cpu_to_le32(ctx_pg->entries); + req.qp_num_qp1_entries = cpu_to_le16(ctxm->qp_qp1_entries); + req.qp_num_l2_entries = cpu_to_le16(ctxm->qp_l2_entries); + req.qp_entry_size = cpu_to_le16(ctxm->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); + ctxm = &ctx->ctx_arr[BNXT_CTX_SRQ]; + ctx_pg = ctxm->pg_info; + req.srq_num_entries = cpu_to_le32(ctx_pg->entries); + req.srq_num_l2_entries = cpu_to_le16(ctxm->srq_l2_entries); + req.srq_entry_size = cpu_to_le16(ctxm->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, + ctxm = &ctx->ctx_arr[BNXT_CTX_CQ]; + ctx_pg = ctxm->pg_info; + req.cq_num_entries = cpu_to_le32(ctx_pg->entries); + req.cq_num_l2_entries = cpu_to_le16(ctxm->cq_l2_entries); + req.cq_entry_size = cpu_to_le16(ctxm->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); + ctxm = &ctx->ctx_arr[BNXT_CTX_MRAV]; + ctx_pg = ctxm->pg_info; + req.mrav_num_entries = cpu_to_le32(ctx_pg->entries); + if (ctxm->mrav_num_entries_units) + flags |= + HWRM_FUNC_BACKING_STORE_CFG_INPUT_FLAGS_MRAV_RESERVATION_SPLIT; + req.mrav_entry_size = cpu_to_le16(ctxm->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); *** 2040 LINES SKIPPED ***